tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sprdfb / lcd / lcd_vx5b3d_mipi.c
1 /* drivers/video/sprdfb/lcd_vx5b3d_mipi.c\r
2  *\r
3  * Support for 5b3d lvds LCD device\r
4  *\r
5  * Copyright (C) 2013 Spreadtrum\r
6  *\r
7  * This software is licensed under the terms of the GNU General Public\r
8  * License version 2, as published by the Free Software Foundation, and\r
9  * may be copied, distributed, and modified under those terms.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  */\r
16 #include <asm/arch/sprd_lcd.h>\r
17 //#include <asm/arch/sprd_i2c.h>\r
18 #include <asm/arch/sci_types.h>\r
19 #include "sp8830_i2c.h"\r
20 //#include "sc8830_i2c_cfg.h"\r
21 \r
22 #include "../sprdfb.h"\r
23 \r
24 #define printk printf\r
25 \r
26 #define  LCD_DEBUG\r
27 #ifdef LCD_DEBUG\r
28 #define LCD_PRINT printk\r
29 #else\r
30 #define LCD_PRINT(...)\r
31 #endif\r
32 \r
33 \r
34 \r
35 struct bridge_ops {\r
36         int32_t (*init)(struct panel_spec *self);\r
37 };\r
38 \r
39 static struct bridge_ops b_ops = {\r
40         .init = NULL,\r
41 };\r
42 \r
43 #define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))\r
44 \r
45 #define I2CID_BRIDGE                3\r
46 #define I2C_BRIDGE_ADDR             0x64\r
47 \r
48 #define GPIOID_BLIC_EN (214)\r
49 #define GPIOID_BRIDGE_EN  (233)  // We can't see this pin in the SCH provided by SS\r
50 #define GPIOID_BRIDGE_RST  (234)\r
51 #define GPIOID_LCD_3V3_EN  (152) // If this gpio not exist in HW, remove this defination
52 \r
53 #define DELAY_CMD       (0xFFFF)  // This is a flag for delay\r
54 \r
55 extern int sprd_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value);\r
56 extern int sprd_gpio_request(struct gpio_chip *chip, unsigned offset);\r
57 \r
58 typedef struct I2C_Init_Code {\r
59         uint16_t addr;\r
60         uint32_t data;\r
61 };\r
62 \r
63 static I2C_DEV i2c_dev_bridge = {\r
64         .id = I2CID_BRIDGE,\r
65         .freq = 400*1000,\r
66         .bus = 2,\r
67         .slave_addr = I2C_BRIDGE_ADDR*2,\r
68         .reg_addr_num = 2,  // This is to decide the register byte number\r
69         .check_ack = 1,\r
70         .no_stop = 0,\r
71 };\r
72 \r
73 struct I2C_Init_Code lvds_5b3d_init_data[] = {\r
74         {0x700, 0x6C900040},\r
75         {0x704, 0x0003040A},\r
76         {0x70C, 0x00004604},\r
77         {0x710, 0x054D000B},\r
78         {0x714, 0x00000020},\r
79         {0x718, 0x00000102},\r
80         {0x71C, 0x00A8002F},\r
81         {0x720, 0x00000000},\r
82 \r
83         {DELAY_CMD, 100},       /* For pll locking */\r
84         {0x154, 0x00000000},\r
85         {0x154, 0x80000000},\r
86         {DELAY_CMD, 100},       /* For pll locking */\r
87 \r
88         {0x700, 0x6C900840},\r
89         {0x70C, 0x00005E56},\r
90         {0x718, 0x00000202},\r
91 \r
92         {0x154, 0x00000000},\r
93         {0x154, 0x80000000},\r
94         {DELAY_CMD, 100},       /* For pll locking */\r
95 \r
96         {0x37C, 0x00001063},\r
97         {0x380, 0x82A86030},\r
98         {0x384, 0x2861408B},\r
99         {0x388, 0x00130285},\r
100         {0x38C, 0x10630009},\r
101         {0x394, 0x400B82A8},\r
102         {0x600, 0x016CC78C},\r
103         {0x604, 0x3FFFFFE0},\r
104         {0x608, 0x00000D8C},\r
105         {0x154, 0x00000000},\r
106         {0x154, 0x80000000},\r
107         {0x120, 0x00000005},\r
108         {0x124, 0x1892C400},\r
109         {0x128, 0x00102806},\r
110         {0x12C, 0x00000062},\r
111         {0x130, 0x00003C18},\r
112         {0x134, 0x00000015},\r
113         {0x138, 0x00FF8000},\r
114         {0x13C, 0x00000000},\r
115 \r
116         /*PWM  100 % duty ration*/\r
117         {0x114, 0x000c6302},\r
118 \r
119         /*backlight duty ratio control when device is first bring up.*/\r
120         {0x160, 0x000007F8},\r
121         {0x164, 0x000002A8},\r
122         {0x138, 0x3fff0000},\r
123         {0x15C, 0x00000005},\r
124 \r
125         {0x140, 0x00010000},\r
126         /*Add for power consumtion*/\r
127         {0x174, 0x00000000},\r
128         /*end*/\r
129 \r
130         /*\r
131            slope = 2 / variance = 0x55550022\r
132            slope register [15,10]\r
133            */\r
134         {0x404, 0x55550822},\r
135 \r
136         /*\r
137            To minimize the text effect\r
138            this value from 0xa to 0xf\r
139            */\r
140         {0x418, 0x555502ff},\r
141 \r
142         /*\r
143            Disable brightnes issue Caused by IBC\r
144            read 4 bytes from address 0x410 to 0x413\r
145            0x15E50300 is read value for 0x410 register\r
146            0x5E50300= 0x15E50300 & 0xefffffff\r
147            */\r
148         {0x410, 0x05E50300},\r
149         /*...end*/\r
150         {0x20C, 0x00000124},\r
151         {0x21C, 0x00000000},\r
152         {0x224, 0x00000007},\r
153         {0x228, 0x00050001},\r
154         {0x22C, 0x0000FF03},\r
155         {0x230, 0x00000001},\r
156         {0x234, 0xCA033E10},\r
157         {0x238, 0x00000060},\r
158         {0x23C, 0x82E86030},\r
159         {0x244, 0x001E0285},\r
160         {0x258, 0x00060062},\r
161         /*vee strenght initialization*/\r
162         {0x400, 0x00000000},\r
163         {0x158, 0x00000000},\r
164         {0x158, 0x00000001},\r
165 \r
166 };\r
167 \r
168 \r
169 \r
170 static int32_t vx5b3d_power()\r
171 {\r
172 \r
173 #if 0\r
174         if (!probe) {\r
175                 if (sprd_gpio_request(GPIOID_BRIDGE_EN, "BRIDGE_EN")) {\r
176                         printk("[%s] GPIO%d request failed!\n", "BRIDGE_EN", GPIOID_BRIDGE_EN);\r
177                         return 0;\r
178                 }\r
179                 else\r
180                         sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_EN, 0);\r
181 #endif\r
182 #ifdef GPIOID_LCD_3V3_EN
183                 if (sprd_gpio_request(NULL,GPIOID_LCD_3V3_EN)){
184                         printk("sprdfb: LCD_3V3_EN GPIO%d request failed!\n", GPIOID_LCD_3V3_EN);
185                         return 0;
186                 }else{
187                         sprd_gpio_direction_output(NULL, GPIOID_LCD_3V3_EN, 1);
188                         sprd_gpio_set(NULL,GPIOID_LCD_3V3_EN, 1);
189                         mdelay(5);
190                 }
191 #endif
192                 if (sprd_gpio_request(NULL,GPIOID_BRIDGE_RST)){\r
193                         printk("sprdfb: BRIDGE_RST GPIO%d request failed!\n", GPIOID_BRIDGE_RST);\r
194                         return 0;\r
195                 }\r
196                 sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_RST, 1);\r
197                 sprd_gpio_set(NULL,GPIOID_BRIDGE_RST, 1);\r
198                 mdelay(5);\r
199 \r
200                 if (sprd_gpio_request(NULL,GPIOID_BLIC_EN)) {\r
201                         printk("sprdfb: BLIC_EN  GPIO%d request failed!\n", GPIOID_BLIC_EN);\r
202                         return 0;\r
203                 }\r
204                 sprd_gpio_direction_output(NULL, GPIOID_BLIC_EN, 1);\r
205                 sprd_gpio_set(NULL, GPIOID_BLIC_EN, 1);\r
206                 mdelay(5);\r
207 \r
208                 if (sprd_gpio_request(NULL,GPIOID_BRIDGE_EN)){\r
209                         printk("sprdfb: BRIDGE_RST GPIO%d request failed!\n", GPIOID_BRIDGE_EN);\r
210                         return 0;\r
211                 }\r
212                 sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_EN, 1);\r
213                 sprd_gpio_set(NULL,GPIOID_BRIDGE_EN, 1);\r
214                 mdelay(5);\r
215 \r
216                 LCD_PRINT("zyun: 2\n");\r
217 \r
218 #if 0\r
219                 lvds_1v8 = regulator_get(NULL,"vddsim1");\r
220                 if (IS_ERR(lvds_1v8)) {\r
221                         lvds_1v8 = NULL;\r
222                         pr_info("%s regulator 1v8 get failed!!\n", "vddsim1");\r
223                 } else {\r
224                         regulator_set_voltage(lvds_1v8, 1800000, 1800000);\r
225                         regulator_enable(lvds_1v8);\r
226                 }\r
227 \r
228                 lvds_3v3 = regulator_get(NULL,"vddwifipa");\r
229                 if (IS_ERR(lvds_3v3)) {\r
230                         lvds_3v3 = NULL;\r
231                         pr_info("%s regulator 3v3 get failed!!\n", "vddwifipa");\r
232                 } else {\r
233                         regulator_set_voltage(lvds_3v3, 3300000, 3300000);\r
234                         regulator_enable(lvds_3v3);\r
235                 }\r
236                 probe = 1;\r
237         }\r
238 \r
239 #endif\r
240         \r
241 }\r
242 #define CONTROL_BYTE_GEN       (0x09u)\r
243 #define GEN_QL_CSR_WRITE  {\\r
244         CONTROL_BYTE_GEN, \\r
245         0x29,  /* Data ID */\\r
246         0x05,  /* Vendor Id 1 */\\r
247         0x01,  /* Vendor Id 2 */\\r
248         0x40,  /* Vendor Unique Command */\\r
249         0x00,  /* Address LS */\\r
250         0x00,  /* Address MS */\\r
251         0x00,  /* data LS */\\r
252         0x00, \\r
253         0x00, \\r
254         0x00,  /* data MS */\\r
255 }\r
256 \r
257 int vx5b3d_i2c_write32_array(int32_t handle, struct I2C_Init_Code *b_data, int len)\r
258 {\r
259         int i, ret;\r
260         char buf[] = GEN_QL_CSR_WRITE;\r
261 \r
262         for (i = 0; i < len; i++) {\r
263                 if (b_data[i].addr == DELAY_CMD) {\r
264                         mdelay(b_data[i].data);\r
265                         continue;\r
266                 }\r
267                 memcpy(buf+5,(uint8 *)&(b_data[i].addr), 2);\r
268                 memcpy(buf+7,(uint8 *)&(b_data[i].data), 4);\r
269 \r
270                 //ret = I2C_HAL_Write(handle,(uint8 *)&(b_data[i].addr), (uint8 *)&(b_data[i].data),4);\r
271                 ret = I2C_HAL_Write(handle, buf, buf+2,9);\r
272 //              LCD_PRINT("I2C Write, buf5-11 is: %x %x %x %x %x %x\n",  buf[5], buf[6],buf[7],buf[8],buf[9],buf[10]);\r
273         }\r
274 \r
275         return ret;\r
276 }\r
277 \r
278 #if 0\r
279 int Quicklogic_i2c_write32(u16 reg, u32 val)\r
280 {\r
281         int status = 0;\r
282         /*int write_size;*/\r
283         char buf[] = GEN_QL_CSR_WRITE;\r
284 \r
285         if (g_client == NULL)   /* No global client pointer? */\r
286                 return -EIO;\r
287 \r
288         mutex_lock(&lock);\r
289 \r
290         buf[5] = (uint8_t)reg;  /* Address LS */\r
291         buf[6] = (uint8_t)(reg >> 8);   /* Address MS */\r
292 \r
293         buf[7] = val & 0xff;\r
294         buf[8] = (val >> 8) & 0xff;\r
295         buf[9] = (val >> 16) & 0xff;\r
296         buf[10] =(val >> 24) & 0xff;\r
297         status = i2c_master_send(g_client, (char *)(&buf[0]), 11);\r
298 \r
299         if (status >= 0)\r
300                 status = 0;\r
301         else {\r
302                 pr_info("%s, [0x%04x] -EIO\n", __func__, reg);\r
303                 status = -EIO;\r
304         }\r
305 \r
306         udelay(10);\r
307         mutex_unlock(&lock);\r
308 \r
309         return status;\r
310 \r
311 }\r
312 #endif\r
313 \r
314 static int32_t lvds_5b3d_init(struct panel_spec *self)\r
315 {\r
316         int32_t handle = 0;\r
317         int32_t len=ARRAY_SIZE(lvds_5b3d_init_data);\r
318 \r
319         /* open i2c */\r
320         handle = I2C_HAL_Open(&i2c_dev_bridge);\r
321         if(handle==-1)\r
322                 LCD_PRINT("sprdfb: hal open failed!%d\n",handle);\r
323 \r
324         vx5b3d_i2c_write32_array(handle,lvds_5b3d_init_data,len);\r
325 \r
326         I2C_HAL_Close(handle);\r
327 \r
328         return 0;\r
329 }\r
330 \r
331 \r
332 static int32_t lcd_5b3d_mipi_lvds_init(struct panel_spec *self)\r
333 {\r
334         LCD_PRINT("zyun: 1\n");\r
335 \r
336         vx5b3d_power();  // TO pull up some GPIO\r
337         lvds_5b3d_init(self);\r
338 }\r
339 \r
340 static uint32_t vx5b3d_readid(struct panel_spec *self)\r
341 {\r
342         int32_t j =0;\r
343         uint8_t read_data[3] = {0};\r
344         int32_t read_rtn = 0;\r
345         uint8_t param[2] = {0};\r
346         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;\r
347         mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;\r
348         mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;\r
349         mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;\r
350 \r
351         mipi_set_cmd_mode();\r
352         mipi_eotp_set(0,0);\r
353 \r
354         for(j = 0; j < 4; j++){\r
355                 param[0] = 0x01;\r
356                 param[1] = 0x00;\r
357                 mipi_force_write(0x37, param, 2);\r
358                 read_rtn = mipi_force_read(0xda,1,&read_data[0]);\r
359 \r
360                 read_rtn = mipi_force_read(0xdb,1,&read_data[1]);\r
361 \r
362                 read_rtn = mipi_force_read(0xdc,1,&read_data[2]);\r
363 \r
364 \r
365                 //      if((0x55 == read_data[0])&&(0xbc == read_data[1])&&(0x90 == read_data[2])){\r
366                 LCD_PRINT("vx5b3d_readid readID, 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]);\r
367                 printk("lcd_vx5b3d_mipi read id success!\n");\r
368                 return 0x8282;\r
369                 //              }\r
370         }\r
371         LCD_PRINT("vx5b3d_readid read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]);\r
372         mipi_eotp_set(0,0);\r
373 \r
374         return 0;\r
375 }\r
376 \r
377 \r
378 static struct panel_operations lcd_vx5b3d_mipi_operations = {\r
379         .panel_init = lcd_5b3d_mipi_lvds_init,\r
380         .panel_readid = vx5b3d_readid,\r
381 };\r
382 \r
383 static struct timing_rgb lcd_vx5b3d_mipi_timing = {\r
384         .hfp = 123,\r
385         .hbp = 100,\r
386         .hsync = 120,\r
387         .vfp = 13,\r
388         .vbp = 10,\r
389         .vsync = 10,\r
390 };\r
391 \r
392 static struct info_mipi lcd_vx5b3d_mipi_info = {\r
393         .work_mode  = SPRDFB_MIPI_MODE_VIDEO,\r
394         .video_bus_width = 24, /*18,16*/\r
395         .lan_number = 4,\r
396         .phy_feq = 480*1000,\r
397         .h_sync_pol = SPRDFB_POLARITY_POS,\r
398         .v_sync_pol = SPRDFB_POLARITY_POS,\r
399         .de_pol = SPRDFB_POLARITY_POS,\r
400         .te_pol = SPRDFB_POLARITY_POS,\r
401         .color_mode_pol = SPRDFB_POLARITY_NEG,\r
402         .shut_down_pol = SPRDFB_POLARITY_NEG,\r
403         .timing = &lcd_vx5b3d_mipi_timing,\r
404         .ops = NULL,\r
405 };\r
406 struct panel_spec lcd_vx5b3d_mipi_spec = {\r
407         .width = 1024,\r
408         .height = 600,\r
409         .fps = 60,\r
410         .type = LCD_MODE_DSI,\r
411         .direction = LCD_DIRECT_NORMAL,\r
412         .info = {\r
413                 .mipi = &lcd_vx5b3d_mipi_info\r
414         },\r
415         .ops = &lcd_vx5b3d_mipi_operations,\r
416 };\r
417 \r
418 \r
419 \r
420 \r