1 /*
2  * drivers/video/fbdev/sunxi/disp2/disp/lcd/rt13qv005d.c
3  *
4  * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5  * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16 [lcd0]
17 lcd_used            = 1
18 lcd_driver_name     = "rt13qv005d"
19 lcd_if              = 1
20 lcd_x               = 240
21 lcd_y               = 240
22 lcd_width           = 26
23 lcd_height          = 29
24 lcd_dclk_freq       = 16
25 lcd_pwm_used        = 1
26 lcd_pwm_ch          = 8
27 lcd_pwm_freq        = 50000
28 lcd_pwm_pol         = 1
29 lcd_pwm_max_limit   = 255
30 lcd_hbp             = 20
31 lcd_ht              = 288
32 lcd_hspw            = 10
33 lcd_vbp             = 8
34 lcd_vt              = 256
35 lcd_vspw            = 4
36 lcd_frm             = 1
37 lcd_hv_clk_phase    = 0
38 lcd_hv_sync_polarity = 0
39 lcd_gamma_en        = 0
40 lcd_bright_curve_en = 1
41 lcd_cmap_en         = 0
42 lcd_cpu_mode        = 1
43 lcd_cpu_te          = 1
44 lcd_cpu_if          = 12
45 lcd_hv_if           = 0
46 lcd_hv_srgb_seq     = 0
47 lcd_rb_swap         = 0
48 
49 lcdgamma4iep        = 22
50 
51 lcd_power           = "vcc-lcd"
52 lcd_pin_power       = "vcc-pd"
53 
54 ;reset pin
55 lcd_gpio_0          = port:PD09<1><0><2><1>
56 ;cs pin
57 lcd_gpio_1          = port:PD10<1><0><2><0>
58 
59 lcdd3               = port:PD1<2><0><2><default>
60 lcdd4               = port:PD2<2><0><2><default>
61 lcdd5               = port:PD3<2><0><2><default>
62 lcdd6               = port:PD4<2><0><2><default>
63 lcdd7               = port:PD5<2><0><2><default>
64 lcdd10              = port:PD6<2><0><2><default>
65 lcdd11              = port:PD7<2><0><2><default>
66 lcdd12              = port:PD8<2><0><2><default>
67 lcdclk              = port:PD18<2><0><3><default>
68 lcdde               = port:PD19<2><0><3><default>
69 lcdhsync            = port:PD20<2><0><3><default>
70 lcdvsync            = port:PD21<2><0><3><default>
71 [lcd0_suspend]
72 lcdd3               = port:PD1<7><0><2><default>
73 lcdd4               = port:PD2<7><0><2><default>
74 lcdd5               = port:PD3<7><0><2><default>
75 lcdd6               = port:PD4<7><0><2><default>
76 lcdd7               = port:PD5<7><0><2><default>
77 lcdd10              = port:PD6<7><0><2><default>
78 lcdd11              = port:PD7<7><0><2><default>
79 lcdd12              = port:PD8<7><0><2><default>
80 lcdclk              = port:PD18<7><0><3><default>
81 lcdde               = port:PD19<7><0><3><default>
82 lcdhsync            = port:PD20<7><0><3><default>
83 lcdvsync            = port:PD21<7><0><3><default>
84  */
85 #include "rt13qv005d.h"
86 
87 #define TCON_DEBUG (0)
88 
89 static void lcd_panel_st7789v_init(u32 sel, struct disp_panel_para *info);
90 static void lcd_cpu_panel_fr(__u32 sel, __u32 w, __u32 h, __u32 x, __u32 y);
91 static void LCD_power_on(u32 sel);
92 static void LCD_power_off(u32 sel);
93 static void LCD_bl_open(u32 sel);
94 static void LCD_bl_close(u32 sel);
95 
96 static void LCD_panel_init(u32 sel);
97 static void LCD_panel_exit(u32 sel);
98 
LCD_cfg_panel_info(struct panel_extend_para * info)99 static void LCD_cfg_panel_info(struct panel_extend_para *info)
100 {
101 #if 0
102     u32 i = 0, j = 0;
103     u32 items;
104     u8 lcd_gamma_tbl[][2] = {
105         //{input value, corrected value}
106         {0, 0},     {15, 15},   {30, 30},   {45, 45},   {60, 60},
107         {75, 75},   {90, 90},   {105, 105}, {120, 120}, {135, 135},
108         {150, 150}, {165, 165}, {180, 180}, {195, 195}, {210, 210},
109         {225, 225}, {240, 240}, {255, 255},
110     };
111 
112     u32 lcd_cmap_tbl[2][3][4] = {
113         {
114         {LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
115         {LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
116         {LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
117         },
118         {
119         {LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
120         {LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
121         {LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
122         },
123     };
124 
125     items = sizeof(lcd_gamma_tbl) / 2;
126     for (i = 0; i < items - 1; i++) {
127         u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
128 
129         for (j = 0; j < num; j++) {
130             u32 value = 0;
131 
132             value =
133                 lcd_gamma_tbl[i][1] +
134                 ((lcd_gamma_tbl[i + 1][1] - lcd_gamma_tbl[i][1]) *
135                  j) /
136                 num;
137             info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
138                 (value << 16) + (value << 8) + value;
139         }
140     }
141     info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items - 1][1] << 16) +
142                    (lcd_gamma_tbl[items - 1][1] << 8) +
143                    lcd_gamma_tbl[items - 1][1];
144 
145     memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
146 #endif
147 }
148 
LCD_open_flow(u32 sel)149 static s32 LCD_open_flow(u32 sel)
150 {
151     LCD_OPEN_FUNC(sel, LCD_power_on, 120);
152     LCD_OPEN_FUNC(sel, LCD_panel_init, 100);
153     LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 50);
154     LCD_OPEN_FUNC(sel, LCD_bl_open, 0);
155 
156     return 0;
157 }
158 
LCD_close_flow(u32 sel)159 static s32 LCD_close_flow(u32 sel)
160 {
161     LCD_CLOSE_FUNC(sel, LCD_bl_close, 20);
162     LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 10);
163     LCD_CLOSE_FUNC(sel, LCD_panel_exit, 50);
164     LCD_CLOSE_FUNC(sel, LCD_power_off, 0);
165 
166     return 0;
167 }
168 
LCD_power_on(u32 sel)169 static void LCD_power_on(u32 sel)
170 {
171     /*config lcd_power pin to open lcd power0 */
172     sunxi_lcd_power_enable(sel, 0);
173     sunxi_lcd_pin_cfg(sel, 1);
174 
175     /*lcd_rst, active hight */
176     sunxi_lcd_delay_ms(10);
177     sunxi_lcd_gpio_set_value(sel, 1, 1);
178     sunxi_lcd_gpio_set_value(sel, 0, 0);
179     sunxi_lcd_delay_ms(10);
180     sunxi_lcd_gpio_set_value(sel, 0, 1);
181 }
182 
LCD_power_off(u32 sel)183 static void LCD_power_off(u32 sel)
184 {
185     /*lcd_cs, active low */
186     sunxi_lcd_gpio_set_value(sel, 1, 1);
187     sunxi_lcd_delay_ms(10);
188     /*lcd_rst, active hight */
189     sunxi_lcd_gpio_set_value(sel, 0, 0);
190     sunxi_lcd_delay_ms(10);
191 
192     sunxi_lcd_pin_cfg(sel, 0);
193     /*config lcd_power pin to close lcd power0 */
194     sunxi_lcd_power_disable(sel, 0);
195 }
196 
LCD_bl_open(u32 sel)197 static void LCD_bl_open(u32 sel)
198 {
199     sunxi_lcd_pwm_enable(sel);
200     /*config lcd_bl_en pin to open lcd backlight */
201     sunxi_lcd_backlight_enable(sel);
202 }
203 
LCD_bl_close(u32 sel)204 static void LCD_bl_close(u32 sel)
205 {
206     /*config lcd_bl_en pin to close lcd backlight */
207     sunxi_lcd_backlight_disable(sel);
208     sunxi_lcd_pwm_disable(sel);
209 }
210 
211 /*static int bootup_flag = 0;*/
LCD_panel_init(u32 sel)212 static void LCD_panel_init(u32 sel)
213 {
214     struct disp_panel_para *info =
215         kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL);
216 
217     bsp_disp_get_panel_info(sel, info);
218     lcd_panel_st7789v_init(sel, info);
219 
220     if (LCD_CPU_AUTO_MODE == info->lcd_cpu_mode)
221         sunxi_lcd_cpu_set_auto_mode(sel);
222     /*else */
223     /*  tcon0_cpu_set_tri_mode(sel); */
224 
225     disp_sys_free(info);
226     return;
227 }
228 
LCD_panel_exit(u32 sel)229 static void LCD_panel_exit(u32 sel)
230 {
231     sunxi_lcd_cpu_write_index(0, 0x28);
232     sunxi_lcd_cpu_write_index(0, 0x10);
233 }
234 
lcd_dbi_wr_dcs(__u32 sel,__u8 cmd,__u8 * para,__u32 para_num)235 static void lcd_dbi_wr_dcs(__u32 sel, __u8 cmd, __u8 *para, __u32 para_num)
236 {
237     __u8 index = cmd;
238     __u8 *data_p = para;
239     __u16 i;
240     sunxi_lcd_cpu_write_index(sel, index);
241     for (i = 0; i < para_num; i++) {
242         sunxi_lcd_cpu_write_data(sel, *(data_p++));
243     }
244 }
245 
lcd_cpu_panel_fr(__u32 sel,__u32 w,__u32 h,__u32 x,__u32 y)246 static void lcd_cpu_panel_fr(__u32 sel, __u32 w, __u32 h, __u32 x, __u32 y)
247 {
248     __u8 para[4];
249     __u32 para_num;
250     para[0] = (x >> 8) & 0xff;
251     para[1] = (x >> 0) & 0xff;
252     para[2] = ((x + w - 1) >> 8) & 0xff;
253     para[3] = ((x + w - 1) >> 0) & 0xff;
254     para_num = 4;
255     lcd_dbi_wr_dcs(sel, DSI_DCS_SET_COLUMN_ADDRESS, para, para_num);
256 
257     para[0] = (y >> 8) & 0xff;
258     para[1] = (y >> 0) & 0xff;
259     para[2] = ((y + h - 1) >> 8) & 0xff;
260     para[3] = ((y + h - 1) >> 0) & 0xff;
261     para_num = 4;
262     lcd_dbi_wr_dcs(sel, DSI_DCS_SET_PAGE_ADDRESS, para, para_num);
263 }
264 
lcd_panel_st7789v_init(u32 sel,struct disp_panel_para * info)265 static void lcd_panel_st7789v_init(u32 sel, struct disp_panel_para *info)
266 {
267 
268     /*lcd_cs, active low */
269     sunxi_lcd_gpio_set_value(sel, 1, 0);
270     sunxi_lcd_delay_ms(10);
271 
272 
273     sunxi_lcd_cpu_write_index(0, 0x11);
274     sunxi_lcd_delay_ms(120);
275 
276     /* Memory Data Access Control */
277     sunxi_lcd_cpu_write_index(0, 0x36);
278     sunxi_lcd_cpu_write_data(0, 0x00); /* 0x20 */
279 
280     sunxi_lcd_cpu_write_index(0, 0x3A);
281     /* 06 ---->262K(RGB666);05---->65K(RGB565) */
282     sunxi_lcd_cpu_write_data(0, 0x06);
283 
284     sunxi_lcd_cpu_write_index(0, 0xB2);
285     sunxi_lcd_cpu_write_data(0, 0x0C);
286     sunxi_lcd_cpu_write_data(0, 0x0C);
287     sunxi_lcd_cpu_write_data(0, 0x00);
288     sunxi_lcd_cpu_write_data(0, 0x33);
289     sunxi_lcd_cpu_write_data(0, 0x33);
290 
291     sunxi_lcd_cpu_write_index(0, 0xB7);
292     sunxi_lcd_cpu_write_data(0, 0x75);
293 
294     sunxi_lcd_cpu_write_index(0, 0xBB);
295     /* 0x20);//0x3C);//0x0E);//0x20);  //vcom    0x20 */
296     sunxi_lcd_cpu_write_data(0, 0x3D);
297 
298     sunxi_lcd_cpu_write_index(0, 0xC2);
299     sunxi_lcd_cpu_write_data(0, 0x01);
300     /* VRH--->值越大越暗,反之越白 */
301     sunxi_lcd_cpu_write_index(0, 0xC3);
302     /* 0x0b);//0x0b);   0x0B 0x06 */
303     sunxi_lcd_cpu_write_data(0, 0x19);
304 
305     sunxi_lcd_cpu_write_index(0, 0xC4);
306     sunxi_lcd_cpu_write_data(0, 0x20);
307 
308     sunxi_lcd_cpu_write_index(0, 0xC6);
309     /* frame */
310     sunxi_lcd_cpu_write_data(0, 0x0F);
311 
312     sunxi_lcd_cpu_write_index(0, 0xD0);
313     sunxi_lcd_cpu_write_data(0, 0xA4);
314     sunxi_lcd_cpu_write_data(0, 0xA1);
315 
316     sunxi_lcd_cpu_write_index(0, 0xD6);
317     sunxi_lcd_cpu_write_data(0, 0xA1);
318 
319     /*[> gamma <]*/
320     sunxi_lcd_cpu_write_index(0, 0xE0);
321     sunxi_lcd_cpu_write_data(0, 0x70);
322     sunxi_lcd_cpu_write_data(0, 0x04);
323     sunxi_lcd_cpu_write_data(0, 0x08);
324     sunxi_lcd_cpu_write_data(0, 0x09);
325     sunxi_lcd_cpu_write_data(0, 0x09);
326     sunxi_lcd_cpu_write_data(0, 0x05);
327     sunxi_lcd_cpu_write_data(0, 0x2a);
328     sunxi_lcd_cpu_write_data(0, 0x33);
329     sunxi_lcd_cpu_write_data(0, 0x41);
330     sunxi_lcd_cpu_write_data(0, 0x07);
331     sunxi_lcd_cpu_write_data(0, 0x13);
332     sunxi_lcd_cpu_write_data(0, 0x13);
333     sunxi_lcd_cpu_write_data(0, 0x29);
334     sunxi_lcd_cpu_write_data(0, 0x2f);
335 
336     sunxi_lcd_cpu_write_index(0, 0xE1); /* gamma */
337     sunxi_lcd_cpu_write_data(0, 0x70);
338     sunxi_lcd_cpu_write_data(0, 0x03);
339     sunxi_lcd_cpu_write_data(0, 0x09);
340     sunxi_lcd_cpu_write_data(0, 0x0A);
341     sunxi_lcd_cpu_write_data(0, 0x09);
342     sunxi_lcd_cpu_write_data(0, 0x06);
343     sunxi_lcd_cpu_write_data(0, 0x2B);
344     sunxi_lcd_cpu_write_data(0, 0x34);
345     sunxi_lcd_cpu_write_data(0, 0x41);
346     sunxi_lcd_cpu_write_data(0, 0x07);
347     sunxi_lcd_cpu_write_data(0, 0x12);
348     sunxi_lcd_cpu_write_data(0, 0x14);
349     sunxi_lcd_cpu_write_data(0, 0x28);
350     sunxi_lcd_cpu_write_data(0, 0x2E);
351     /*inversion on */
352     sunxi_lcd_cpu_write_index(0, 0x21);
353     /*te on*/
354     sunxi_lcd_cpu_write_index(0, 0x35);
355     sunxi_lcd_cpu_write_data(0, 0x00);
356 
357     sunxi_lcd_cpu_write_index(0, 0x29); /* Display on */
358 
359     lcd_cpu_panel_fr(0, info->lcd_x, info->lcd_y, 0, 0);
360 
361     sunxi_lcd_cpu_write_index(0, 0x2C); /* start memory write */
362 
363 }
364 
365 /* sel: 0:lcd0; 1:lcd1 */
LCD_user_defined_func(u32 sel,u32 para1,u32 para2,u32 para3)366 static s32 LCD_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
367 {
368     return 0;
369 }
370 
371 /* panel driver name, must mach the name of lcd_drv_name in sys_config.fex */
372 struct __lcd_panel rt13qv005d_panel = {
373     .name = "rt13qv005d",
374     .func = {
375         .cfg_panel_info = LCD_cfg_panel_info,
376         .cfg_open_flow = LCD_open_flow,
377         .cfg_close_flow = LCD_close_flow,
378         .lcd_user_defined_func = LCD_user_defined_func,
379     },
380 };
381