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