uboot的驱动代码:
/*
* drivers/video/sunxi/disp2/disp/lcd/K080_IM2HYL802R_800X1280.c
*
* Copyright (c) 2007-2018 Allwinnertech Co., Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "K080_IM2HYL802R_800X1280.h"
//#include <mach/sys_config.h>
#include "panels.h"
/*
&lcd0 {
lcd_used = <1>;
status = "okay";
lcd_driver_name = "K080_IM2HYL802R_800X1280";
lcd_backlight = <50>;
lcd_if = <4>;
lcd_x = <800>;
lcd_y = <1280>;
lcd_width = <135>;
lcd_height = <216>;
lcd_dclk_freq = <75>;
lcd_pwm_used = <1>;
lcd_pwm_ch = <0>;
lcd_pwm_freq = <50000>;
lcd_pwm_pol = <1>;
lcd_pwm_max_limit = <255>;
lcd_hbp = <88>;
lcd_ht = <960>;
lcd_hspw = <4>;
lcd_vbp = <12>;
lcd_vt = <1300>;
lcd_vspw = <4>;
lcd_frm = <0>;
lcd_gamma_en = <0>;
lcd_bright_curve_en = <0>;
lcd_cmap_en = <0>;
deu_mode = <0>;
lcdgamma4iep = <22>;
smart_color = <90>;
lcd_dsi_if = <0>;
lcd_dsi_lane = <4>;
lcd_dsi_format = <0>;
lcd_dsi_te = <0>;
lcd_dsi_eotp = <0>;
lcd_pin_power = "dcdc1";
lcd_pin_power1 = "eldo3";
lcd_power = "eldo3";
lcd_power1 = "dcdc1";
lcd_power2 = "dc1sw";
lcd_gpio_1 = <&pio PD 22 1 0 3 1>;
pinctrl-0 = <&dsi4lane_pins_a>;
pinctrl-1 = <&dsi4lane_pins_b>;
lcd_bl_en = <&pio PB 8 1 0 3 1>;
lcd_bl_0_percent = <15>;
lcd_bl_100_percent = <100>;
};
*/
extern s32 bsp_disp_get_panel_info(u32 screen_id, disp_panel_para *info);
static void LCD_power_on(u32 sel);
static void LCD_power_off(u32 sel);
static void LCD_bl_open(u32 sel);
static void LCD_bl_close(u32 sel);
//static void LCD_panel_try_switch(u32 sel);
static void LCD_panel_init(u32 sel);
static void LCD_panel_exit(u32 sel);
//static u8 const mipi_dcs_pixel_format[4] = {0x77,0x66,0x66,0x55};
#define panel_reset(val) sunxi_lcd_gpio_set_value(sel, 1, val)
#define power_en(val) sunxi_lcd_gpio_set_value(sel, 0, val)
static void LCD_cfg_panel_info(panel_extend_para *info)
{
u32 i = 0, j = 0;
u32 items;
u8 lcd_gamma_tbl[][2] = {
//{input value, corrected value}
{0, 0},
{15, 15},
{30, 30},
{45, 45},
{60, 60},
{75, 75},
{90, 90},
{105, 105},
{120, 120},
{135, 135},
{150, 150},
{165, 165},
{180, 180},
{195, 195},
{210, 210},
{225, 225},
{240, 240},
{255, 255},
};
u32 lcd_cmap_tbl[2][3][4] = {
{
{LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
{LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
{LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
},
{
{LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
{LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
{LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
},
};
items = sizeof(lcd_gamma_tbl) / 2;
for (i = 0; i < items - 1; i++) {
u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
for (j = 0; j < num; j++) {
u32 value = 0;
value = lcd_gamma_tbl[i][1] + ((lcd_gamma_tbl[i + 1][1] - lcd_gamma_tbl[i][1]) * j) / num;
info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] = (value << 16) + (value << 8) + value;
}
}
info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items - 1][1] << 16) + (lcd_gamma_tbl[items - 1][1] << 8) + lcd_gamma_tbl[items - 1][1];
memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
}
static s32 LCD_open_flow(u32 sel)
{
pr_info("[LCD] %s: screen %u\n", __func__, sel);
LCD_OPEN_FUNC(sel, LCD_power_on, 100); //open lcd power, and delay 100ms
LCD_OPEN_FUNC(sel, LCD_panel_init, 200); //open lcd power, than delay 200ms
LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 50); //open lcd controller, and delay 50ms
LCD_OPEN_FUNC(sel, LCD_bl_open, 0); //open lcd backlight, and delay 0ms
return 0;
}
static s32 LCD_close_flow(u32 sel)
{
pr_info("[LCD] %s: screen %u\n", __func__, sel);
LCD_CLOSE_FUNC(sel, LCD_bl_close, 200); //close lcd backlight, and delay 0ms
LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 20); //close lcd controller, and delay 0ms
LCD_CLOSE_FUNC(sel, LCD_panel_exit, 10); //open lcd power, than delay 200ms
LCD_CLOSE_FUNC(sel, LCD_power_off, 500); //close lcd power, and delay 500ms
return 0;
}
static void LCD_power_on(u32 sel)
{
pr_info("[LCD] %s: start, screen %u\n", __func__, sel);
// 1. 复位引脚拉低(复位触发)
panel_reset(0);
sunxi_lcd_delay_ms(20);
// 2. 电源开启(严格按联发科顺序:3.3V → 1.8V → AVDD)
sunxi_lcd_power_enable(sel, 0);
sunxi_lcd_delay_ms(20);
sunxi_lcd_power_enable(sel, 1);
sunxi_lcd_delay_ms(10);
sunxi_lcd_power_enable(sel, 2);
sunxi_lcd_delay_ms(5);
// 3. 电源使能GPIO置高
power_en(1);
sunxi_lcd_delay_ms(10);
// 4. 复位引脚拉高(释放复位)
panel_reset(1);
sunxi_lcd_delay_ms(50);
sunxi_lcd_pin_cfg(sel, 1);
pr_info("[LCD] %s: finish, screen %u\n", __func__, sel);
}
static void LCD_power_off(u32 sel)
{
pr_info("[LCD] %s: start, screen %u\n", __func__, sel);
sunxi_lcd_pin_cfg(sel, 0);
power_en(0);
sunxi_lcd_delay_ms(20);
panel_reset(0);
sunxi_lcd_delay_ms(5);
// 电源关闭顺序:反向关闭(AVDD → 1.8V → 3.3V),匹配上电顺序
sunxi_lcd_power_disable(sel, 2);
sunxi_lcd_delay_ms(5);
sunxi_lcd_power_disable(sel, 1);
sunxi_lcd_delay_ms(5);
sunxi_lcd_power_disable(sel, 0);
pr_info("[LCD] %s: finish, screen %u\n", __func__, sel);
}
static void LCD_bl_open(u32 sel)
{
pr_info("[LCD] %s: screen %u\n", __func__, sel);
sunxi_lcd_pwm_enable(sel);
sunxi_lcd_delay_ms(50);
sunxi_lcd_backlight_enable(sel);//config lcd_bl_en pin to open lcd backlight
}
static void LCD_bl_close(u32 sel)
{
pr_info("[LCD] %s: screen %u\n", __func__, sel);
sunxi_lcd_backlight_disable(sel);//config lcd_bl_en pin to close lcd backlight
sunxi_lcd_delay_ms(20);
sunxi_lcd_pwm_disable(sel);
}
#define REGFLAG_DELAY 0XFE
#define REGFLAG_END_OF_TABLE 0xFD // END OF REGISTERS MARKER
struct LCM_setting_table {
u8 cmd;
u32 count;
u8 para_list[64];
};
/*add panel initialization below*/
static struct LCM_setting_table lcm_initialization_setting[] = {
{REGFLAG_DELAY, REGFLAG_DELAY, {120}}, /* 120 ms after reset */
/* Page-1 (0x3001) */
{0xFF, 1, {0x30}},
{0xFF, 1, {0x52}},
{0xFF, 1, {0x01}},
{0xE3, 1, {0x04}},
{0x08, 1, {0x0E}},
{0x25, 1, {0x10}},
{0x28, 1, {0x5F}},
{0x2C, 1, {0x22}},
{0x30, 1, {0x58}},
{0x45, 1, {0x91}},
{0x37, 1, {0x9C}},
{0x38, 1, {0xA7}},
{0x39, 1, {0x27}},
{0x44, 1, {0x00}},
{0x49, 1, {0x1C}},
{0x59, 1, {0xFE}},
{0x5C, 1, {0x00}},
{0x91, 1, {0x77}},
{0x92, 1, {0x77}},
{0xA0, 1, {0x55}},
{0xA1, 1, {0x50}},
{0xA3, 1, {0x58}},
{0xA4, 1, {0x9C}},
{0xA7, 1, {0x02}},
{0xA8, 1, {0x01}},
{0xA9, 1, {0x01}},
{0xAA, 1, {0xFC}},
{0xAB, 1, {0x28}},
{0xAC, 1, {0x06}},
{0xAD, 1, {0x06}},
{0xAE, 1, {0x06}},
{0xAF, 1, {0x03}},
{0xB0, 1, {0x08}},
{0xB1, 1, {0x26}},
{0xB2, 1, {0x28}},
{0xB3, 1, {0x28}},
{0xB4, 1, {0x03}},
{0xB5, 1, {0x08}},
{0xB6, 1, {0x26}},
{0xB7, 1, {0x08}},
{0xB8, 1, {0x26}},
{0xC0, 1, {0x00}},
{0xC1, 1, {0x00}},
{0xC3, 1, {0x0F}},
/* Page-2 (0x3002) */
{0xFF, 1, {0x30}},
{0xFF, 1, {0x52}},
{0xFF, 1, {0x02}},
{0xB0, 1, {0x00}},
{0xB1, 1, {0x05}},
{0xB2, 1, {0x02}},
{0xB3, 1, {0x24}},
{0xB4, 1, {0x25}},
{0xB5, 1, {0x30}},
{0xB6, 1, {0x0C}},
{0xB7, 1, {0x27}},
{0xB8, 1, {0x0F}},
{0xB9, 1, {0x05}},
{0xBA, 1, {0x11}},
{0xBB, 1, {0x10}},
{0xBC, 1, {0x11}},
{0xBD, 1, {0x12}},
{0xBE, 1, {0x17}},
{0xBF, 1, {0x0C}},
{0xC0, 1, {0x14}},
{0xC1, 1, {0x0A}},
{0xD0, 1, {0x08}},
{0xD1, 1, {0x0F}},
{0xD2, 1, {0x09}},
{0xD3, 1, {0x35}},
{0xD4, 1, {0x38}},
{0xD5, 1, {0x3D}},
{0xD6, 1, {0x1B}},
{0xD7, 1, {0x3B}},
{0xD8, 1, {0x0F}},
{0xD9, 1, {0x05}},
{0xDA, 1, {0x11}},
{0xDB, 1, {0x10}},
{0xDC, 1, {0x11}},
{0xDD, 1, {0x14}},
{0xDE, 1, {0x19}},
{0xDF, 1, {0x11}},
{0xE0, 1, {0x19}},
{0xE1, 1, {0x09}},
/* Page-3 (0x3003) */
{0xFF, 1, {0x30}},
{0xFF, 1, {0x52}},
{0xFF, 1, {0x03}},
{0x08, 1, {0x8B}},
{0x09, 1, {0x8A}},
{0x0A, 1, {0x89}},
{0x0B, 1, {0x88}},
{0x34, 1, {0x61}},
{0x35, 1, {0xD4}},
{0x36, 1, {0x24}},
{0x37, 1, {0x03}},
{0x40, 1, {0x8B}},
{0x41, 1, {0x8A}},
{0x42, 1, {0x89}},
{0x43, 1, {0x88}},
{0x45, 1, {0x01}},
{0x46, 1, {0x02}},
{0x48, 1, {0x03}},
{0x49, 1, {0x04}},
{0x50, 1, {0x87}},
{0x51, 1, {0x86}},
{0x52, 1, {0x85}},
{0x53, 1, {0x84}},
{0x55, 1, {0x05}},
{0x56, 1, {0x06}},
{0x58, 1, {0x07}},
{0x59, 1, {0x08}},
{0x80, 1, {0x0F}},
{0x81, 1, {0x0E}},
{0x82, 1, {0x07}},
{0x83, 1, {0x06}},
{0x84, 1, {0x05}},
{0x85, 1, {0x04}},
{0x92, 1, {0x0E}},
{0x93, 1, {0x0F}},
{0x94, 1, {0x01}},
{0x95, 1, {0x00}},
{0x96, 1, {0x0F}},
{0x97, 1, {0x0E}},
{0x98, 1, {0x07}},
{0x99, 1, {0x06}},
{0x9A, 1, {0x05}},
{0x9B, 1, {0x04}},
{0xA8, 1, {0x0E}},
{0xA9, 1, {0x0F}},
{0xAA, 1, {0x01}},
{0xAB, 1, {0x00}},
{0xE0, 1, {0x02}},
{0xE1, 1, {0x52}},
/* Page-0 (0x3000) */
{0xFF, 1, {0x30}},
{0xFF, 1, {0x52}},
{0xFF, 1, {0x00}},
{0x35, 1, {0x00}},
{0x36, 1, {0x02}},
{0x53, 1, {0x2C}},
/* Display ON sequence */
//SLP OUT
{0x11, 0, {0x00} }, // SLPOUT
{REGFLAG_DELAY, REGFLAG_DELAY, {120} },
//DISP ON
{0x29, 0, {0x00} }, // DSPON
{REGFLAG_DELAY, REGFLAG_DELAY, {100} },
{REGFLAG_END_OF_TABLE, REGFLAG_END_OF_TABLE, {} }
};
/*static void LCD_panel_try_switch(u32 sel)
{
u8 result[16] = {0};
u32 num = 0;
sunxi_lcd_delay_ms(100);
sunxi_lcd_dsi_dcs_read(sel, 0x04, result, &num);
printf("get lcd id 0x%x\n", result[0]);
if (result[0] == 0x93) {
LCD_power_off(sel);
sunxi_lcd_switch_compat_panel(sel, 1);
return;
}
}*/
static void LCD_panel_init(u32 sel)
{
__u32 i;
pr_info("[LCD] %s: screen %u - start init table\n", __func__, sel);
sunxi_lcd_dsi_clk_enable(sel);
sunxi_lcd_delay_ms(20);
pr_info("[LCD] %s: sending SW reset\n", __func__);
sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_SOFT_RESET);
//sunxi_lcd_delay_ms(10);
sunxi_lcd_delay_ms(120);
pr_info("[LCD] %s: entering init table loop\n", __func__);
for (i = 0; ; i++) {
if (lcm_initialization_setting[i].count == REGFLAG_END_OF_TABLE)
break;
else if (lcm_initialization_setting[i].count == REGFLAG_DELAY)
sunxi_lcd_delay_ms(lcm_initialization_setting[i].para_list[0]);
#ifdef SUPPORT_DSI
else
dsi_dcs_wr(sel, lcm_initialization_setting[i].cmd, lcm_initialization_setting[i].para_list, lcm_initialization_setting[i].count);
#endif
//break;
}
pr_info("[LCD] %s: screen %u - init table done\n", __func__, sel);
return;
}
static void LCD_panel_exit(u32 sel)
{
pr_info("[LCD] %s: screen %u\n", __func__, sel);
sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_SET_DISPLAY_OFF);
sunxi_lcd_delay_ms(20);
sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_ENTER_SLEEP_MODE);
sunxi_lcd_delay_ms(80);
return ;
}
//sel: 0:lcd0; 1:lcd1
static s32 LCD_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
{
return 0;
}
//sel: 0:lcd0; 1:lcd1
/*static s32 LCD_set_bright(u32 sel, u32 bright)
{
sunxi_lcd_dsi_dcs_write_1para(sel,0x51,bright);
return 0;
}*/
__lcd_panel_t K080_IM2HYL802R_800X1280_mipi_panel = {
/* panel driver name, must mach the name of lcd_drv_name in sys_config.fex */
.name = "K080_IM2HYL802R_800X1280",
.func = {
.cfg_panel_info = LCD_cfg_panel_info,
.cfg_open_flow = LCD_open_flow,
.cfg_close_flow = LCD_close_flow,
.lcd_user_defined_func = LCD_user_defined_func,
//.set_bright = LCD_set_bright,
},
};
设备树:
disp: disp@06000000 {
disp_init_enable = <1>;
disp_mode = <0>;
screen0_output_type = <1>;
screen0_output_mode = <4>;
screen1_output_type = <1>;
screen1_output_mode = <4>;
screen1_output_format = <0>;
screen1_output_bits = <0>;
screen1_output_eotf = <4>;
screen1_output_cs = <257>;
screen1_output_dvi_hdmi = <2>;
screen1_output_range = <2>;
screen1_output_scan = <0>;
screen1_output_aspect_ratio = <8>;
dev0_output_type = <1>;
dev0_output_mode = <4>;
dev0_screen_id = <0>;
dev0_do_hpd = <0>;
dev1_output_type = <4>;
dev1_output_mode = <10>;
dev1_screen_id = <1>;
dev1_do_hpd = <1>;
def_output_dev = <0>;
hdmi_mode_check = <1>;
fb0_format = <0>;
fb0_width = <720>;
fb0_height = <1280>;
fb1_format = <0>;
fb1_width = <0>;
fb1_height = <0>;
chn_cfg_mode = <1>;
disp_para_zone = <1>;
/*VCC-LCD*/
cldo4-supply = <®_cldo4>;
/*VCC-LVDS-1.8V*/
cldo1-supply = <®_cldo1>;
/*VCC-DSI*/
/*VCC-PD-3.3V*/
cldo3-supply = <®_cldo3>;
};
/*----------------------------------------------------------------------------------
;lcd0 configuration
;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds; 4:dsi; 5:edp; 6:extend dsi
;lcd_hv_if 0:Parallel RGB; 8:Serial RGB; 10:Dummy RGB; 11: RGB Dummy;12:CCIR656
;lcd_hv_clk_phase 0:0 degree;1:90 degree;2:180 degree;3:270 degree
;lcd_hv_sync_polarity 0:vs low,hs low; 1:vs high,hslow; 2:vs low,hs high; 3:vs high,hs high
;lcd_hv_syuv_seq 0:YUYV; 1:YVYU; 2:UYVY; 3:VYUY
;lcd_cpu_if 0:18bit/1 cycle parallel(RGB666); 4:16bit/1cycle parallel (RGB565)
; 6:18bit/3 cycle parallel(RGB666); 7:16bit/2cycle parallel (RGB565)
;lcd_cpu_te 0:frame auto trigger; 1:frame triggered by te rising edge; 2:frame triggered by te falling edge;
;lcd_dsi_if 0:video mode; 1: Command mode; 2:video burst mode
;lcd_dsi_te 0:frame auto trigger; 1:frame triggered by te rising edge; 2:frame triggered by te falling edge;
;lcd_x: lcd horizontal resolution
;lcd_y: lcd vertical resolution
;lcd_width: width of lcd in mm
;lcd_height: height of lcd in mm
;lcd_dclk_freq: in MHZ unit
;lcd_pwm_freq: in HZ unit
;lcd_pwm_pol: lcd backlight PWM polarity
;lcd_pwm_max_limit lcd backlight PWM max limit(<=255)
;lcd_hbp: hsync back porch(pixel) + hsync plus width(pixel);
;lcd_ht: hsync total cycle(pixel)
;lcd_vbp: vsync back porch(line) + vysnc plus width(line)
;lcd_vt: vysnc total cycle(line)
;lcd_hspw: hsync plus width(pixel)
;lcd_vspw: vysnc plus width(pixel)
;lcd_lvds_if: 0:single link; 1:dual link
;lcd_lvds_colordepth: 0:8bit; 1:6bit
;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode
;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither
;lcd_io_phase: 0:noraml; 1:intert phase(0~3bit: vsync phase; 4~7bit:hsync phase;
; 8~11bit:dclk phase; 12~15bit:de phase)
;lcd_gamma_en lcd gamma correction enable
;lcd_bright_curve_en lcd bright curve correction enable
;lcd_cmap_en lcd color map function enable
;deu_mode 0:smoll lcd screen; 1:large lcd screen(larger than 10inch)
;lcdgamma4iep: Smart Backlight parameter, lcd gamma vale * 10;
; decrease it while lcd is not bright enough; increase while lcd is too bright
;smart_color 90:normal lcd screen 65:retina lcd screen(9.7inch)
;Pin setting for special function ie.LVDS, RGB data or vsync
; name(donot care) = port:PD12<pin function><pull up or pull down><drive ability><output level>
;Pin setting for gpio:
; lcd_gpio_X = port:PD12<pin function><pull up or pull down><drive ability><output level>
;Pin setting for backlight enable pin
; lcd_bl_en = port:PD12<pin function><pull up or pull down><drive ability><output level>
;fsync setting, pulse to csi
;lcd_fsync_en (0:disable fsync,1:enable)
;lcd_fsync_act_time (active time of fsync, unit:pixel)
;lcd_fsync_dis_time (disactive time of fsync, unit:pixel)
;lcd_fsync_pol (0:positive;1:negative)
;gpio config: <&pio for cpu or &r_pio for cpus, port, port num, pio function,
pull up or pull down(default 0), driver level(default 1), data>
;For dual link lvds: use lvds2link_pins_a and lvds2link_pins_b instead
;For rgb24: use rgb24_pins_a and rgb24_pins_b instead
;For lvds1: use lvds1_pins_a and lvds1_pins_b instead
;For lvds0: use lvds0_pins_a and lvds0_pins_b instead
;----------------------------------------------------------------------------------*/
lcd0: lcd0@01c0c000 {
lcd_used = <1>;
lcd_driver_name = "K080_IM2HYL802R_800X1280";
lcd_backlight = <50>;
lcd_if = <4>;
lcd_x = <720>;
lcd_y = <1280>;
lcd_width = <150>;
lcd_height = <36>;
lcd_dclk_freq = <58>;
lcd_pwm_used = <1>;
lcd_pwm_ch = <0>;
lcd_pwm_freq = <50000>;
lcd_pwm_pol = <1>;
lcd_pwm_max_limit = <255>;
lcd_hbp = <30>;
lcd_ht = <770>;
lcd_hspw = <6>;
lcd_vbp = <16>;
lcd_vt = <1311>;
lcd_vspw = <4>;
lcd_frm = <0>;
lcd_gamma_en = <0>;
lcd_bright_curve_en = <0>;
lcd_cmap_en = <0>;
deu_mode = <0>;
lcdgamma4iep = <22>;
smart_color = <90>;
lcd_dsi_if = <0>;
lcd_dsi_lane = <4>;
lcd_dsi_format = <0>;
lcd_dsi_te = <0>;
lcd_dsi_eotp = <0>;
lcd_pin_power = "cldo3"; /* VCC-PD (3.3 V) */
lcd_power1 = "cldo1"; /* VCC-LVDS (1.8 V) */
lcd_power2 = "cldo4"; /* VCC-LCD (3.3 V) */
lcd_gpio_1 = <&pio PD 22 1 0 3 1>; /* RESET */
pinctrl-0 = <&dsi4lane_pins_a>;
pinctrl-1 = <&dsi4lane_pins_b>;
lcd_bl_en = <&pio PD 23 1 1 0 3 1>; /* backlight */
lcd_bl_0_percent = <15>;
lcd_bl_100_percent = <100>;
};
参考mtk的驱动参数:
/*
* Copyright (C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
#ifdef BUILD_LK
#include <string.h>
#include <platform/mt_gpio.h>
#include <platform/mt_pmic.h>
#include <platform/sync_write.h>
#include <platform/ddp_hal.h>
#else
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_gpio.h>
#include <asm-generic/gpio.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#endif
#endif
#include "lcm_drv.h"
#ifndef BUILD_LK
extern int inettek_gpio_set(const char *name);
extern int lcm_vgp_supply_enable(void);
extern int lcm_vgp_supply_disable(void);
extern int lcm_get_vgp_supply(struct device *dev);
#endif
#ifdef BUILD_LK
#define LCD_2V8_EN (38 | 0x80000000)
#define LCD_RST_PIN (66 | 0x80000000)
#define LCD_3V3_RST_PIN (70 | 0x80000000)
#define LCD_AVDD_EN (20 | 0x80000000) // VSN +VSP
#define LCD_GAMA_EN (0 | 0x80000000) // AVDD + VGL + VGH
#endif
/* --------------------------------------------------------------- */
/* Local Constants */
/* --------------------------------------------------------------- */
#define FRAME_WIDTH (720)
#define FRAME_HEIGHT (1280)
#define GPIO_OUT_ONE 1
#define GPIO_OUT_ZERO 0
#define REGFLAG_DELAY 0xFE
#define REGFLAG_END_OF_TABLE 0x00
#define LCM_ID_NV3052 (0x3052)
/* --------------------------------------------------------------- */
/* Local Variables */
/* --------------------------------------------------------------- */
#ifndef BUILD_LK
static unsigned int GPIO_LCD_PWR;
static unsigned int GPIO_LCD_RST;
static unsigned int GPIO_3V3_LCD_RST;
static void lcm_request_gpio_control(struct device *dev)
{
GPIO_LCD_PWR = of_get_named_gpio(dev->of_node, "gpio_lcd_pwr", 0);
gpio_request(GPIO_LCD_PWR, "GPIO_LCD_PWR");
GPIO_LCD_RST = of_get_named_gpio(dev->of_node, "gpio_lcd_rst", 0);
gpio_request(GPIO_LCD_PWR, "GPIO_LCD_RST");
GPIO_3V3_LCD_RST = of_get_named_gpio(dev->of_node, "gpio_3v3_lcd_rst", 0);
gpio_request(GPIO_LCD_PWR, "GPIO_3V3_LCD_RST");
}
static int lcm_driver_probe(struct device *dev, void const *data)
{
lcm_request_gpio_control(dev);
lcm_get_vgp_supply(dev);
lcm_vgp_supply_enable();
return 0;
}
static const struct of_device_id lcm_platform_of_match[] = {
{
.compatible = "mickey,nv3052_bv055hdl_nb6",
.data = 0,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, platform_of_match);
static int lcm_platform_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
id = of_match_node(lcm_platform_of_match, pdev->dev.of_node);
if (!id)
return -ENODEV;
return lcm_driver_probe(&pdev->dev, id->data);
}
static struct platform_driver lcm_driver = {
.probe = lcm_platform_probe,
.driver = {
.name = "nv3052_bv055hdl_nb6",
.owner = THIS_MODULE,
.of_match_table = lcm_platform_of_match,
},
};
static int __init lcm_drv_init(void)
{
if (platform_driver_register(&lcm_driver)) {
pr_err("LCM: failed to register this driver!\n");
return -ENODEV;
}
return 0;
}
static void __exit lcm_drv_exit(void)
{
platform_driver_unregister(&lcm_driver);
}
late_initcall(lcm_drv_init);
module_exit(lcm_drv_exit);
MODULE_AUTHOR("mediatek");
MODULE_DESCRIPTION("LCM display subsystem driver");
MODULE_LICENSE("GPL");
#endif
extern void mdelay(unsigned long msec);
#ifdef BUILD_LK
static LCM_UTIL_FUNCS lcm_util = {
.set_reset_pin = NULL,
.udelay = NULL,
.mdelay = NULL,
};
#else
static LCM_UTIL_FUNCS lcm_util = { 0 };
#endif
#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
#define UDELAY(n) (lcm_util.udelay(n))
#define MDELAY(n) (lcm_util.mdelay(n))
/* --------------------------------------------------------------- */
/* Local Functions */
/* --------------------------------------------------------------- */
#define dsi_set_cmdq_V2(cmd, count, ppara, force_update) \
(lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update))
#define dsi_set_cmdq(pdata, queue_size, force_update) \
(lcm_util.dsi_set_cmdq(pdata, queue_size, force_update))
#define wrtie_cmd(cmd) \
(lcm_util.dsi_write_cmd(cmd))
#define write_regs(addr, pdata, byte_nums) \
(lcm_util.dsi_write_regs(addr, pdata, byte_nums))
#define read_reg \
(lcm_util.dsi_read_reg())
#define read_reg_v2(cmd, buffer, buffer_size) \
(lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size))
#ifdef BUILD_LK
static void pmic_vgp2_enable(bool en, int vol_mv)
{
unsigned int val;
if (!en)
mt6392_upmu_set_rg_vgp2_en(0x0);
else {
switch (vol_mv) {
case 1200:
val = 0x00;
break;
case 1300:
val = 0x01;
break;
case 1500:
val = 0x02;
break;
case 1800:
val = 0x03;
break;
case 2000:
val = 0x04;
break;
case 2800:
val = 0x05;
break;
case 3000:
val = 0x06;
break;
case 3300:
val = 0x07;
break;
default:
val = 0x05;
break;
}
//VGP2 0x00=1.2V, 0x01=1.3V, 0x02=1.5V, 0x03=1.8V, 0x04=2.0V, 0x05=2.8V, 0x06=3.0V, 0x07=3.3V
mt6392_upmu_set_rg_vgp2_vosel(val);
mt6392_upmu_set_rg_vgp2_en(0x1);
}
}
#endif
/* --------------------------------------------------------------------------- */
/* Local Functions */
/* --------------------------------------------------------------------------- */
#ifdef BUILD_LK
static void lcm_set_gpio_output(unsigned int GPIO, unsigned int output)
{
mt_set_gpio_mode(GPIO, GPIO_MODE_00);
mt_set_gpio_dir(GPIO, GPIO_DIR_OUT);
mt_set_gpio_out(GPIO, output);
}
#endif
struct LCM_setting_table {
unsigned char cmd;
unsigned char count;
unsigned char para_list[4];
};
//update initial param for IC boe_nt71391_dsi_vdo 0.01
static struct LCM_setting_table lcm_initialization_setting[] =
{
//----------NV305F+BOE5.5(BV055HDL-NB6) Initial------------------
{REGFLAG_DELAY, 120, {}},
{0xFF,0x01,{0x30}},
{0xFF,0x01,{0x52}},
{0xFF,0x01,{0x01}},
{0xE3,0x01,{0x04}},
{0x08,0x01,{0x0e}},
{0x25,0x01,{0x10}},
{0x28,0x01,{0x5F}},
{0x2C,0x01,{0x22}},
{0x30,0x01,{0x58}},
{0x45,0x01,{0x91}},
{0x37,0x01,{0x9C}},
{0x38,0x01,{0xA7}},
{0x39,0x01,{0x27}},
{0x44,0x01,{0x00}},
{0x49,0x01,{0x1C}},
{0x59,0x01,{0xFE}},
{0x5C,0x01,{0x00}},
{0x91,0x01,{0x77}},
{0x92,0x01,{0x77}},
{0xA0,0x01,{0x55}},
{0xA1,0x01,{0x50}},
{0xA3,0x01,{0x58}},
{0xA4,0x01,{0x9C}},
{0xA7,0x01,{0x02}},
{0xA8,0x01,{0x01}},
{0xA9,0x01,{0x01}},
{0xAA,0x01,{0xFC}},
{0xAB,0x01,{0x28}},
{0xAC,0x01,{0x06}},
{0xAD,0x01,{0x06}},
{0xAE,0x01,{0x06}},
{0xAF,0x01,{0x03}},
{0xB0,0x01,{0x08}},
{0xB1,0x01,{0x26}},
{0xB2,0x01,{0x28}},
{0xB3,0x01,{0x28}},
{0xB4,0x01,{0x03}},
{0xB5,0x01,{0x08}},
{0xB6,0x01,{0x26}},
{0xB7,0x01,{0x08}},
{0xB8,0x01,{0x26}},
{0xc0,0x01,{0x00}},
{0xc1,0x01,{0x00}},
{0xc3,0x01,{0x0F}},
{0xFF,0x01,{0x30}},
{0xFF,0x01,{0x52}},
{0xFF,0x01,{0x02}},
{0xB0,0x01,{0x00}},
{0xB1,0x01,{0x05}},
{0xB2,0x01,{0x02}},
{0xB3,0x01,{0x24}},
{0xB4,0x01,{0x25}},
{0xB5,0x01,{0x30}},
{0xB6,0x01,{0x0C}},
{0xB7,0x01,{0x27}},
{0xB8,0x01,{0x0F}},
{0xB9,0x01,{0x05}},
{0xBA,0x01,{0x11}},
{0xBB,0x01,{0x10}},
{0xBC,0x01,{0x11}},
{0xBD,0x01,{0x12}},
{0xBE,0x01,{0x17}},
{0xBF,0x01,{0x0C}},
{0xC0,0x01,{0x14}},
{0xC1,0x01,{0x0A}},
{0xD0,0x01,{0x08}},
{0xD1,0x01,{0x0F}},
{0xD2,0x01,{0x09}},
{0xD3,0x01,{0x35}},
{0xD4,0x01,{0x38}},
{0xD5,0x01,{0x3D}},
{0xD6,0x01,{0x1B}},
{0xD7,0x01,{0x3B}},
{0xD8,0x01,{0x0F}},
{0xD9,0x01,{0x05}},
{0xDA,0x01,{0x11}},
{0xDB,0x01,{0x10}},
{0xDC,0x01,{0x11}},
{0xDD,0x01,{0x14}},
{0xDE,0x01,{0x19}},
{0xDF,0x01,{0x11}},
{0xE0,0x01,{0x19}},
{0xE1,0x01,{0x09}},
{0xFF,0x01,{0x30}},
{0xFF,0x01,{0x52}},
{0xFF,0x01,{0x03}},
{0x08,0x01,{0x8B}},
{0x09,0x01,{0x8A}},
{0x0A,0x01,{0x89}},
{0x0B,0x01,{0x88}},
{0x34,0x01,{0x61}},
{0x35,0x01,{0xD4}},
{0x36,0x01,{0x24}},
{0x37,0x01,{0x03}},
{0x40,0x01,{0x8B}},
{0x41,0x01,{0x8A}},
{0x42,0x01,{0x89}},
{0x43,0x01,{0x88}},
{0x45,0x01,{0x01}},
{0x46,0x01,{0x02}},
{0x48,0x01,{0x03}},
{0x49,0x01,{0x04}},
{0x50,0x01,{0x87}},
{0x51,0x01,{0x86}},
{0x52,0x01,{0x85}},
{0x53,0x01,{0x84}},
{0x55,0x01,{0x05}},
{0x56,0x01,{0x06}},
{0x58,0x01,{0x07}},
{0x59,0x01,{0x08}},
{0x80,0x01,{0x0F}},
{0x81,0x01,{0x0E}},
{0x82,0x01,{0x07}},
{0x83,0x01,{0x06}},
{0x84,0x01,{0x05}},
{0x85,0x01,{0x04}},
{0x92,0x01,{0x0E}},
{0x93,0x01,{0x0F}},
{0x94,0x01,{0x01}},
{0x95,0x01,{0x00}},
{0x96,0x01,{0x0F}},
{0x97,0x01,{0x0E}},
{0x98,0x01,{0x07}},
{0x99,0x01,{0x06}},
{0x9A,0x01,{0x05}},
{0x9B,0x01,{0x04}},
{0xA8,0x01,{0x0E}},
{0xA9,0x01,{0x0F}},
{0xAA,0x01,{0x01}},
{0xAB,0x01,{0x00}},
{0xE0,0x01,{0x02}},
{0xE1,0x01,{0x52}},
{0xFF,0x01,{0x30}},
{0xFF,0x01,{0x52}},
{0xFF,0x01,{0x00}},
{0x35,0x01,{0x00}},
{0x36,0x01,{0x02}},
{0x53,0x01,{0x2C}},
{0x11,0x01,{0x00}},
{REGFLAG_DELAY, 200, {}},
{0x29,0x01,{0x00}}, //Display ON
{REGFLAG_DELAY, 100, {}},
{REGFLAG_END_OF_TABLE, 0x00, {}},
};
static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update)
{
unsigned int i;
for(i = 0; i < count; i++) {
unsigned cmd;
cmd = table[i].cmd;
switch (cmd) {
case REGFLAG_DELAY :
MDELAY(table[i].count);
break;
case REGFLAG_END_OF_TABLE :
break;
default:
dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update);
//MDELAY(10);//soso add or it will fail to send register
}
}
}
/* --------------------------------------------------------------- */
/* LCM Driver Implementations */
/* --------------------------------------------------------------- */
#ifdef BUILD_LK
static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
{
memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
}
#else
static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
{
memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
}
#endif
static void lcm_get_params(LCM_PARAMS *params)
{
memset(params, 0, sizeof(LCM_PARAMS));
params->type = LCM_TYPE_DSI;
params->width = FRAME_WIDTH;
params->height = FRAME_HEIGHT;
params->dsi.mode = SYNC_EVENT_VDO_MODE;
params->dsi.LANE_NUM = LCM_FOUR_LANE;
params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
/* Highly depends on LCD driver capability. */
params->dsi.packet_size = 256;
/* Video mode setting */
params->dsi.intermediat_buffer_num = 0;
params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888;
params->dsi.word_count=FRAME_WIDTH*3;
params->dsi.vertical_sync_active = 2;
params->dsi.vertical_backporch = 14;
params->dsi.vertical_frontporch = 16;
params->dsi.vertical_active_line = FRAME_HEIGHT;
params->dsi.horizontal_sync_active = 2;
params->dsi.horizontal_backporch = 44;
params->dsi.horizontal_frontporch = 46;
params->dsi.horizontal_active_pixel = FRAME_WIDTH;
params->dsi.ssc_disable = 1; //0表示开展频,1表示关展频
params->dsi.ssc_range = 6; //6为展频幅度6%,此值可以修改
params->dsi.PLL_CLOCK = 205;
params->dsi.esd_check_enable = 1; //enable ESD check
params->dsi.customization_esd_check_enable = 1; //0 TE ESD CHECK 1 LCD REG CHECK
params->dsi.lcm_esd_check_table[0].cmd = 0x0F;//0X0A
params->dsi.lcm_esd_check_table[0].count = 1;
params->dsi.lcm_esd_check_table[0].para_list[0] = 0xC0;//0X9C
params->dsi.cont_clock = 0;
params->dsi.clk_lp_per_line_enable = 1;
}
static unsigned int lcm_compare_id(void);
static void lcm_reset(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
#ifdef BUILD_LK
lcm_set_gpio_output(LCD_RST_PIN, GPIO_OUT_ONE);
lcm_set_gpio_output(LCD_3V3_RST_PIN, GPIO_OUT_ONE);
MDELAY(20);
lcm_set_gpio_output(LCD_RST_PIN, GPIO_OUT_ZERO);
lcm_set_gpio_output(LCD_3V3_RST_PIN, GPIO_OUT_ZERO);
MDELAY(10);
lcm_set_gpio_output(LCD_RST_PIN, GPIO_OUT_ONE);
lcm_set_gpio_output(LCD_3V3_RST_PIN, GPIO_OUT_ONE);
MDELAY(50);
#else
inettek_gpio_set("lcm_rst_en1");
inettek_gpio_set("lcm_3v3_rst_en1");
MDELAY(20);
inettek_gpio_set("lcm_rst_en0");
inettek_gpio_set("lcm_3v3_rst_en0");
MDELAY(10);
inettek_gpio_set("lcm_rst_en1");
inettek_gpio_set("lcm_3v3_rst_en1");
MDELAY(20);
#endif
}
static void lcm_init(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
lcm_reset();
push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
}
static void lcm_resume(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
lcm_reset();
push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
}
static void lcm_init_power(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
#ifdef BUILD_LK
pmic_vgp2_enable(false, 1800); //VCC_LCD8_1V8
lcm_set_gpio_output(LCD_2V8_EN, GPIO_OUT_ONE); //VCC_LCD_3V3
MDELAY(20);
pmic_vgp2_enable(true, 1800); //VCC_LCD8_1V8
MDELAY(10);
lcm_set_gpio_output(LCD_AVDD_EN, GPIO_OUT_ONE);
lcm_set_gpio_output(LCD_GAMA_EN, GPIO_OUT_ZERO);
#else
inettek_gpio_set("lcm_vcc_en1");
inettek_gpio_set("lcm_avdd_en1");
inettek_gpio_set("lcm_gama_en0");
lcm_vgp_supply_enable();
#endif
}
static void lcm_resume_power(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
#ifdef BUILD_LK
lcm_set_gpio_output(LCD_2V8_EN, GPIO_OUT_ONE); //VCC_LCD_3V3
pmic_vgp2_enable(true, 1800); //VCC_LCD8_1V8
lcm_set_gpio_output(LCD_AVDD_EN, GPIO_OUT_ONE);
lcm_set_gpio_output(LCD_GAMA_EN, GPIO_OUT_ZERO);
#else
inettek_gpio_set("lcm_vcc_en1");
lcm_vgp_supply_enable();
inettek_gpio_set("lcm_avdd_en1");
inettek_gpio_set("lcm_gama_en0");
#endif
}
static void lcm_suspend(void)
{
#ifndef BUILD_LK
//unsigned int data_array[16];
printk("[Kernel/LCM] %s enter\n", __func__);
// data_array[0] = 0x00280500; /* Display Off */
// dsi_set_cmdq(data_array, 1, 1);
// MDELAY(10);
// data_array[0] = 0x00100500; /* Sleep In */
// dsi_set_cmdq(data_array, 1, 1);
// MDELAY(120);
#endif
}
static void lcm_suspend_power(void)
{
#ifdef BUILD_LK
printf("[LK/LCM]xxxxxxx %s enter\n", __func__);
#else
printk("[Kernel/LCM] %s enter\n", __func__);
#endif
#ifdef BUILD_LK
lcm_set_gpio_output(LCD_2V8_EN, GPIO_OUT_ZERO); //VCC_LCD_3V3
pmic_vgp2_enable(false,1800);
MDELAY(10);
lcm_set_gpio_output(LCD_AVDD_EN, GPIO_OUT_ZERO);
lcm_set_gpio_output(LCD_GAMA_EN, GPIO_OUT_ZERO);
lcm_set_gpio_output(LCD_RST_PIN, GPIO_OUT_ZERO);
lcm_set_gpio_output(LCD_3V3_RST_PIN, GPIO_OUT_ZERO);
#else
inettek_gpio_set("lcm_rst_en0");
inettek_gpio_set("lcm_3v3_rst_en0");
MDELAY(10);
inettek_gpio_set("lcm_avdd_en0");
inettek_gpio_set("lcm_gama_en0");
lcm_vgp_supply_disable();
inettek_gpio_set("lcm_vcc_en0");
MDELAY(10);
#endif
}
static unsigned int lcm_compare_id(void)
{
unsigned int id = 0xffff;
unsigned int version_id = 0xff;
unsigned char buffer[3];
unsigned int hw_ver = 0;
unsigned int array[16];
buffer[0] = 0xff;
buffer[1] = 0xff;
buffer[2] = 0xff;
lcm_init_power();
lcm_reset();
// array[0] = 0x00023700;// read id return two byte,version and id
array[0] = 0x00033700;// read id return two byte,version and id
dsi_set_cmdq(array, 1, 1);
read_reg_v2(0x04, buffer, 3);
id = buffer[1]|(buffer[0]<<8);; //we only need ID
version_id = buffer[2];
#ifdef BUILD_LK
extern int g_hw_ver;
hw_ver = g_hw_ver;
//Read NV3052 ID, ID=0x3052, version_id=0x2, hw_ver=0x1
printf("Read NV3052 ID, ID=0x%x, version_id=0x%x, hw_ver=0x%x\n", id , version_id , hw_ver);
printf("[LK/LCM] %s %s is nv3052_bv055hdl_nb6! \n", __func__,hw_ver?"i50_lcm":"i70Plus_lcm");
#else
printk("Read NV3052 ID, ID=0x%x, version_id=0x%x, hw_ver=0x%x\n", id , version_id , hw_ver);
printk("[Kernel/LCM] %s %s is nv3052_bv055hdl_nb6! \n", __func__,hw_ver?"i50_lcm":"i70Plus_lcm");
#endif
if (hw_ver && (LCM_ID_NV3052 == id))
return 1;
else
return 0;
}
LCM_DRIVER nv3052_bv055hdl_nb6_dsi_vdo_lcm_drv = {
.name = "nv3052_bv055hdl_nb6_dsi_vdo",
.set_util_funcs = lcm_set_util_funcs,
.get_params = lcm_get_params,
.init = lcm_init,
.init_power = lcm_init_power,
.suspend = lcm_suspend,
.resume = lcm_resume,
.resume_power = lcm_resume_power,
.suspend_power = lcm_suspend_power,
.compare_id = lcm_compare_id,
};