1 /* drivers/video/sprdfb/lcd_vx5b3d_mipi.c
\r
3 * Support for 5b3d lvds LCD device
\r
5 * Copyright (C) 2013 Spreadtrum
\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
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
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
22 #include "../sprdfb.h"
\r
24 #define printk printf
\r
28 #define LCD_PRINT printk
\r
30 #define LCD_PRINT(...)
\r
36 int32_t (*init)(struct panel_spec *self);
\r
39 static struct bridge_ops b_ops = {
\r
43 #define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
\r
45 #define I2CID_BRIDGE 3
\r
46 #define I2C_BRIDGE_ADDR 0x64
\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
53 #define DELAY_CMD (0xFFFF) // This is a flag for delay
\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
58 typedef struct I2C_Init_Code {
\r
63 static I2C_DEV i2c_dev_bridge = {
\r
67 .slave_addr = I2C_BRIDGE_ADDR*2,
\r
68 .reg_addr_num = 2, // This is to decide the register byte number
\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
83 {DELAY_CMD, 100}, /* For pll locking */
\r
84 {0x154, 0x00000000},
\r
85 {0x154, 0x80000000},
\r
86 {DELAY_CMD, 100}, /* For pll locking */
\r
88 {0x700, 0x6C900840},
\r
89 {0x70C, 0x00005E56},
\r
90 {0x718, 0x00000202},
\r
92 {0x154, 0x00000000},
\r
93 {0x154, 0x80000000},
\r
94 {DELAY_CMD, 100}, /* For pll locking */
\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
116 /*PWM 100 % duty ration*/
\r
117 {0x114, 0x000c6302},
\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
125 {0x140, 0x00010000},
\r
126 /*Add for power consumtion*/
\r
127 {0x174, 0x00000000},
\r
131 slope = 2 / variance = 0x55550022
\r
132 slope register [15,10]
\r
134 {0x404, 0x55550822},
\r
137 To minimize the text effect
\r
138 this value from 0xa to 0xf
\r
140 {0x418, 0x555502ff},
\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
148 {0x410, 0x05E50300},
\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
170 static int32_t vx5b3d_power()
\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
180 sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_EN, 0);
\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);
187 sprd_gpio_direction_output(NULL, GPIOID_LCD_3V3_EN, 1);
188 sprd_gpio_set(NULL,GPIOID_LCD_3V3_EN, 1);
192 if (sprd_gpio_request(NULL,GPIOID_BRIDGE_RST)){
\r
193 printk("sprdfb: BRIDGE_RST GPIO%d request failed!\n", GPIOID_BRIDGE_RST);
\r
196 sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_RST, 1);
\r
197 sprd_gpio_set(NULL,GPIOID_BRIDGE_RST, 1);
\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
204 sprd_gpio_direction_output(NULL, GPIOID_BLIC_EN, 1);
\r
205 sprd_gpio_set(NULL, GPIOID_BLIC_EN, 1);
\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
212 sprd_gpio_direction_output(NULL, GPIOID_BRIDGE_EN, 1);
\r
213 sprd_gpio_set(NULL,GPIOID_BRIDGE_EN, 1);
\r
216 LCD_PRINT("zyun: 2\n");
\r
219 lvds_1v8 = regulator_get(NULL,"vddsim1");
\r
220 if (IS_ERR(lvds_1v8)) {
\r
222 pr_info("%s regulator 1v8 get failed!!\n", "vddsim1");
\r
224 regulator_set_voltage(lvds_1v8, 1800000, 1800000);
\r
225 regulator_enable(lvds_1v8);
\r
228 lvds_3v3 = regulator_get(NULL,"vddwifipa");
\r
229 if (IS_ERR(lvds_3v3)) {
\r
231 pr_info("%s regulator 3v3 get failed!!\n", "vddwifipa");
\r
233 regulator_set_voltage(lvds_3v3, 3300000, 3300000);
\r
234 regulator_enable(lvds_3v3);
\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
254 0x00, /* data MS */\
\r
257 int vx5b3d_i2c_write32_array(int32_t handle, struct I2C_Init_Code *b_data, int len)
\r
260 char buf[] = GEN_QL_CSR_WRITE;
\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
267 memcpy(buf+5,(uint8 *)&(b_data[i].addr), 2);
\r
268 memcpy(buf+7,(uint8 *)&(b_data[i].data), 4);
\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
279 int Quicklogic_i2c_write32(u16 reg, u32 val)
\r
282 /*int write_size;*/
\r
283 char buf[] = GEN_QL_CSR_WRITE;
\r
285 if (g_client == NULL) /* No global client pointer? */
\r
290 buf[5] = (uint8_t)reg; /* Address LS */
\r
291 buf[6] = (uint8_t)(reg >> 8); /* Address MS */
\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
302 pr_info("%s, [0x%04x] -EIO\n", __func__, reg);
\r
307 mutex_unlock(&lock);
\r
314 static int32_t lvds_5b3d_init(struct panel_spec *self)
\r
316 int32_t handle = 0;
\r
317 int32_t len=ARRAY_SIZE(lvds_5b3d_init_data);
\r
320 handle = I2C_HAL_Open(&i2c_dev_bridge);
\r
322 LCD_PRINT("sprdfb: hal open failed!%d\n",handle);
\r
324 vx5b3d_i2c_write32_array(handle,lvds_5b3d_init_data,len);
\r
326 I2C_HAL_Close(handle);
\r
332 static int32_t lcd_5b3d_mipi_lvds_init(struct panel_spec *self)
\r
334 LCD_PRINT("zyun: 1\n");
\r
336 vx5b3d_power(); // TO pull up some GPIO
\r
337 lvds_5b3d_init(self);
\r
340 static uint32_t vx5b3d_readid(struct panel_spec *self)
\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
351 mipi_set_cmd_mode();
\r
352 mipi_eotp_set(0,0);
\r
354 for(j = 0; j < 4; j++){
\r
357 mipi_force_write(0x37, param, 2);
\r
358 read_rtn = mipi_force_read(0xda,1,&read_data[0]);
\r
360 read_rtn = mipi_force_read(0xdb,1,&read_data[1]);
\r
362 read_rtn = mipi_force_read(0xdc,1,&read_data[2]);
\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
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
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
383 static struct timing_rgb lcd_vx5b3d_mipi_timing = {
\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
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
406 struct panel_spec lcd_vx5b3d_mipi_spec = {
\r
410 .type = LCD_MODE_DSI,
\r
411 .direction = LCD_DIRECT_NORMAL,
\r
413 .mipi = &lcd_vx5b3d_mipi_info
\r
415 .ops = &lcd_vx5b3d_mipi_operations,
\r