1 /*
2 * Allwinner SoCs display driver.
3 *
4 * Copyright (C) 2016 Allwinner.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11 #include "lt070me05000.h"
12
13 static void LCD_power_on(u32 sel);
14 static void LCD_power_off(u32 sel);
15 static void LCD_bl_open(u32 sel);
16 static void LCD_bl_close(u32 sel);
17
18 static void LCD_panel_init(u32 sel);
19 static void LCD_panel_exit(u32 sel);
20
21 static u8 const mipi_dcs_pixel_format[4] = { 0x77, 0x66, 0x66, 0x55 };
22
23 #define panel_reset(val) sunxi_lcd_gpio_set_value(sel, 1, val)
24 #define power_en(val) sunxi_lcd_gpio_set_value(sel, 0, val)
25
LCD_cfg_panel_info(struct panel_extend_para * info)26 static void LCD_cfg_panel_info(struct panel_extend_para *info)
27 {
28 u32 i = 0, j = 0;
29 u32 items;
30 u8 lcd_gamma_tbl[][2] = {
31 /* {input value, corrected value} */
32 {0, 0},
33 {15, 15},
34 {30, 30},
35 {45, 45},
36 {60, 60},
37 {75, 75},
38 {90, 90},
39 {105, 105},
40 {120, 120},
41 {135, 135},
42 {150, 150},
43 {165, 165},
44 {180, 180},
45 {195, 195},
46 {210, 210},
47 {225, 225},
48 {240, 240},
49 {255, 255},
50 };
51
52 u32 lcd_cmap_tbl[2][3][4] = {
53 {
54 {LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
55 {LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
56 {LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
57 },
58 {
59 {LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
60 {LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
61 {LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
62 },
63 };
64
65 items = sizeof(lcd_gamma_tbl) / 2;
66 for (i = 0; i < items - 1; i++) {
67 u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
68
69 for (j = 0; j < num; j++) {
70 u32 value = 0;
71
72 value =
73 lcd_gamma_tbl[i][1] +
74 ((lcd_gamma_tbl[i + 1][1] -
75 lcd_gamma_tbl[i][1]) * j) / num;
76 info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
77 (value << 16) + (value << 8) + value;
78 }
79 }
80 info->lcd_gamma_tbl[255] =
81 (lcd_gamma_tbl[items - 1][1] << 16) +
82 (lcd_gamma_tbl[items - 1][1] << 8) + lcd_gamma_tbl[items - 1][1];
83
84 memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
85
86 }
87
LCD_open_flow(u32 sel)88 static s32 LCD_open_flow(u32 sel)
89 {
90 /* open lcd power, and delay 50ms */
91 LCD_OPEN_FUNC(sel, LCD_power_on, 20);
92 /* open lcd power, than delay 200ms */
93 LCD_OPEN_FUNC(sel, LCD_panel_init, 10);
94 /* open lcd controller, and delay 100ms */
95 LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 20);
96 /* open lcd backlight, and delay 0ms */
97 LCD_OPEN_FUNC(sel, LCD_bl_open, 0);
98
99 return 0;
100 }
101
LCD_close_flow(u32 sel)102 static s32 LCD_close_flow(u32 sel)
103 {
104 /* close lcd backlight, and delay 0ms */
105 LCD_CLOSE_FUNC(sel, LCD_bl_close, 0);
106 /* close lcd controller, and delay 0ms */
107 LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 0);
108 /* open lcd power, than delay 200ms */
109 LCD_CLOSE_FUNC(sel, LCD_panel_exit, 200);
110 /* close lcd power, and delay 500ms */
111 LCD_CLOSE_FUNC(sel, LCD_power_off, 500);
112
113 return 0;
114 }
115
LCD_power_on(u32 sel)116 static void LCD_power_on(u32 sel)
117 {
118 /* config lcd_power pin to open lcd power */
119 sunxi_lcd_power_enable(sel, 0);
120 sunxi_lcd_delay_ms(5);
121 /* config lcd_power pin to open lcd power0 */
122 sunxi_lcd_power_enable(sel, 1);
123 sunxi_lcd_delay_ms(5);
124 /* config lcd_power pin to open lcd power2 */
125 sunxi_lcd_power_enable(sel, 2);
126 sunxi_lcd_delay_ms(5);
127 power_en(1);
128 sunxi_lcd_delay_ms(20);
129 panel_reset(1);
130 sunxi_lcd_delay_ms(5);
131 sunxi_lcd_pin_cfg(sel, 1);
132 }
133
LCD_power_off(u32 sel)134 static void LCD_power_off(u32 sel)
135 {
136 sunxi_lcd_pin_cfg(sel, 0);
137 power_en(0);
138 sunxi_lcd_delay_ms(20);
139 panel_reset(0);
140 sunxi_lcd_delay_ms(5);
141 /* config lcd_power pin to close lcd power2 */
142 sunxi_lcd_power_disable(sel, 2);
143 sunxi_lcd_delay_ms(5);
144 /* config lcd_power pin to close lcd power1 */
145 sunxi_lcd_power_disable(sel, 1);
146 sunxi_lcd_delay_ms(5);
147 /* config lcd_power pin to close lcd power */
148 sunxi_lcd_power_disable(sel, 0);
149 }
150
LCD_bl_open(u32 sel)151 static void LCD_bl_open(u32 sel)
152 {
153 sunxi_lcd_pwm_enable(sel);
154 /* config lcd_bl_en pin to open lcd backlight */
155 sunxi_lcd_backlight_enable(sel);
156 }
157
LCD_bl_close(u32 sel)158 static void LCD_bl_close(u32 sel)
159 {
160 /* config lcd_bl_en pin to close lcd backlight */
161 sunxi_lcd_backlight_disable(sel);
162 sunxi_lcd_pwm_disable(sel);
163 }
164
LCD_panel_init(u32 sel)165 static void LCD_panel_init(u32 sel)
166 {
167 struct disp_panel_para *panel_info =
168 kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);
169 u32 bright = 0;
170 u8 para[9];
171
172 bsp_disp_get_panel_info(sel, panel_info);
173 bright = bsp_disp_lcd_get_bright(sel);
174
175 sunxi_lcd_dsi_clk_enable(sel);
176 sunxi_lcd_delay_ms(20);
177 sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_SOFT_RESET);
178 sunxi_lcd_delay_ms(10);
179 sunxi_lcd_dsi_gen_write_1para(sel, 0xb0, 0x00);
180 sunxi_lcd_dsi_gen_write_5para(sel, 0xb3, 0x04, 0x08, 0x00, 0x22, 0x00);
181 sunxi_lcd_dsi_gen_write_1para(sel, 0xb4, 0x0c);
182 sunxi_lcd_dsi_gen_write_2para(sel, 0xb6, 0x3a, 0xd3);
183 sunxi_lcd_dsi_dcs_write_1para(sel, 0x51, bright);
184 sunxi_lcd_dsi_dcs_write_1para(sel, 0x53, 0x2c);
185 sunxi_lcd_dsi_dcs_write_1para(sel, DSI_DCS_SET_PIXEL_FORMAT, 0x77);
186 sunxi_lcd_dsi_dcs_write_4para(sel, DSI_DCS_SET_COLUMN_ADDRESS, 0x00,
187 0x00, 0x04, 0xaf);
188 sunxi_lcd_dsi_dcs_write_4para(sel, DSI_DCS_SET_PAGE_ADDRESS, 0x00, 0x00,
189 0x07, 0x7f);
190 sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_EXIT_SLEEP_MODE);
191 sunxi_lcd_delay_ms(120);
192 sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_SET_DISPLAY_ON);
193
194 sunxi_lcd_dsi_gen_write_5para(sel, 0xb3, 0x14, 0x08, 0x00, 0x22, 0x00);
195
196 sunxi_lcd_dsi_gen_write_1para(sel, 0xd6, 0x01);
197 para[0] = 0x31;
198 para[1] = 0xf7;
199 para[2] = 0x80;
200 para[3] = 0x00;
201 para[4] = panel_info->lcd_vbp - 1;
202 para[5] = 0x00;
203 para[6] = 0x08;
204 para[7] = 0x00;
205 para[8] = 0x00;
206 sunxi_lcd_dsi_gen_write(sel, 0xc2, para, 9);
207
208 disp_sys_free(panel_info);
209 }
210
LCD_panel_exit(u32 sel)211 static void LCD_panel_exit(u32 sel)
212 {
213 sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_SET_DISPLAY_OFF);
214 sunxi_lcd_delay_ms(20);
215 sunxi_lcd_dsi_dcs_write_0para(sel, DSI_DCS_ENTER_SLEEP_MODE);
216 sunxi_lcd_delay_ms(80);
217 }
218
219 /* sel: 0:lcd0; 1:lcd1 */
LCD_user_defined_func(u32 sel,u32 para1,u32 para2,u32 para3)220 static s32 LCD_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
221 {
222 return 0;
223 }
224
225 /* sel: 0:lcd0; 1:lcd1 */
LCD_set_bright(u32 sel,u32 bright)226 static s32 LCD_set_bright(u32 sel, u32 bright)
227 {
228 sunxi_lcd_dsi_dcs_write_1para(sel, 0x51, bright);
229 return 0;
230 }
231
232 struct __lcd_panel lt070me05000_panel = {
233 /* panel driver name, must mach the lcd_drv_name in sys_config.fex */
234 .name = "lt070me05000",
235 .func = {
236 .cfg_panel_info = LCD_cfg_panel_info,
237 .cfg_open_flow = LCD_open_flow,
238 .cfg_close_flow = LCD_close_flow,
239 .lcd_user_defined_func = LCD_user_defined_func,
240 .set_bright = LCD_set_bright,
241 }
242 ,
243 };
244