1 /* drivers/video/sprdfb/lcd_s6d77a1_mipi.c
\r
3 * Support for s6d77a1 mipi LCD device
\r
5 * Copyright (C) 2010 Spreadtrum
\r
8 #include <asm/arch/sprd_lcd.h>
\r
9 #include "../sprdfb.h"
\r
10 #define printk printf
\r
14 #define LCD_PRINT printk
\r
16 #define LCD_PRINT(...)
\r
19 #define MAX_DATA 150
\r
21 typedef struct LCM_Init_Code_tag {
\r
23 unsigned char data[MAX_DATA];
\r
26 typedef struct LCM_force_cmd_code_tag{
\r
27 unsigned int datatype;
\r
28 LCM_Init_Code real_cmd_code;
\r
29 }LCM_Force_Cmd_Code;
\r
31 #define LCM_TAG_SHIFT 24
\r
32 #define LCM_TAG_MASK ((1 << 24) -1)
\r
33 #define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
\r
34 #define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
\r
35 //#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
\r
37 #define LCM_TAG_SEND (1<< 0)
\r
38 #define LCM_TAG_SLEEP (1 << 1)
\r
40 #define PIKEA_J1_NBW_PANEL
\r
43 static LCM_Init_Code init_data[] = {
\r
45 #ifndef PIKEA_J1_NBW_PANEL
\r
47 {LCM_SEND(1),{0x11}},
\r
48 {LCM_SEND(5),{3,0,0xF0,0x5A,0x5A}},
\r
49 {LCM_SEND(5),{3,0,0xFC,0xA5,0xA5}},
\r
50 {LCM_SEND(5),{3,0,0xF1,0x5A,0xA5}},
\r
52 {LCM_SEND(2),{0xB3, 0x01}},
\r
53 {LCM_SEND(2),{0xB5, 0x10}},
\r
54 {LCM_SEND(6),{4,0,0xBC,0x01,0x29,0x51}}, /* 141006 Battery detect function disabled */
\r
57 {LCM_SEND(5),{3,0,0xE3,0x24,0x2C}},
\r
59 /* Display Inversion Off */
\r
60 {LCM_SEND(1),{0x21}},
\r
62 /* Display Control */
\r
63 {LCM_SEND(10), {8,0,0xF2,0x11,0x04,0x08,0x10,0x10,0x82,0x54}},
\r
65 /* power control 1 */
\r
66 {LCM_SEND(8),{6,0,0xF3,0x91,0x00,0x00,0x00,0x10}},
\r
68 /* power control 2 */
\r
69 {LCM_SEND(46),{44,0,0xF4,0x01,0x02,0x23,0x24,0x25,0x25,0x26,0x26,0x29,0x29,0x2C,0x2B,0x2C,0x07,0x08,0x05,0x04,0x04,0x01,0x01,0x22,0x0A,0x17,0x0F,0x11,0x23,0x0D,0x0A,0x0B,0x02,0x19,0x13,0x1E,0x1F,0x23,0x20,0x05,0x16,0x1A,0x16,0x1E,0x24,0x1E}},
\r
71 /* power control 3 */
\r
72 {LCM_SEND(31),{29,0,0xF5,0x28,0x28,0xB9,0x21,0x35,0x55,0x36,0x0A,0x00,0x39,0x00,0x00,0x0B,0x4B,0xC4,0xCB,0x4B,0x12,0x12,0x1A,0x00,0x10,0xE0,0xE2,0x0E,0x34,0x34,0x03}},
\r
75 {LCM_SEND(20),{18,0,0xFE,0x00,0x02,0x01,0x39,0x60,0x40,0x21,0x00,0x4B,0x00,0x80,0x00,0xF0,0x00,0x00,0x00,0x02}},
\r
77 /* ASG EQ Control */
\r
78 {LCM_SEND(13),{11,0,0xEE,0x00,0xA8,0x00,0xA8,0x00,0x00,0x00,0x00,0x00,0x00}},
\r
80 {LCM_SEND(24),{22,0,0xEF,0x23,0x01,0x00,0x00,0x2A,0x49,0x08,0x27,0x21,0x40,0x10,0x28,0x02,0x21,0x21,0x03,0x03,0x40,0x00,0x08,0x00}},
\r
82 /* Panel Gate Control */
\r
83 {LCM_SEND(33),{31,0,0xF7,0x02,0x1B,0x0D,0x0D,0x09,0x09,0x0C,0x0C,0x08,0x08,0x04,0x06,0x1A,0x02,0x02,0x02,0x1B,0x0F,0x0F,0x0B,0x0B,0x0E,0x0E,0x0A,0x0A,0x05,0x07,0x1A,0x02,0x02}},
\r
85 /* Source Control */
\r
86 {LCM_SEND(9),{7,0,0xF6,0x63,0x25,0x15,0x00,0x00,0x2A}},
\r
88 /* Memory Data Access Control */
\r
89 {LCM_SEND(2),{0x36,0x10}},
\r
91 /* Positive Gamma Control */
\r
92 {LCM_SEND(20),{18,0,0xFA,0x0C,0x36,0x11,0x17,0x0E,0x14,0x19,0x18,0x1A,0x21,0x23,0x22,0x22,0x21,0x22,0x22,0x29}},
\r
94 /* Negative Gamma Control */
\r
95 {LCM_SEND(20),{18,0,0xFB,0x0C,0x36,0x12,0x17,0x0F,0x14,0x19,0x18,0x1A,0x21,0x24,0x22,0x23,0x21,0x22,0x22,0x29}},
\r
98 {LCM_SEND(1),{0x11}},
\r
101 {LCM_SEND(1),{0x29}},
\r
105 {LCM_SEND(5), {3, 0x00, 0xF0, 0x5A, 0x5A} },
\r
106 {LCM_SEND(5), {3, 0x00, 0xFC, 0xA5, 0xA5} },
\r
107 {LCM_SEND(2), {0xB3, 0x01} },
\r
108 {LCM_SEND(2), {0xB5, 0x10} },
\r
109 {LCM_SEND(6), {4, 0x00, 0xBC, 0x00, 0x29, 0x51} },
\r
110 {LCM_SEND(5), {3, 0x00, 0xE3, 0x24, 0x2C} },
\r
111 {LCM_SEND(1), {0x21} },
\r
112 {LCM_SEND(10), {8, 0x00, 0xF2, 0x11, 0x04, 0x08, 0x10, 0x10, 0x82, 0x54} },
\r
113 {LCM_SEND(8), {6, 0x00, 0xF3, 0x91, 0x00, 0x00, 0x00, 0x10} },
\r
114 {LCM_SEND(46), {44, 0x00, 0xF4, 0x01, 0x02, 0x23, 0x24, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2C, 0x2B, 0x2C,
\r
115 0x07, 0x08, 0x05, 0x04, 0x04, 0x01, 0x01, 0x22, 0x0A, 0x17, 0x0F, 0x11, 0x23, 0x0D, 0x0A, 0x0B,
\r
116 0x02, 0x19, 0x13, 0x1E, 0x1F, 0x23, 0x20, 0x05, 0x16, 0x1A, 0x16, 0x1E, 0x24, 0x1E} },
\r
117 {LCM_SEND(31), {29, 0x00, 0xF5, 0x5A, 0x62, 0xB9, 0x21, 0x35, 0x55, 0x06, 0x08, 0x00, 0x39, 0x00, 0x00, 0x0B,
\r
118 0x4B, 0xC4, 0xCB, 0x4B, 0x12, 0x12, 0x1A, 0x00, 0x10, 0xE0, 0xE2, 0x0E, 0x34, 0x34, 0x03} },
\r
119 {LCM_SEND(20), {18, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x39, 0x60, 0x40, 0x21, 0x00, 0x4B, 0x00, 0x80, 0x00, 0xF0,
\r
120 0x00, 0x00, 0x00, 0x02} },
\r
121 {LCM_SEND(13), {11, 0x00, 0xEE, 0x86, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
\r
122 {LCM_SEND(24), {22, 0x00, 0xEF, 0x34, 0x12, 0x00, 0x00, 0x0A, 0x29, 0x08, 0x27, 0x21, 0x40, 0x10, 0x28, 0x02,
\r
123 0x21, 0x21, 0x03, 0x03, 0x40, 0x00, 0x00, 0x00} },
\r
124 {LCM_SEND(33), {31, 0x00, 0xF7, 0x02, 0x1B, 0x1A, 0x00, 0x01, 0x0D, 0x0D, 0x09, 0x09, 0x0C, 0x0C, 0x08, 0x08,
\r
125 0x04, 0x06, 0x02, 0x1B, 0x1A, 0x00, 0x01, 0x0F, 0x0F, 0x0B, 0x0B, 0x0E, 0x0E, 0x0A, 0x0A, 0x05, 0x07} },
\r
126 {LCM_SEND(9), {7, 0x00, 0xF6, 0x63, 0x25, 0x15, 0x00, 0x00, 0x2E} },
\r
127 {LCM_SEND(2), {0x36, 0x10} },
\r
128 {LCM_SEND(20), {18, 0x00, 0xFA, 0x00, 0x3F, 0x09, 0x10, 0x08, 0x0D, 0x12, 0x12, 0x12, 0x18, 0x1B, 0x1B, 0x1D, 0x1E, 0x21, 0x25, 0x2D} },
\r
129 {LCM_SEND(20), {18, 0x00, 0xFB, 0x00, 0x3F, 0x09, 0x11, 0x08, 0x0E, 0x13, 0x12, 0x13, 0x19, 0x1B, 0x1C, 0x1D, 0x1E, 0x21, 0x25, 0x2D} },
\r
130 {LCM_SEND(10), {8, 0x00, 0xFD, 0x00, 0x10, 0x11, 0x20, 0x21, 0x1F, 0xCC} },
\r
131 {LCM_SEND(5), {3, 0x00, 0xFC, 0x5A, 0x5A} },
\r
133 {LCM_SEND(1),{0x11}},
\r
135 {LCM_SEND(1),{0x29}},
\r
141 static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
\r
143 static LCM_Init_Code sleep_in[] = {
\r
144 {LCM_SEND(1), {0x28}},
\r
145 {LCM_SLEEP(150)}, //>150ms
\r
146 {LCM_SEND(1), {0x10}},
\r
147 {LCM_SLEEP(150)}, //>150ms
\r
150 static LCM_Init_Code sleep_out[] = {
\r
151 {LCM_SEND(1), {0x11}},
\r
152 {LCM_SLEEP(120)},//>120ms
\r
153 {LCM_SEND(1), {0x29}},
\r
154 {LCM_SLEEP(20)}, //>20ms
\r
157 extern void (*lcd_panel_cabc_pwm_bl)(int brightness);
\r
158 extern void backlight_control(int brigtness);
\r
159 static int32_t s6d77a1_mipi_init(struct panel_spec *self)
\r
162 LCM_Init_Code *init = init_data;
\r
165 lcd_panel_cabc_pwm_bl = backlight_control;
\r
167 mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
\r
168 mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
\r
169 mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
\r
171 LCD_PRINT("lcd_s6d77a1_init\n");
\r
173 mipi_set_cmd_mode();
\r
174 mipi_eotp_set(0,0);
\r
176 for(i = 0; i < ARRAY_SIZE(init_data); i++){
\r
177 tag = (init->tag >>24);
\r
178 if(tag & LCM_TAG_SEND){
\r
179 mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
\r
181 }else if(tag & LCM_TAG_SLEEP){
\r
182 mdelay(init->tag & LCM_TAG_MASK);//udelay((init->tag & LCM_TAG_MASK) * 1000);
\r
186 mipi_eotp_set(0,0);
\r
191 static uint32_t s6d77a1_readid(struct panel_spec *self)
\r
194 uint8_t read_data[4] = {0};
\r
195 int32_t read_rtn = 0;
\r
196 uint8_t param[2] = {0};
\r
197 mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
\r
198 mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
\r
199 mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
\r
200 mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
\r
202 LCD_PRINT("lcd_s6d77a1_mipi read id!\n");
\r
204 mipi_set_cmd_mode();
\r
205 mipi_eotp_set(0,0);
\r
207 for(j = 0; j < 4; j++){
\r
210 mipi_force_write(0x37, param, 2);
\r
211 read_rtn = mipi_force_read(0x04, 3, read_data);
\r
212 LCD_PRINT("lcd_s6d77a1_mipi read id 0xda, 0xdb,0xdc is 0x%x,0x%x,0x%x!\n",
\r
213 read_data[0], read_data[1], read_data[2]);
\r
214 if ((0x55 == read_data[0]) && (0xB8 == read_data[1])
\r
215 && (0x10 == read_data[2])) {
\r
216 LCD_PRINT("lcd_s6d77a1_mipi read id success!\n");
\r
221 mipi_eotp_set(0,0);
\r
223 LCD_PRINT("lcd_s6d77a1_mipi read id failed!\n");
\r
225 return 0x55b810; //to fix me
\r
228 static struct panel_operations lcd_s6d77a1_mipi_operations = {
\r
229 .panel_init = s6d77a1_mipi_init,
\r
230 .panel_readid = s6d77a1_readid,
\r
233 static struct timing_rgb lcd_s6d77a1_mipi_timing = {
\r
234 .hfp = 84, /* unit: pixel */
\r
237 .vfp = 16, /* unit: line */
\r
243 static struct info_mipi lcd_s6d77a1_mipi_info = {
\r
244 .work_mode = SPRDFB_MIPI_MODE_VIDEO,
\r
245 .video_bus_width = 24, /*18,16*/
\r
247 .phy_feq =481*1000,
\r
248 .h_sync_pol = SPRDFB_POLARITY_POS,
\r
249 .v_sync_pol = SPRDFB_POLARITY_POS,
\r
250 .de_pol = SPRDFB_POLARITY_POS,
\r
251 .te_pol = SPRDFB_POLARITY_POS,
\r
252 .color_mode_pol = SPRDFB_POLARITY_NEG,
\r
253 .shut_down_pol = SPRDFB_POLARITY_NEG,
\r
254 .timing = &lcd_s6d77a1_mipi_timing,
\r
258 struct panel_spec lcd_s6d77a1_mipi_spec = {
\r
262 .type = LCD_MODE_DSI,
\r
263 .direction = LCD_DIRECT_NORMAL,
\r
265 .mipi = &lcd_s6d77a1_mipi_info
\r
267 .ops = &lcd_s6d77a1_mipi_operations,
\r