diff options
Diffstat (limited to 'drivers/video/sprdfb/lcd')
51 files changed, 20047 insertions, 0 deletions
diff --git a/drivers/video/sprdfb/lcd/Makefile b/drivers/video/sprdfb/lcd/Makefile new file mode 100644 index 00000000..6d392745 --- /dev/null +++ b/drivers/video/sprdfb/lcd/Makefile @@ -0,0 +1,50 @@ +obj-$(CONFIG_FB_LCD_HX8363_RGB_SPI) += lcd_hx8363_rgb_spi.o +obj-$(CONFIG_FB_LCD_HX8363_MCU) += lcd_hx8363_mcu.o +obj-$(CONFIG_FB_LCD_HX8369) += lcd_hx8369.o +obj-$(CONFIG_FB_LCD_S6D0139) += lcd_s6d0139.o +obj-$(CONFIG_FB_LCD_NT35516_MCU) += lcd_nt35516_mcu.o +obj-$(CONFIG_FB_LCD_NT35516_MIPI) += lcd_nt35516_mipi.o +obj-$(CONFIG_FB_LCD_NT35516_RGB_I2C) += lcd_nt35516_rgb_i2c.o +obj-$(CONFIG_FB_LCD_NT35516_RGB_SPI) += lcd_nt35516_rgb_spi.o +obj-$(CONFIG_FB_LCD_NT35510_MIPI) += lcd_nt35510_mipi.o +obj-$(CONFIG_FB_LCD_NT35512_MIPI) += lcd_nt35512_mipi.o +obj-$(CONFIG_FB_LCD_OTM8018B_MIPI) += lcd_otm_8018b_mipi.o +obj-$(CONFIG_FB_LCD_SSD2075_MIPI) += lcd_ssd2075_mipi.o +obj-$(CONFIG_FB_LCD_ILI9486) += lcd_ili9486.o +obj-$(CONFIG_FB_LCD_ILI9486_RGB_SPI) += lcd_ili9486_rgb_spi.o +obj-$(CONFIG_FB_LCD_NT51017_MIPI_LVDS) += lcd_nt51017_mipi_lvds.o +obj-$(CONFIG_FB_LCD_HX8369B_MIPI) += lcd_hx8369b_mipi.o +obj-$(CONFIG_FB_LCD_HX8369B_MIPI_KIRAN3G) += lcd_hx8369b_mipi_kiran3g.o +obj-$(CONFIG_FB_LCD_HX8369B_MIPI_COREPRIMELITE) += lcd_hx8369b_mipi_coreprimelite.o +obj-$(CONFIG_FB_LCD_SD7798D_MIPI_COREPRIMELITE) += lcd_sd7798d_mipi.o +obj-$(CONFIG_FB_LCD_HX8369B_MIPI_SHARKLS_Z3LTE) += lcd_hx8369b_mipi_sharkls_z3lte.o +obj-$(CONFIG_FB_LCD_SD7798D_MIPI_SHARKLS_Z3LTE) += lcd_sd7798d_mipi_sharkls_z3lte.o +obj-$(CONFIG_FB_LCD_ILI9341) += lcd_ili9341.o +obj-$(CONFIG_FB_LCD_ST7789V_MCU) += lcd_st7789v_mcu.o +obj-$(CONFIG_FB_LCD_OTM1283A_MIPI) += lcd_otm1283a_mipi.o +obj-$(CONFIG_FB_LCD_NT35502_MIPI) += lcd_nt35502_mipi.o +obj-$(CONFIG_FB_LCD_VIVA_RGB_SPI) += lcd_hx8363_rgb_spi_viva.o +obj-$(CONFIG_FB_LCD_SC7798_RGB_SPI) += lcd_sc7798_rgb_spi.o +obj-$(CONFIG_FB_LCD_ILI9806E_MIPI) += lcd_ili9806e_mipi.o +obj-$(CONFIG_FB_LCD_ILI9806E_2_MIPI) += lcd_ili9806e_2_mipi.o +obj-$(CONFIG_FB_LCD_T8861_MIPI) += lcd_t8861_mipi.o +obj-$(CONFIG_FB_LCD_HX8379A_MIPI) += lcd_hx8379a_mipi.o +obj-$(CONFIG_FB_LCD_HX8389C_MIPI) += lcd_hx8389c_mipi.o +obj-$(CONFIG_FB_LCD_ILI6150_LVDS) += lcd_ili6150_lvds.o +obj-$(CONFIG_FB_LCD_RM68180_MIPI) += lcd_rm68180_mipi.o +obj-$(CONFIG_FB_LCD_ILI9486S1_MIPI) += lcd_ili9486s1_mipi.o +obj-$(CONFIG_FB_LCD_VX5B3D_MIPI) += lcd_vx5b3d_mipi.o +obj-$(CONFIG_FB_LCD_HX8369B_MIPI_VIVALTO_VE) += lcd_hx8369b_mipi_vivaltoVE.o +obj-$(CONFIG_FB_LCD_GRANDNEO_MIPI) += lcd_hx8369b_grandneo_mipi.o +obj-$(CONFIG_FB_LCD_TSHARK2_J3_MIPI) += lcd_hx8369b_tshark2_j3_mipi.o +obj-$(CONFIG_FB_LCD_SD7798D_MIPI) += lcd_sd7798d_mipi.o +obj-$(CONFIG_FB_LCD_S6D77A1_MIPI_PIKEA_J1) += lcd_s6d77a1_pikeA_mipi.o +obj-$(CONFIG_FB_LCD_NT51017_MIPI) += lcd_nt51017_goyal_mipi.o +obj-$(CONFIG_FB_LCD_OTM8019A_MIPI) += lcd_otm8019a_mipi.o +obj-$(CONFIG_FB_LCD_FL10802_MIPI) += lcd_fl10802_mipi.o +obj-$(CONFIG_FB_LCD_JD9161_MIPI) += lcd_jd9161_mipi.o +obj-$(CONFIG_FB_LCD_HX8394D_MIPI) += lcd_hx8394d_mipi.o +obj-$(CONFIG_FB_LCD_HX8394A_MIPI) += lcd_hx8394a_mipi.o +obj-$(CONFIG_FB_LCD_NT35596H_MIPI) += lcd_nt35596h_mipi.o +obj-$(CONFIG_FB_LCD_S6D7AA0X62_MIPI) += lcd_s6d7aa0x62_t8_mipi.o +obj-$(CONFIG_FB_LCD_DUMMY) += lcd_dummy.o diff --git a/drivers/video/sprdfb/lcd/lcd_dummy.c b/drivers/video/sprdfb/lcd/lcd_dummy.c new file mode 100644 index 00000000..6254daf5 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_dummy.c @@ -0,0 +1,104 @@ +/* drivers/video/sc8825/lcd_dummy.c
+ *
+ * Support for dummy LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+static int32_t dummy_mipi_init(struct panel_spec *self)
+{
+ pr_debug(KERN_DEBUG "dummy_init\n");
+ return 0;
+}
+
+static uint32_t dummy_readid(struct panel_spec *self)
+{
+ printk("lcd_dummy read id!\n");
+ printk("lcd_dummy read id success!\n");
+ return 0xFFFFFFFF;
+}
+
+static int32_t dummy_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ printk(KERN_DEBUG "dummy_enter_sleep, is_sleep = %d\n", is_sleep);
+ return 0;
+}
+
+static int32_t dummy_check_esd(struct panel_spec *self)
+{
+ pr_debug("dummy_check_esd!\n");
+ pr_debug("dummy_check_esd OK!\n");
+ return 1;
+}
+
+static struct panel_operations lcd_dummy_operations = {
+ .panel_init = dummy_mipi_init,
+ .panel_readid = dummy_readid,
+ .panel_enter_sleep = dummy_enter_sleep,
+ .panel_esd_check = dummy_check_esd,
+};
+
+static struct timing_rgb lcd_dummy_timing = {
+ .hfp = 20, /* unit: pixel */
+ .hbp = 20,
+ .hsync = 20,//4,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_dummy_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 3,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_dummy_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_dummy_spec = {
+ .width = 320,
+ .height = 480,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .info = {
+ .mipi = &lcd_dummy_info
+ },
+ .ops = &lcd_dummy_operations,
+};
+
+struct panel_cfg lcd_dummy = {
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0xFFFFFFFF,
+ .lcd_name = "lcd_dummy",
+ .panel = &lcd_dummy_spec,
+};
+
+static int __init lcd_dummy_init(void)
+{
+ return sprdfb_panel_register(&lcd_dummy);
+}
+
+subsys_initcall(lcd_dummy_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_fl10802_mipi.c b/drivers/video/sprdfb/lcd/lcd_fl10802_mipi.c new file mode 100644 index 00000000..48565bb5 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_fl10802_mipi.c @@ -0,0 +1,364 @@ +/* drivers/video/sc8825/lcd_fl10802_mipi.c
+ *
+ * Support for fl10802 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_Delay(ms) uDelay(ms*1000)
+
+#define MAX_DATA 80//48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39,LCM_SEND(6), {4,0,0xb9,0xf1,0x08,0x01}},
+ {0x39,LCM_SEND(20), {18,0,0xba,0x31,0x00,0x44,0x25,0xb1,0x0a,0x00,0x00,0xc1,0x00,0x00,0x00,0x0d,0x02,0x5d,0xb5,0xee}},
+
+ {0x37,{LCM_SEND(2),{0x3,0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x39,LCM_SEND(6), {4,0,0xb9,0xf1,0x08,0x01}},
+ {0x39,LCM_SEND(20), {18,0,0xba,0x31,0x00,0x44,0x25,0xb1,0x0a,0x00,0x00,0xc1,0x00,0x00,0x00,0x0d,0x02,0x5d,0xb5,0xee}},
+
+ {0x37,{LCM_SEND(2),{0x1,0}}},
+};
+
+
+static LCM_Init_Code init_data[] = {
+
+
+{LCM_SEND(6), {4,0,0xB9,0xF1,0x08,0x01}},
+
+{LCM_SEND(10), {8,0,0xB1,0x21,0x1E,0x1E,0x87,0x30,0x01,0x8B}},
+
+{LCM_SEND(2), {0xB2,0x23}},
+
+{LCM_SEND(11), {9,0,0xB3,0x00,0x00,0x06,0x06,0x20,0x20,0x30,0x30}},
+
+{LCM_SEND(20), {18,0,0xBA,0x31,0x00,0x44,0x25,0x91,0x0A,0x00,0x00,0xC1,
+ 0x00,0x00,0x00,0x0D,0x02,0x1D,0xB9,0xEE}},
+
+{LCM_SEND(8), {6,0,0xE3,0x04,0x04,0x01,0x01,0x00}},
+
+{LCM_SEND(2), {0xB4,0x02}}, // 2-dot
+
+{LCM_SEND(5), {3,0,0xB5,0x05,0x05}},
+
+{LCM_SEND(5), {3,0,0xB6,0x8C,0x8C}}, //VCOM //0x8C
+
+{LCM_SEND(5), {3,0,0xB8,0x64,0x28}}, //2x, -2.5x
+
+{LCM_SEND(2), {0xCC,0x00}},
+
+{LCM_SEND(2), {0xBC,0x44}},
+
+{LCM_SEND(54), {52,0,0xE9,0x00,0x00,0x07,0x00,0x00,0x81,0x89,0x12,0x31,
+ 0x23,0x23,0x08,0x81,0x80,0x23,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x0F,0x89,0x13,0x18,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x89,0x02,0x08,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00}},
+
+{LCM_SEND(25), {23,0,0xEA,0x90,0x00,0x00,0x00,0x88,0x20,0x09,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x31,0x19,0x88,0x88,0x88,
+ 0x88,0x88,0x88}},
+
+{LCM_SEND(37), {35,0,0xE0,0x00,0x00,0x00,0x16,0x17,0x27,0x2D,0x3C,0x0A,
+ 0x13,0x12,0x17,0x19,0x17,0x17,0x12,0x16,
+ 0x00,0x00,0x00,0x16,0x17,0x27,0x2D,0x3C,0x0A,
+ 0x13,0x12,0x17,0x19,0x17,0x17,0x12,0x16}},
+
+
+
+{LCM_SEND(2), {0x11,0x00}},
+{LCM_SLEEP(120),},
+
+{LCM_SEND(2), {0x29,0x00}},
+{LCM_SLEEP(10),},
+
+};
+
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(20)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static int32_t fl10802_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug(KERN_DEBUG "fl10802_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+ return 0;
+}
+
+static uint32_t fl10802_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[5] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel lcd_fl10802_mipi read id!\n");
+ #if 1
+ //self->info.mipi->ops->mipi_set_lp_mode();
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ udelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK) * 1000);
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x04, 3,(uint8_t *)read_data);
+ printk("kernel lcd_fl10802_mipi read id 0xa1 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+ mipi_eotp_set(1,1);
+ if((0x10 == read_data[0])&&(0x80== read_data[1])&&(0x1A == read_data[2])){
+ printk(" kernel lcd_fl10802_mipi read id success!\n");
+ return 0x1080;
+ }
+ }
+ #endif
+ printk("lcd_fl10802_mipi identify fail!\n");
+ //self->info.mipi->ops->mipi_set_hs_mode();
+ return 0x0;
+}
+
+static uint32_t fl10802_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_fl10802_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ printk("lcd_fl10802_mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_fl10802a_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ printk("lcd_fl10802_mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t fl10802_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ pr_debug("fl10802_check_esd!\n");
+ power_mode = fl10802_readpowermode(self);
+ //power_mode = 0x0;
+ if(power_mode == 0x9c){
+ pr_debug("fl10802_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("fl10802_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+
+static int32_t fl10802_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "fl10802_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(1,1);
+ return 0;
+}
+
+static struct panel_operations lcd_fl10802_mipi_operations = {
+ .panel_init = fl10802_mipi_init,
+ .panel_readid = fl10802_readid,
+ .panel_esd_check = fl10802_check_esd,
+ .panel_enter_sleep = fl10802_enter_sleep,
+};
+
+static struct timing_rgb lcd_fl10802_mipi_timing = {
+ .hfp = 80, /* unit: pixel */
+ .hbp = 80,
+ .hsync = 10,
+ .vfp = 17, /*unit: line*/
+ .vbp = 11,
+ .vsync = 3,
+};
+
+static struct info_mipi lcd_fl10802_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 400*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ //.te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_fl10802_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_fl10802_mipi_spec = {
+ .width = 480,
+ .height = 800,
+ .fps = 59,
+ .reset_timing = {5,10,120},
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_fl10802_mipi_info
+ },
+ .ops = &lcd_fl10802_mipi_operations,
+};
+
+struct panel_cfg lcd_fl10802_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x1080,
+ .lcd_name = "lcd_fl10802_mipi",
+ .panel = &lcd_fl10802_mipi_spec,
+};
+
+static int __init lcd_fl10802_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_fl10802_mipi);
+}
+
+subsys_initcall(lcd_fl10802_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_hx8363_mcu.c b/drivers/video/sprdfb/lcd/lcd_hx8363_mcu.c new file mode 100644 index 00000000..1f7e4875 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8363_mcu.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + + +static int32_t hx8363_init(struct panel_spec *self) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + printk("hx8363_init\n"); + + send_cmd(0xB9); // SET password + send_data(0xFF); // + send_data(0x83); // + send_data(0x63); // + + send_cmd(0xB0);//Enable internal oscillator + send_data(0x01); + send_data(0x0B); + + send_cmd(0xB1); + send_data(0x01); + send_data(0x00); + send_data(0x44); + send_data(0x08); + send_data(0x01); + send_data(0x11); + send_data(0x11); + send_data(0x36); + send_data(0x3E); + send_data(0x3F); + send_data(0x3F); + send_data(0x40); + send_data(0x32); + send_data(0x00); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + + send_cmd(0xB2); // SET DISP + send_data(0x08); // + send_data(0x00); // + + send_cmd(0xB4); + send_data(0x00);//Column inversion + send_data(0x18); + send_data(0x9C); + send_data(0x08); + send_data(0x18); + send_data(0x04); + send_data(0x72);//72 + + send_cmd(0xB6);//Set_VCOM + send_data(0x1B); + + send_cmd(0xCC);// SET Panel + send_data(0x01); // + + LCD_DelayMS(5); + + send_cmd(0xE0); // SET Gamma + send_data(0x00); + send_data(0x05); + send_data(0x07); + send_data(0x0C); + send_data(0x13); + send_data(0x2F); + send_data(0x0B); + send_data(0x1D); + send_data(0x86); + send_data(0x0D); + send_data(0x91); + send_data(0x16); + send_data(0x99); + send_data(0x16); + send_data(0x16); + send_data(0x09); + send_data(0x05); + send_data(0x00); + send_data(0x05); + send_data(0x07); + send_data(0x0C); + send_data(0x13); + send_data(0x2F); + send_data(0x0B); + send_data(0x1D); + send_data(0x86); + send_data(0x0D); + send_data(0x91); + send_data(0x16); + send_data(0x99); + send_data(0x16); + send_data(0x16); + send_data(0x09); + send_data(0x05); + + send_cmd(0xC1); //COLMOD + send_data(0x01); // + //R + send_data(0x07 ); + send_data(0x0A ); + send_data(0x1A ); + send_data(0x2F ); + send_data(0x3E ); + send_data(0x4A ); + send_data(0x52 ); + send_data(0x5A ); + send_data(0x62 ); + send_data(0x69 ); + send_data(0x70 ); + send_data(0x76 ); + send_data(0x7D ); + send_data(0x82 ); + send_data(0x86 ); + send_data(0x8C ); + send_data(0x93 ); + send_data(0x9A ); + send_data(0x9F ); + send_data(0xA4 ); + send_data(0xA9 ); + send_data(0xB0 ); + send_data(0xB6 ); + send_data(0xBB ); + send_data(0xC2 ); + send_data(0xC9 ); + send_data(0xCF ); + send_data(0xD7 ); + send_data(0xE0 ); + send_data(0xE7 ); + send_data(0xEF ); + send_data(0xF8 ); + send_data(0xFF ); + send_data(0x34 ); + send_data(0x1E ); + send_data(0x92 ); + send_data(0x9E ); + send_data(0x01 ); + send_data(0xE6 ); + send_data(0x08 ); + send_data(0x6F ); + send_data(0x02 ); + //G + send_data(0x07 ); + send_data(0x0A ); + send_data(0x1A ); + send_data(0x2F ); + send_data(0x3E ); + send_data(0x4A ); + send_data(0x52 ); + send_data(0x5A ); + send_data(0x62 ); + send_data(0x69 ); + send_data(0x70 ); + send_data(0x76 ); + send_data(0x7D ); + send_data(0x82 ); + send_data(0x86 ); + send_data(0x8C ); + send_data(0x93 ); + send_data(0x9A ); + send_data(0x9F ); + send_data(0xA4 ); + send_data(0xA9 ); + send_data(0xB0 ); + send_data(0xB6 ); + send_data(0xBB ); + send_data(0xC2 ); + send_data(0xC9 ); + send_data(0xCF ); + send_data(0xD7 ); + send_data(0xE0 ); + send_data(0xE7 ); + send_data(0xEF ); + send_data(0xF8 ); + send_data(0xFF ); + send_data(0x34 ); + send_data(0x1E ); + send_data(0x92 ); + send_data(0x9E ); + send_data(0x01 ); + send_data(0xE6 ); + send_data(0x08 ); + send_data(0x6F ); + send_data(0x02 ); + //B + send_data(0x07 ); + send_data(0x0A ); + send_data(0x1A ); + send_data(0x2F ); + send_data(0x3E ); + send_data(0x4A ); + send_data(0x52 ); + send_data(0x5A ); + send_data(0x62 ); + send_data(0x69 ); + send_data(0x70 ); + send_data(0x76 ); + send_data(0x7D ); + send_data(0x82 ); + send_data(0x86 ); + send_data(0x8C ); + send_data(0x93 ); + send_data(0x9A ); + send_data(0x9F ); + send_data(0xA4 ); + send_data(0xA9 ); + send_data(0xB0 ); + send_data(0xB6 ); + send_data(0xBB ); + send_data(0xC2 ); + send_data(0xC9 ); + send_data(0xCF ); + send_data(0xD7 ); + send_data(0xE0 ); + send_data(0xE7 ); + send_data(0xEF ); + send_data(0xF8 ); + send_data(0xFF ); + send_data(0x34 ); + send_data(0x1E ); + send_data(0x92 ); + send_data(0x9E ); + send_data(0x01 ); + send_data(0xE6 ); + send_data(0x08 ); + send_data(0x6F ); + send_data(0x02 ); + + send_cmd(0x3A); //COLMOD + send_data(0x07); // + + send_cmd(0x11);//Sleep Out + LCD_DelayMS(120); + + send_cmd(0xC2);// SET DISPIF + send_data(0x04); //24bit + send_cmd(0x35); //Tearing Effect + send_data(0x00); // + send_cmd(0x36); + send_data(0x02); // + send_cmd(0x29); + LCD_DelayMS(10); + send_cmd(0x2c); + + return 0; +} + +static int32_t hx8363_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + if(is_sleep==1){ + //Sleep In + send_cmd(0x28); + LCD_DelayMS(120); + send_cmd(0x10); + LCD_DelayMS(120); + }else{ + //Sleep Out + send_cmd(0x11); + LCD_DelayMS(120); + send_cmd(0x29); + LCD_DelayMS(120); + } + + return 0; +} + + + + +static int32_t hx8363_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("hx8363_set_window: %d, %d, %d, %d\n",left, top, right, bottom); + + send_cmd(0x2A); // col + send_data((left >> 8)); + send_data((left & 0xFF)); + send_data((right >> 8)); + send_data((right & 0xFF)); + + send_cmd(0x2B); // row + send_data((top >> 8)); + send_data((top & 0xFF)); + send_data((bottom >> 8)); + send_data((bottom & 0xFF)); + + send_cmd(0x2C); //Write data + + return 0; +} +static int32_t hx8363_invalidate(struct panel_spec *self) +{ + pr_debug("hx8363_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + + + +static int32_t hx8363_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + pr_debug("hx8363_invalidate_rect \n"); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t hx8363_read_id(struct panel_spec *self) +{ + int32_t id = 0; + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + read_data_t read_data = self->info.mcu->ops->read_data; + send_data_t send_data = self->info.mcu->ops->send_data; + + //Get ID + + + return 0x18; // id; +} + +static struct panel_operations lcd_hx8363_mcu_operations = { + .panel_init = hx8363_init, + .panel_set_window = hx8363_set_window, + .panel_invalidate_rect= hx8363_invalidate_rect, + .panel_invalidate = hx8363_invalidate, + .panel_enter_sleep = hx8363_enter_sleep, + .panel_readid = hx8363_read_id +}; + +static struct timing_mcu lcd_hx8363_mcu_timing[] = { +[MCU_LCD_REGISTER_TIMING] = { // read/write register timing + .rcss = 15, // 15ns + .rlpw = 60, + .rhpw = 60, + .wcss = 10, + .wlpw = 35, + .whpw = 35, + }, +[MCU_LCD_GRAM_TIMING] = { // read/write gram timing + .rcss = 15, // 15ns + .rlpw = 60, + .rhpw = 60, + .wcss = 0, + .wlpw = 16, + .whpw = 16, + }, +}; + +static struct info_mcu lcd_hx8363_mcu_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 24, + .bpp = 24, + .timing =lcd_hx8363_mcu_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8363_mcu_spec = { + .width = 480, + .height = 854, + .type = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_hx8363_mcu_info + }, + .ops = &lcd_hx8363_mcu_operations, +}; + +struct panel_cfg lcd_hx8363_mcu = { + /* this panel may on both CS0/1 */ + .dev_id = SPRDFB_UNDEFINELCD_ID, + .lcd_id = 0x18, + .lcd_name = "lcd_hx8363_mcu", + .panel = &lcd_hx8363_mcu_spec, +}; + +static int __init lcd_hx8363_mcu_init(void) +{ + return sprdfb_panel_register(&lcd_hx8363_mcu); +} + +subsys_initcall(lcd_hx8363_mcu_init); diff --git a/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi.c b/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi.c new file mode 100644 index 00000000..18742b53 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi.c @@ -0,0 +1,445 @@ +/* drivers/video/sc8810/lcd_hx8363_rgb_spi.c + * + * + * + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +#define HX8363_SpiWriteCmd(cmd) \ +{ \ + spi_send_cmd((cmd & 0xFF));\ +} + +#define HX8363_SpiWriteData(data)\ +{ \ + spi_send_data((data & 0xFF));\ +} + +static int32_t hx8363_init(struct panel_spec *self) +{ + uint32_t test_data[8] = {0}; + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 480; + uint32_t bottom = 854; + uint32_t data = 0; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + + printk("hx8363_init\n"); + + HX8363_SpiWriteCmd(0xB9); // SET password + HX8363_SpiWriteData(0xFF); // + HX8363_SpiWriteData(0x83); // + HX8363_SpiWriteData(0x63); // + + HX8363_SpiWriteCmd(0xB1); + HX8363_SpiWriteData(0x01); + HX8363_SpiWriteData(0x00); + HX8363_SpiWriteData(0x44); + HX8363_SpiWriteData(0x08); + HX8363_SpiWriteData(0x01); +// HX8363_SpiWriteData(0x0E); // +// HX8363_SpiWriteData(0x0E); // +// HX8363_SpiWriteData(0x1B); //the lower ,Saturation is better +// HX8363_SpiWriteData(0x23); //the lower ,Saturation is better + HX8363_SpiWriteData(0x0F); // + HX8363_SpiWriteData(0x0F); // + HX8363_SpiWriteData(0x22); //the lower ,Saturation is better + HX8363_SpiWriteData(0x2A); //the lower ,Saturation is better + HX8363_SpiWriteData(0x3F); + HX8363_SpiWriteData(0x3F); + HX8363_SpiWriteData(0x40); + HX8363_SpiWriteData(0x32); + HX8363_SpiWriteData(0x00); + HX8363_SpiWriteData(0xE6); + HX8363_SpiWriteData(0xE6); + HX8363_SpiWriteData(0xE6); + HX8363_SpiWriteData(0xE6); + HX8363_SpiWriteData(0xE6); + + HX8363_SpiWriteCmd(0xB2); // SET DISP + HX8363_SpiWriteData(0x08); // + HX8363_SpiWriteData(0x03); // + + HX8363_SpiWriteCmd(0xB4); + HX8363_SpiWriteData(0x00);//Column inversion + HX8363_SpiWriteData(0x18); + HX8363_SpiWriteData(0x9C); + HX8363_SpiWriteData(0x08); + HX8363_SpiWriteData(0x18); + HX8363_SpiWriteData(0x04); + HX8363_SpiWriteData(0x82); + + HX8363_SpiWriteCmd(0xB6); //Set_VCOM + HX8363_SpiWriteData(0x1B); //0x10 + + HX8363_SpiWriteCmd(0xCC); // SET Panel + HX8363_SpiWriteData(0x01); // + msleep(5); + + HX8363_SpiWriteCmd(0xE0); // SET Gamma + HX8363_SpiWriteData(0x00); + HX8363_SpiWriteData(0x05); + HX8363_SpiWriteData(0x07); + HX8363_SpiWriteData(0x0C); + HX8363_SpiWriteData(0x13); + HX8363_SpiWriteData(0x2F); + HX8363_SpiWriteData(0x0B); + HX8363_SpiWriteData(0x1D); + HX8363_SpiWriteData(0x86); + HX8363_SpiWriteData(0x0D); + HX8363_SpiWriteData(0x91); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x99); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x09); + HX8363_SpiWriteData(0x05); + HX8363_SpiWriteData(0x00); + HX8363_SpiWriteData(0x05); + HX8363_SpiWriteData(0x07); + HX8363_SpiWriteData(0x0C); + HX8363_SpiWriteData(0x13); + HX8363_SpiWriteData(0x2F); + HX8363_SpiWriteData(0x0B); + HX8363_SpiWriteData(0x1D); + HX8363_SpiWriteData(0x86); + HX8363_SpiWriteData(0x0D); + HX8363_SpiWriteData(0x91); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x99); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x16); + HX8363_SpiWriteData(0x09); + HX8363_SpiWriteData(0x05); + + HX8363_SpiWriteCmd(0xC1); //COLMOD + HX8363_SpiWriteData(0x01); // + //R + HX8363_SpiWriteData(0x07 ); + HX8363_SpiWriteData(0x0A ); + HX8363_SpiWriteData(0x1A ); + HX8363_SpiWriteData(0x2F ); + HX8363_SpiWriteData(0x3E ); + HX8363_SpiWriteData(0x4A ); + HX8363_SpiWriteData(0x52 ); + HX8363_SpiWriteData(0x5A ); + HX8363_SpiWriteData(0x62 ); + HX8363_SpiWriteData(0x69 ); + HX8363_SpiWriteData(0x70 ); + HX8363_SpiWriteData(0x76 ); + HX8363_SpiWriteData(0x7D ); + HX8363_SpiWriteData(0x82 ); + HX8363_SpiWriteData(0x86 ); + HX8363_SpiWriteData(0x8C ); + HX8363_SpiWriteData(0x93 ); + HX8363_SpiWriteData(0x9A ); + HX8363_SpiWriteData(0x9F ); + HX8363_SpiWriteData(0xA4 ); + HX8363_SpiWriteData(0xA9 ); + HX8363_SpiWriteData(0xB0 ); + HX8363_SpiWriteData(0xB6 ); + HX8363_SpiWriteData(0xBB ); + HX8363_SpiWriteData(0xC2 ); + HX8363_SpiWriteData(0xC9 ); + HX8363_SpiWriteData(0xCF ); + HX8363_SpiWriteData(0xD7 ); + HX8363_SpiWriteData(0xE0 ); + HX8363_SpiWriteData(0xE7 ); + HX8363_SpiWriteData(0xEF ); + HX8363_SpiWriteData(0xF8 ); + HX8363_SpiWriteData(0xFF ); + HX8363_SpiWriteData(0x34 ); + HX8363_SpiWriteData(0x1E ); + HX8363_SpiWriteData(0x92 ); + HX8363_SpiWriteData(0x9E ); + HX8363_SpiWriteData(0x01 ); + HX8363_SpiWriteData(0xE6 ); + HX8363_SpiWriteData(0x08 ); + HX8363_SpiWriteData(0x6F ); + HX8363_SpiWriteData(0x02 ); + //G + HX8363_SpiWriteData(0x07 ); + HX8363_SpiWriteData(0x0A ); + HX8363_SpiWriteData(0x1A ); + HX8363_SpiWriteData(0x2F ); + HX8363_SpiWriteData(0x3E ); + HX8363_SpiWriteData(0x4A ); + HX8363_SpiWriteData(0x52 ); + HX8363_SpiWriteData(0x5A ); + HX8363_SpiWriteData(0x62 ); + HX8363_SpiWriteData(0x69 ); + HX8363_SpiWriteData(0x70 ); + HX8363_SpiWriteData(0x76 ); + HX8363_SpiWriteData(0x7D ); + HX8363_SpiWriteData(0x82 ); + HX8363_SpiWriteData(0x86 ); + HX8363_SpiWriteData(0x8C ); + HX8363_SpiWriteData(0x93 ); + HX8363_SpiWriteData(0x9A ); + HX8363_SpiWriteData(0x9F ); + HX8363_SpiWriteData(0xA4 ); + HX8363_SpiWriteData(0xA9 ); + HX8363_SpiWriteData(0xB0 ); + HX8363_SpiWriteData(0xB6 ); + HX8363_SpiWriteData(0xBB ); + HX8363_SpiWriteData(0xC2 ); + HX8363_SpiWriteData(0xC9 ); + HX8363_SpiWriteData(0xCF ); + HX8363_SpiWriteData(0xD7 ); + HX8363_SpiWriteData(0xE0 ); + HX8363_SpiWriteData(0xE7 ); + HX8363_SpiWriteData(0xEF ); + HX8363_SpiWriteData(0xF8 ); + HX8363_SpiWriteData(0xFF ); + HX8363_SpiWriteData(0x34 ); + HX8363_SpiWriteData(0x1E ); + HX8363_SpiWriteData(0x92 ); + HX8363_SpiWriteData(0x9E ); + HX8363_SpiWriteData(0x01 ); + HX8363_SpiWriteData(0xE6 ); + HX8363_SpiWriteData(0x08 ); + HX8363_SpiWriteData(0x6F ); + HX8363_SpiWriteData(0x02 ); + //B + HX8363_SpiWriteData(0x07 ); + HX8363_SpiWriteData(0x0A ); + HX8363_SpiWriteData(0x1A ); + HX8363_SpiWriteData(0x2F ); + HX8363_SpiWriteData(0x3E ); + HX8363_SpiWriteData(0x4A ); + HX8363_SpiWriteData(0x52 ); + HX8363_SpiWriteData(0x5A ); + HX8363_SpiWriteData(0x62 ); + HX8363_SpiWriteData(0x69 ); + HX8363_SpiWriteData(0x70 ); + HX8363_SpiWriteData(0x76 ); + HX8363_SpiWriteData(0x7D ); + HX8363_SpiWriteData(0x82 ); + HX8363_SpiWriteData(0x86 ); + HX8363_SpiWriteData(0x8C ); + HX8363_SpiWriteData(0x93 ); + HX8363_SpiWriteData(0x9A ); + HX8363_SpiWriteData(0x9F ); + HX8363_SpiWriteData(0xA4 ); + HX8363_SpiWriteData(0xA9 ); + HX8363_SpiWriteData(0xB0 ); + HX8363_SpiWriteData(0xB6 ); + HX8363_SpiWriteData(0xBB ); + HX8363_SpiWriteData(0xC2 ); + HX8363_SpiWriteData(0xC9 ); + HX8363_SpiWriteData(0xCF ); + HX8363_SpiWriteData(0xD7 ); + HX8363_SpiWriteData(0xE0 ); + HX8363_SpiWriteData(0xE7 ); + HX8363_SpiWriteData(0xEF ); + HX8363_SpiWriteData(0xF8 ); + HX8363_SpiWriteData(0xFF ); + HX8363_SpiWriteData(0x34 ); + HX8363_SpiWriteData(0x1E ); + HX8363_SpiWriteData(0x92 ); + HX8363_SpiWriteData(0x9E ); + HX8363_SpiWriteData(0x01 ); + HX8363_SpiWriteData(0xE6 ); + HX8363_SpiWriteData(0x08 ); + HX8363_SpiWriteData(0x6F ); + HX8363_SpiWriteData(0x02 ); + + HX8363_SpiWriteCmd(0x3A); //COLMOD + HX8363_SpiWriteData(0x77); // + + HX8363_SpiWriteCmd(0x11);//Sleep Out + msleep(120); + HX8363_SpiWriteCmd(0x35); //Tearing Effect + HX8363_SpiWriteData(0x00); // + HX8363_SpiWriteCmd(0x36); + HX8363_SpiWriteData(0x02); + HX8363_SpiWriteCmd(0x29); + msleep(10); + HX8363_SpiWriteCmd(0x2C); + +} + +static int32_t hx8363_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + + if(is_sleep==1){ + //Sleep In + HX8363_SpiWriteCmd(0x28); + msleep(120); + HX8363_SpiWriteCmd(0x10); + msleep(10); + }else{ + //Sleep Out + HX8363_SpiWriteCmd(0x11); + msleep(120); + HX8363_SpiWriteCmd(0x29); + msleep(10); + } + + return 0; +} + + + + +static int32_t hx8363_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + uint32_t *test_data[4] = {0}; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; +#if 0 + + printk("zxdbg add -hx8363_set_window: %d, %d, %d, %d\n",left, top, right, bottom); + + HX8363_SpiWriteCmd(0x2A00); + HX8363_SpiWriteData((left>>8));// set left address + HX8363_SpiWriteData((left&0xff)); + HX8363_SpiWriteData((right>>8));// set right address + HX8363_SpiWriteData((right&0xff)); + + HX8363_SpiWriteCmd(0x2B00); + HX8363_SpiWriteData((top>>8));// set left address + HX8363_SpiWriteData((top&0xff)); + HX8363_SpiWriteData((bottom>>8));// set bottom address + HX8363_SpiWriteData((bottom&0xff)); + +// HX8363_SpiWriteCmd(0x2C00); + + HX8363_SpiWriteCmd(0x2A00); + spi_read(test_data); + spi_read(test_data+1); + HX8363_SpiWriteCmd(0x2B00); + spi_read(test_data+2); + spi_read(test_data+3); +#endif +// printk("zxdbg add -hx8363_read read: %x, %x, %x, %x\n",test_data[0], test_data[1], test_data[2], test_data[3]); + + return 0; +} +static int32_t hx8363_invalidate(struct panel_spec *self) +{ +// printk("hx8363_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + + + +static int32_t hx8363_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ +// printk("hx8363_invalidate_rect \n"); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t hx8363_read_id(struct panel_spec *self) +{ + int32_t id = 0x62; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + printk("sprdfb hx8363_read_id \n"); + HX8363_SpiWriteCmd(0xB9); // SET password + HX8363_SpiWriteData(0xFF); // + HX8363_SpiWriteData(0x83); // + HX8363_SpiWriteData(0x63); // + + HX8363_SpiWriteCmd(0xFE); // SET SPI READ INDEX + HX8363_SpiWriteData(0xF4); // GETHXID + HX8363_SpiWriteCmd(0xFF); // GET SPI READ + + spi_read(&id); + id &= 0xff; + printk(" hx8363_read_id kernel id = %x\n",id); +// return id; + return 0x63; +} + +static struct panel_operations lcd_hx8363_rgb_spi_operations = { + .panel_init = hx8363_init, + .panel_set_window = hx8363_set_window, + .panel_invalidate_rect= hx8363_invalidate_rect, + .panel_invalidate = hx8363_invalidate, + .panel_enter_sleep = hx8363_enter_sleep, + .panel_readid = hx8363_read_id +}; + +static struct timing_rgb lcd_hx8363_rgb_timing = { + .hfp = 15,//10, /* unit: pixel */ + .hbp = 15,//6, + .hsync = 10, //8, + .vfp = 8, // 3, /*unit: line*/ + .vbp = 8, // 3, + .vsync = 6, // 4, +}; + +static struct spi_info lcd_hx8363_rgb_spi_info = { + .ops = NULL, +}; + +static struct info_rgb lcd_hx8363_rgb_info = { + .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_SPI, + .video_bus_width = 24, /*18,16*/ + .h_sync_pol = SPRDFB_POLARITY_NEG, + .v_sync_pol = SPRDFB_POLARITY_NEG, + .de_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_hx8363_rgb_timing, + .bus_info = { + .spi = &lcd_hx8363_rgb_spi_info, + } +}; + +struct panel_spec lcd_panel_hx8363_rgb_spi_spec = { + .width = 480, + .height = 854, + .reset_timing = {20, 10, 120}, + .fps = 61, + .type = LCD_MODE_RGB, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .rgb = &lcd_hx8363_rgb_info + }, + .ops = &lcd_hx8363_rgb_spi_operations, +}; + +struct panel_cfg lcd_hx8363_rgb_spi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x63, + .lcd_name = "lcd_hx8363_rgb_spi", + .panel = &lcd_panel_hx8363_rgb_spi_spec, +}; +static int __init lcd_hx8363_rgb_spi_init(void) +{ + return sprdfb_panel_register(&lcd_hx8363_rgb_spi); +} + +subsys_initcall(lcd_hx8363_rgb_spi_init); diff --git a/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi_viva.c b/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi_viva.c new file mode 100644 index 00000000..76b8b12a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8363_rgb_spi_viva.c @@ -0,0 +1,442 @@ +/* drivers/video/sc8810/lcd_hx8363_rgb_spi.c + * + * + * + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + + + +#define HX8363_SpiWriteCmd(cmd) \ +{ \ + spi_send_cmd((cmd & 0xFF));\ +} + +#define HX8363_SpiWriteData(data)\ +{ \ + spi_send_data((data & 0xFF));\ +} +#define HX8369b_SpiWriteCmd(cmd) \ +{ \ + spi_send_cmd((cmd & 0xFF));\ +} + +#define HX8369b_SpiWriteData(data)\ +{ \ + spi_send_data((data & 0xFF));\ +} +static int32_t hx8363_init(struct panel_spec *self) +{ + uint32_t test_data[8] = {0}; + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 480; + uint32_t bottom = 800; + uint32_t data = 0; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + + printk("hx8363_init\n"); + + HX8369b_SpiWriteCmd(0xB9); // SET EXTC + HX8369b_SpiWriteData(0xFF); // + HX8369b_SpiWriteData(0x83); // + HX8369b_SpiWriteData(0x69); // + + //Power Setting Sequence + + HX8369b_SpiWriteCmd(0xB1); //Set Power + HX8369b_SpiWriteData(0x0B); + HX8369b_SpiWriteData(0x83); + HX8369b_SpiWriteData(0xA7); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x11); + HX8369b_SpiWriteData(0x11); + HX8369b_SpiWriteData(0x08); + HX8369b_SpiWriteData(0x08); + HX8369b_SpiWriteData(0x0C); + HX8369b_SpiWriteData(0x22); + + + HX8369b_SpiWriteCmd(0xC6); //Set Source EQ + HX8369b_SpiWriteData(0x41); + HX8369b_SpiWriteData(0xFF); + HX8369b_SpiWriteData(0x7A); + HX8369b_SpiWriteData(0xFF); + + HX8369b_SpiWriteCmd(0xE3); //Set Source EQ + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + + HX8369b_SpiWriteCmd(0xC0); //Set Source Option + HX8369b_SpiWriteData(0x73); + HX8369b_SpiWriteData(0x50); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x34); + HX8369b_SpiWriteData(0xC4); + HX8369b_SpiWriteData(0x00); + + // Initializing Sequence + + HX8369b_SpiWriteCmd(0x3A); //Interface Pixel + HX8369b_SpiWriteData(0x70); + + HX8369b_SpiWriteCmd(0xB3); //Set RGB Interface + HX8369b_SpiWriteData(0x83); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x31); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x01); + HX8369b_SpiWriteData(0x13); + HX8369b_SpiWriteData(0x06); + + HX8369b_SpiWriteCmd(0xB4); //Set column inversion + HX8369b_SpiWriteData(0x00); + + HX8369b_SpiWriteCmd(0xCC); //Set DGC + HX8369b_SpiWriteData(0x0C); + + HX8369b_SpiWriteCmd(0xEA); //Set Color + HX8369b_SpiWriteData(0x72); + + HX8369b_SpiWriteCmd(0xB2); //Set Display + HX8369b_SpiWriteData(0x03); + + HX8369b_SpiWriteCmd(0xD5); //GIP Timing SET + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x0D); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x12); + HX8369b_SpiWriteData(0x40); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x01); + HX8369b_SpiWriteData(0x60); + HX8369b_SpiWriteData(0x37); + HX8369b_SpiWriteData(0x00); + + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x0F); + HX8369b_SpiWriteData(0x01); + HX8369b_SpiWriteData(0x05); + HX8369b_SpiWriteData(0x47); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x18); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x89); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x11); + HX8369b_SpiWriteData(0x33); + HX8369b_SpiWriteData(0x55); + HX8369b_SpiWriteData(0x77); + HX8369b_SpiWriteData(0x31); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x98); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x66); + HX8369b_SpiWriteData(0x44); + HX8369b_SpiWriteData(0x22); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x02); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x89); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x22); + HX8369b_SpiWriteData(0x44); + HX8369b_SpiWriteData(0x66); + HX8369b_SpiWriteData(0x20); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x98); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x77); + HX8369b_SpiWriteData(0x55); + HX8369b_SpiWriteData(0x33); + HX8369b_SpiWriteData(0x11); + HX8369b_SpiWriteData(0x13); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x01); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0xCF); + HX8369b_SpiWriteData(0xFF); + HX8369b_SpiWriteData(0xFF); + HX8369b_SpiWriteData(0x03); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0xCF); + HX8369b_SpiWriteData(0xFF); + HX8369b_SpiWriteData(0xFF); + HX8369b_SpiWriteData(0x20); + HX8369b_SpiWriteData(0x8C); + HX8369b_SpiWriteData(0x5A); + + //Gamam Setting Sequence + + HX8369b_SpiWriteCmd(0xE0); //Gamma + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x02); + HX8369b_SpiWriteData(0x0D); + HX8369b_SpiWriteData(0x0C); + HX8369b_SpiWriteData(0x3F); + HX8369b_SpiWriteData(0x19); + HX8369b_SpiWriteData(0x2D); + HX8369b_SpiWriteData(0x04); + HX8369b_SpiWriteData(0x0F); + HX8369b_SpiWriteData(0x0E); + HX8369b_SpiWriteData(0x14); + HX8369b_SpiWriteData(0x17); + + HX8369b_SpiWriteData(0x15); + HX8369b_SpiWriteData(0x16); + HX8369b_SpiWriteData(0x10); + HX8369b_SpiWriteData(0x11); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x00); + HX8369b_SpiWriteData(0x02); + HX8369b_SpiWriteData(0x0C); + HX8369b_SpiWriteData(0x12); + HX8369b_SpiWriteData(0x3F); + HX8369b_SpiWriteData(0x19); + HX8369b_SpiWriteData(0x2C); + HX8369b_SpiWriteData(0x05); + HX8369b_SpiWriteData(0x08); + HX8369b_SpiWriteData(0x0E); + HX8369b_SpiWriteData(0x12); + HX8369b_SpiWriteData(0x16); + HX8369b_SpiWriteData(0x14); + HX8369b_SpiWriteData(0x15); + HX8369b_SpiWriteData(0x10); + HX8369b_SpiWriteData(0x12); + HX8369b_SpiWriteData(0x01); + + //Dispaly on + HX8369b_SpiWriteCmd(0x11); + mdelay(120); + HX8369b_SpiWriteCmd(0x29); + + +} + +static int32_t hx8363_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + + if(is_sleep==1){ + //Sleep In + HX8363_SpiWriteCmd(0x28); + mdelay(120); + HX8363_SpiWriteCmd(0x10); + mdelay(10); + }else{ + //Sleep Out + HX8363_SpiWriteCmd(0x11); + mdelay(120); + HX8363_SpiWriteCmd(0x29); + mdelay(10); + } + + return 0; +} + + + + +static int32_t hx8363_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + uint32_t *test_data[4] = {0}; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; +#if 0 + + printk("zxdbg add -hx8363_set_window: %d, %d, %d, %d\n",left, top, right, bottom); + + HX8363_SpiWriteCmd(0x2A00); + HX8363_SpiWriteData((left>>8));// set left address + HX8363_SpiWriteData((left&0xff)); + HX8363_SpiWriteData((right>>8));// set right address + HX8363_SpiWriteData((right&0xff)); + + HX8363_SpiWriteCmd(0x2B00); + HX8363_SpiWriteData((top>>8));// set left address + HX8363_SpiWriteData((top&0xff)); + HX8363_SpiWriteData((bottom>>8));// set bottom address + HX8363_SpiWriteData((bottom&0xff)); + +// HX8363_SpiWriteCmd(0x2C00); + + HX8363_SpiWriteCmd(0x2A00); + spi_read(test_data); + spi_read(test_data+1); + HX8363_SpiWriteCmd(0x2B00); + spi_read(test_data+2); + spi_read(test_data+3); +#endif +// printk("zxdbg add -hx8363_read read: %x, %x, %x, %x\n",test_data[0], test_data[1], test_data[2], test_data[3]); + + return 0; +} +static int32_t hx8363_invalidate(struct panel_spec *self) +{ +// printk("hx8363_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + + + +static int32_t hx8363_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ +// printk("hx8363_invalidate_rect \n"); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t hx8363_read_id(struct panel_spec *self) +{ + int32_t id = 0x62; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; +/* + printk("sprdfb hx8363_read_id \n"); + HX8363_SpiWriteCmd(0xB9); // SET password + HX8363_SpiWriteData(0xFF); // + HX8363_SpiWriteData(0x83); // + HX8363_SpiWriteData(0x63); // + + HX8363_SpiWriteCmd(0xFE); // SET SPI READ INDEX + HX8363_SpiWriteData(0xF4); // GETHXID + HX8363_SpiWriteCmd(0xFF); // GET SPI READ + + spi_read(&id); +*/ + id &= 0xff; + printk(" hx8363_read_id kernel id = %x\n",id); +// return id; + return 0x63; +} + +static struct panel_operations lcd_hx8363_rgb_spi_operations = { + .panel_init = hx8363_init, + .panel_set_window = hx8363_set_window, + .panel_invalidate_rect= hx8363_invalidate_rect, + .panel_invalidate = hx8363_invalidate, + .panel_enter_sleep = hx8363_enter_sleep, + .panel_readid = hx8363_read_id +}; + +static struct timing_rgb lcd_hx8363_rgb_timing = { +#if 1 + .hfp = 30,//10, /* unit: pixel */ + .hbp = 55, //6, + .hsync = 10, //8, + .vfp = 6, // 3, /*unit: line*/ + .vbp = 19, // 3, + .vsync = 6, // 4, +#else + .hfp = 15,//10, /* unit: pixel */ + .hbp = 15,//6, + .hsync = 10, //8, + .vfp = 8, // 3, /*unit: line*/ + .vbp = 8, // 3, + .vsync = 6, // 4, +#endif +}; + +static struct spi_info lcd_hx8363_rgb_spi_info = { + .ops = NULL, +}; + +static struct info_rgb lcd_hx8363_rgb_info = { + .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_SPI, + .video_bus_width = 24, /*18,16*/ + .h_sync_pol = SPRDFB_POLARITY_NEG, + .v_sync_pol = SPRDFB_POLARITY_NEG, + .de_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_hx8363_rgb_timing, + .bus_info = { + .spi = &lcd_hx8363_rgb_spi_info, + } +}; + +struct panel_spec lcd_panel_hx8363_rgb_spi_spec = { + .width = 480, + .height = 800, + .fps = 61, + .type = LCD_MODE_RGB, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .rgb = &lcd_hx8363_rgb_info + }, + .ops = &lcd_hx8363_rgb_spi_operations, +}; + +struct panel_cfg lcd_hx8363_rgb_spi_spec_viva = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x63, + .lcd_name = "lcd_hx8363_rgb_spi", + .panel = &lcd_panel_hx8363_rgb_spi_spec, +}; + +static int __init lcd_hx8363_rgb_spi_init(void) +{ + return sprdfb_panel_register(&lcd_hx8363_rgb_spi_spec_viva); + +} + +subsys_initcall(lcd_hx8363_rgb_spi_init); diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369.c b/drivers/video/sprdfb/lcd/lcd_hx8369.c new file mode 100644 index 00000000..5c143a9a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "lcdpanel.h" + +static int32_t hx8369_init(struct panel_spec *self) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + /* SET password */ + send_cmd(0xB9); + send_data(0xFF); + send_data(0x83); + send_data(0x69); + + /* Set Power */ + send_cmd(0xB1); + send_data(0x9D); + send_data(0x00); + send_data(0x34); + send_data(0x07); + send_data(0x00); + send_data(0x0B); + send_data(0x0B); + send_data(0x1A); + send_data(0x22); + send_data(0x3F); + send_data(0x3F); + send_data(0x01); + send_data(0x23); + send_data(0x01); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + send_data(0xE6); + + /* SET Display 480x800 */ + send_cmd(0xB2); + send_data(0x00); + send_data(0x20); + send_data(0x03); + send_data(0x03); + send_data(0x70); + send_data(0x00); + send_data(0xFF); + send_data(0x00); + send_data(0x00); + send_data(0x00); + send_data(0x00); + send_data(0x03); + send_data(0x03); + send_data(0x00); + send_data(0x01); + + /* SET Display 480x800 */ + send_cmd(0xB4); + send_data(0x00); + send_data(0x18); + send_data(0x80); + send_data(0x06); + send_data(0x02); + + /* OSC */ + send_cmd(0xB0); + send_data(0x00); + send_data(0x09); /*05 42HZ 07 50HZ 0B 100% 67HZ */ + + /* SET VCOM */ + send_cmd(0xB6); + send_data(0x4A); + send_data(0x4A); + + /* SET GIP */ + send_cmd(0xD5); + send_data(0x00); + send_data(0x03); + send_data(0x03); + send_data(0x00); + send_data(0x01); + send_data(0x02); + + send_data(0x28); + send_data(0x70); + send_data(0x11); + send_data(0x13); + send_data(0x00); + send_data(0x00); + send_data(0x40); + send_data(0x06); + send_data(0x51); + send_data(0x07); + send_data(0x00); + send_data(0x00); + send_data(0x41); + send_data(0x06); + send_data(0x50); + send_data(0x07); + send_data(0x07); + send_data(0x0F); + send_data(0x04); + send_data(0x00); + + /* Set Gamma */ + send_cmd(0xE0); + send_data(0x00); + send_data(0x01); + send_data(0x04); + send_data(0x23); + send_data(0x22); + send_data(0x3F); + send_data(0x13); + send_data(0x39); + send_data(0x06); + send_data(0x0B); + send_data(0x0E); + send_data(0x12); + send_data(0x15); + send_data(0x13); + send_data(0x15); + send_data(0x13); + send_data(0x1B); + send_data(0x00); + send_data(0x01); + send_data(0x04); + send_data(0x23); + send_data(0x22); + send_data(0x3F); + send_data(0x13); + send_data(0x39); + send_data(0x06); + send_data(0x0B); + send_data(0x0E); + send_data(0x12); + send_data(0x15); + send_data(0x13); + send_data(0x15); + send_data(0x13); + send_data(0x1B); + send_cmd(0x35); /* TE on*/ + send_data(0x00); + + /* set CSEL */ + send_cmd(0x3A); + send_data(0x07); /* CSEL=0x06, 16bit-color CSEL=0x06, 18bit-color CSEL=0x07, 24bit-color */ + + /*24 bit don't need to set 2DH*/ + + /* Sleep Out */ + send_cmd(0x11); + + LCD_DelayMS(120); + + #if 0 + { /* for test the lcd */ + int i; + + send_cmd(0x2C); //Write data + for (i = 0; i < 480*800/3; i++) + send_data(0xff); + for (i = 0; i < 480*800/3; i++) + send_data(0xff00); + for (i = 0; i < 480*800/3; i++) + send_data(0xff0000); + } + #endif + /* Display On */ + send_cmd(0x29); + + LCD_DelayMS (120); + + /* Write data */ + send_cmd(0x2C); + + return 0; +} + +static int32_t hx8369_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("hx8369_set_window:%d, %d, %d, %d\n", left, top, right, bottom); + + /* col */ + send_cmd(0x2A); + send_data((left >> 8)); + send_data((left & 0xFF)); + send_data((right >> 8)); + send_data((right & 0xFF)); + + /* row */ + send_cmd(0x2B); + send_data((top >> 8)); + send_data((top & 0xFF)); + send_data((bottom >> 8)); + send_data((bottom & 0xFF)); + + /* Write data */ + send_cmd(0x2C); + + return 0; +} + + +static int32_t hx8369_invalidate(struct panel_spec *self) +{ + + return self->ops->panel_set_window(self, 0, 0, + self->width-1, self->height-1); + +} + +static int32_t hx8369_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("hx8369_invalidate_rect\n"); + + /* TE scanline */ + send_cmd(0x44); + send_data((top >> 8)); + send_data((top & 0xFF)); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t hx8369_set_direction(struct panel_spec *self, uint16_t direction) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("hx8369_set_direction\n"); + send_cmd(0x36); + + switch (direction) { + case LCD_DIRECT_NORMAL: + send_data(0); + break; + case LCD_DIRECT_ROT_90: + send_data(0xA0); + break; + case LCD_DIRECT_ROT_180: + send_data(0x60); + break; + case LCD_DIRECT_ROT_270: + send_data(0xB0); + break; + case LCD_DIRECT_MIR_H: + send_data(0x40); + break; + case LCD_DIRECT_MIR_V: + send_data(0x10); + break; + case LCD_DIRECT_MIR_HV: + send_data(0xE0); + break; + default: + pr_debug("unknown lcd direction!\n"); + send_data(0x0); + direction = LCD_DIRECT_NORMAL; + break; + } + + self->direction = direction; + + return 0; +} + +static int32_t hx8369_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + + if(is_sleep) { + /* Sleep In */ + send_cmd(0x28); + LCD_DelayMS(120); + send_cmd(0x10); + LCD_DelayMS(120); + } + else { +#if 1 + /* Sleep Out */ + send_cmd(0x11); + LCD_DelayMS(120); + send_cmd(0x29); + LCD_DelayMS(120); +#else + /* re init */ + se1f->ops->reset(self); + se1f->ops->lcd_init(self); +#endif + } + return 0; +} + +static uint32_t hx8369_read_id(struct panel_spec *self) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + read_data_t read_data = self->info.mcu->ops->read_data; + + send_cmd(0xB9); + send_data(0xFF); + send_data(0x83); + send_data(0x69); + + send_cmd(0xF4); + read_data(); + return read_data(); +} + +static struct panel_operations lcd_hx8369_operations = { + .panel_init = hx8369_init, + .panel_set_window = hx8369_set_window, + .panel_invalidate = hx8369_invalidate, + .panel_invalidate_rect = hx8369_invalidate_rect, + .panel_set_direction = hx8369_set_direction, + .panel_enter_sleep = hx8369_enter_sleep, + .panel_readid = hx8369_read_id, +}; + +static struct timing_mcu lcd_hx8369_timing[] = { +[LCD_REGISTER_TIMING] = { /* read/write register timing (ns) */ + .rcss = 25, /* 25 ns */ + .rlpw = 70, + .rhpw = 70, + .wcss = 10, + .wlpw = 50, + .whpw = 50, + }, +[LCD_GRAM_TIMING] = { /* read/write gram timing (ns) */ + .rcss = 25, + .rlpw = 70, + .rhpw = 70, + .wcss = 0, + .wlpw = 15, + .whpw = 24, + } +}; + +static struct info_mcu lcd_hx8369_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 24, + .timing = lcd_hx8369_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369_spec = { + .width = 480, + .height = 800, + .mode = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_hx8369_info, + }, + .ops = &lcd_hx8369_operations, +}; + +struct panel_cfg lcd_hx8369 = { + /* this panel may on both CS0/1 */ + .lcd_cs = -1, + .lcd_id = 0x69, + .lcd_name = "lcd_hx8369", + .panel = &lcd_hx8369_spec, +}; + +static int __init lcd_hx8369_init(void) +{ + return sprd_register_panel(&lcd_hx8369); +} + +subsys_initcall(lcd_hx8369_init); diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_grandneo_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_grandneo_mipi.c new file mode 100755 index 00000000..35c2178b --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_grandneo_mipi.c @@ -0,0 +1,338 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +//#define NEW_PANAL_BOE + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { +#ifndef NEW_PANAL_BOE + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SLEEP(10)}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x08,0x03,0x30,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x39,0x45,0x00,0x00,\ + 0x0D,0x44,0x39,0x37,0x00,0x00,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x37,0x59,\ + 0x18,0x10,0x00,0x00,0x05,0x00,0x00,0x40,0x28,0x69,0x40,0x00,0x00,0x00,0x00,0x00,0x26,0x49,0x08,0x00,0x00,0x00,\ + 0x04,0x00,0x00,0x51,0x39,0x78,0x50,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,\ + 0xF8,0x0F,0xFF,0xFF,0x07,0xF8,0x0F,0xFF,0xFF,0x00,0x20,0x5A,\ +}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(15),{13,0,0xB1,0x12,0x83,0x77,0x00,0x10,0x10,0x1E,0x1E,0x0C,0x1A,0x20,0xD6}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x3A,0x17}}, + {LCM_SEND(2),{0xB4,0x01}}, + {LCM_SEND(5),{3,0,0xB6,0x96,0x96}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x20,0xC4,0x00}}, + //gamma setting + {LCM_SEND(130),{128,0,0xC1,0x03,0x00,0x06,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,\ + 0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7C,0x84,0x8C,\ + 0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,\ + 0xE4,0xEC,0xF3,0xFD,0x0F,0xFA,0x95,0x40,0xFF,0xAA,\ + 0x54,0x03,0xC0,0x00,0x07,0x0F,0x17,0x1F,0x27,0x2F,\ + 0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F,\ + 0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,\ + 0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x17,0x1F,\ + 0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,\ + 0x77,0x7F,0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,\ + 0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,}}, + {LCM_SEND(7),{5,0,0xE3,0x0F,0x0F,0x11,0x11}}, + {LCM_SEND(2),{0xEA,0x7A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(38),{36,0,0xE0,0x01,0x0D,0x18,0x14,0x13,0x2F,0x31,0x3B,0x09,0x10,0x12,0x16,0x17,0x16,0x16,0x11,0x14,0x01,\ + 0x0D,0x18,0x14,0x13,0x2F,0x30,0x3B,0x09,0x10,0x11,0x16,0x17,0x15,0x16,0x11,0x14,0x01}}, + {LCM_SEND(2),{0x51,0x80}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(120)}, //40 + +#else + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x0B,0x0B,0x0C,0x0A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(6),{4,0,0xC3,0x55,0xB8,0x90}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x02,0x04,0x2C,0x33,0x3F,0x0D,0x32,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x00,\ +0x02,0x04,0x2C,0x32,0x3F,0x0F,0x31,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x01, +}}, + + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x51,0x80}}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + +#ifndef NEW_PANAL_BOE + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) +#else + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0x90 == read_data[2])) +#endif + { + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8369b_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 90, /* unit: pixel */ + .hbp = 70, + .hsync = 60, + .vfp = 8, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi.c new file mode 100644 index 00000000..65e7014a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi.c @@ -0,0 +1,348 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +#define NEW_PANAL_BOE + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { +#ifndef NEW_PANAL_BOE + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SLEEP(10)}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(2),{0x36,0x00}}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x16,0x16,0x0C,0x0A}}, + {LCM_SEND(2),{0xB2,0x03}}, +// {LCM_SEND(5),{3,0,0xB2,0x00,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(5),{3,0,0xB6,0xA3,0xA3}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xc4,0x00}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x01,0x0D,0x18,0x14,0x13,0x2F,0x31,0x3B,0x09,0x10,0x12,0x16,0x17,0x16,0x16,0x11,0x14,0x01,\ + 0x0D,0x18,0x14,0x13,0x2F,0x30,0x3B,0x09,0x10,0x11,0x16,0x17,0x15,0x16,0x11,0x14,0x01}}, + {LCM_SEND(130),{128,0,0xC1,0x03,0x00,0x06,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,\ + 0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7C,0x84,0x8C,\ + 0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,\ + 0xE4,0xEC,0xF3,0xFD,0x0F,0xFA,0x95,0x40,0xFF,0xAA,\ + 0x54,0x03,0xC0,0x00,0x07,0x0F,0x17,0x1F,0x27,0x2F,\ + 0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F,\ + 0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,\ + 0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x17,0x1F,\ + 0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,\ + 0x77,0x7F,0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,\ + 0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,}}, + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x51,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#else + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x0B,0x0B,0x0C,0x0A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(6),{4,0,0xC3,0x55,0xB8,0x90}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x02,0x04,0x2C,0x33,0x3F,0x0D,0x32,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x00,\ +0x02,0x04,0x2C,0x32,0x3F,0x0F,0x31,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x01, +}}, + + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x51,0x80}}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + +#ifndef NEW_PANAL_BOE + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) +#else + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0x90 == read_data[2])) +#endif + { + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8369b_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 110, /* unit: pixel */ + .hbp = 110, + .hsync = 4, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite.c new file mode 100644 index 00000000..65e7014a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite.c @@ -0,0 +1,348 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +#define NEW_PANAL_BOE + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { +#ifndef NEW_PANAL_BOE + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SLEEP(10)}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(2),{0x36,0x00}}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x16,0x16,0x0C,0x0A}}, + {LCM_SEND(2),{0xB2,0x03}}, +// {LCM_SEND(5),{3,0,0xB2,0x00,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(5),{3,0,0xB6,0xA3,0xA3}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xc4,0x00}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x01,0x0D,0x18,0x14,0x13,0x2F,0x31,0x3B,0x09,0x10,0x12,0x16,0x17,0x16,0x16,0x11,0x14,0x01,\ + 0x0D,0x18,0x14,0x13,0x2F,0x30,0x3B,0x09,0x10,0x11,0x16,0x17,0x15,0x16,0x11,0x14,0x01}}, + {LCM_SEND(130),{128,0,0xC1,0x03,0x00,0x06,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,\ + 0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7C,0x84,0x8C,\ + 0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,\ + 0xE4,0xEC,0xF3,0xFD,0x0F,0xFA,0x95,0x40,0xFF,0xAA,\ + 0x54,0x03,0xC0,0x00,0x07,0x0F,0x17,0x1F,0x27,0x2F,\ + 0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F,\ + 0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,\ + 0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x17,0x1F,\ + 0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,\ + 0x77,0x7F,0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,\ + 0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,}}, + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x51,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#else + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x0B,0x0B,0x0C,0x0A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(6),{4,0,0xC3,0x55,0xB8,0x90}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x02,0x04,0x2C,0x33,0x3F,0x0D,0x32,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x00,\ +0x02,0x04,0x2C,0x32,0x3F,0x0F,0x31,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x01, +}}, + + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x51,0x80}}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + +#ifndef NEW_PANAL_BOE + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) +#else + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0x90 == read_data[2])) +#endif + { + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8369b_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 110, /* unit: pixel */ + .hbp = 110, + .hsync = 4, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite_marlin.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite_marlin.c new file mode 100644 index 00000000..65e7014a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_coreprimelite_marlin.c @@ -0,0 +1,348 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +#define NEW_PANAL_BOE + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { +#ifndef NEW_PANAL_BOE + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SLEEP(10)}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(2),{0x36,0x00}}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x16,0x16,0x0C,0x0A}}, + {LCM_SEND(2),{0xB2,0x03}}, +// {LCM_SEND(5),{3,0,0xB2,0x00,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(5),{3,0,0xB6,0xA3,0xA3}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xc4,0x00}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x01,0x0D,0x18,0x14,0x13,0x2F,0x31,0x3B,0x09,0x10,0x12,0x16,0x17,0x16,0x16,0x11,0x14,0x01,\ + 0x0D,0x18,0x14,0x13,0x2F,0x30,0x3B,0x09,0x10,0x11,0x16,0x17,0x15,0x16,0x11,0x14,0x01}}, + {LCM_SEND(130),{128,0,0xC1,0x03,0x00,0x06,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,\ + 0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7C,0x84,0x8C,\ + 0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,\ + 0xE4,0xEC,0xF3,0xFD,0x0F,0xFA,0x95,0x40,0xFF,0xAA,\ + 0x54,0x03,0xC0,0x00,0x07,0x0F,0x17,0x1F,0x27,0x2F,\ + 0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F,\ + 0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,\ + 0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x17,0x1F,\ + 0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,\ + 0x77,0x7F,0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,\ + 0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,}}, + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x51,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#else + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x0B,0x0B,0x0C,0x0A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(6),{4,0,0xC3,0x55,0xB8,0x90}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x02,0x04,0x2C,0x33,0x3F,0x0D,0x32,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x00,\ +0x02,0x04,0x2C,0x32,0x3F,0x0F,0x31,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x01, +}}, + + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x51,0x80}}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + +#ifndef NEW_PANAL_BOE + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) +#else + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0x90 == read_data[2])) +#endif + { + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8369b_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 110, /* unit: pixel */ + .hbp = 110, + .hsync = 4, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_kiran3g.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_kiran3g.c new file mode 100644 index 00000000..9926fd76 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_kiran3g.c @@ -0,0 +1,384 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +#define LCD_NEW_PANEL + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + +#ifndef LCD_NEW_PANEL + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x11,0x11,0x08,0x08,0x0C,0x12}}, + {LCM_SEND(7),{5,0,0xC6,0x41,0xFF,0x7A,0xFF}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB0,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(10),{8,0,0xB3,0x83,0x00,0x31,0x03,0x01,0x13,0x06}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + //set GIP timing control + {LCM_SEND(95),{93, 0, 0xD5, + 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x12, 0x40, 0x00,\ + 0x00, 0x00, 0x01, 0x60, 0x37, 0x00, 0x00, 0x0F, 0x01, 0x02,\ + 0x47, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x03, 0x00, 0x00, 0x18, 0x00, 0x00, 0x89, 0x00,\ + 0x11, 0x33, 0x55, 0x77, 0x31, 0x00, 0x00, 0x98, 0x00, 0x66,\ + 0x44, 0x22, 0x00, 0x02, 0x00, 0x00, 0x89, 0x00, 0x00, 0x22,\ + 0x44, 0x66, 0x20, 0x00, 0x00, 0x98, 0x00, 0x77, 0x55, 0x33,\ + 0x11, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,\ + 0x00, 0xCF, 0xFF, 0xFF, 0x03, 0x00, 0xCF, 0xFF, 0xFF, 0x20,\ + 0x8C, 0x5A}}, + + //gamma setting + {LCM_SEND(38),{36, 0, 0xE0, + 0x00, 0x00, 0x00, 0x0D, 0x0C, 0x3F, 0x18, 0x2C, 0x04, 0x0F,\ + 0x0E, 0x14, 0x17, 0x15, 0x16, 0x10, 0x13, 0x00, 0x00, 0x00,\ + 0x0C, 0x12, 0x3F, 0x17, 0x2C, 0x05, 0x08, 0x0E, 0x12, 0x16,\ + 0x14, 0x15, 0x11, 0x13, 0x01}}, + {LCM_SEND(130),{128, 0, 0xC1, + 0x01, 0x00, 0x08, 0x10, 0x18, 0x1F, 0x27, 0x2E, 0x34, 0x3E,\ + 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90,\ + 0x98, 0xA0, 0xA8, 0xB0, 0xB8, 0xC0, 0xC8, 0xD0, 0xD8, 0xE0,\ + 0xE8, 0xF0, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x1F, 0x27, 0x2E,\ + 0x34, 0x3E, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80,\ + 0x88, 0x90, 0x98, 0xA0, 0xA8, 0xB0, 0xB8, 0xC0, 0xC8, 0xD0,\ + 0xD8, 0xE0, 0xE8, 0xF0, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x1F,\ + 0x27, 0x2E, 0x34, 0x3E, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70,\ + 0x78, 0x80, 0x88, 0x90, 0x98, 0xA0, 0xA8, 0xB0, 0xB8, 0xC0,\ + 0xC8, 0xD0, 0xD8, 0xE0, 0xE8, 0xF0, 0xF7, 0xFF, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1),{0x29}}, +#else + /* Password */ + {LCM_SEND(5),{3,0,0xF0,0x5A,0x5A}}, + {LCM_SEND(5),{3,0,0xF1,0x5A,0x5A}}, + {LCM_SEND(5),{3,0,0xFC,0xA5,0xA5}}, + + /* Resolution Control */ + {LCM_SEND(2),{0xB3, 0x01}}, + {LCM_SEND(2),{0xB5, 0x10}}, + {LCM_SEND(6),{4,0,0xBC,0x00,0x29,0x51}}, /* 141006 Battery detect function disabled */ + + /* MIPI SETTING */ + {LCM_SEND(5),{3,0,0xE3,0x24,0x2C}}, + + /* Display Inversion Off */ + {LCM_SEND(1),{0x21}}, + + /* Display Control */ + {LCM_SEND(11), {9,0,0xF2,0x11,0x04,0x08,0x10,0x10,0x72,0x4A,0x0A}}, + + /* power control 1 */ + {LCM_SEND(8),{6,0,0xF3,0x91,0x00,0x00,0x00,0x10}}, + + /* power control 2 */ + {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}}, + + /* power control 3 */ + {LCM_SEND(31),{29,0,0xF5,0x14,0x14,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}}, + + /* 9.4 */ + {LCM_SEND(20),{18,0,0xFE,0x00,0x02,0x01,0x39,0x60,0x40,0x21,0x00,0x4B,0x00,0x80,0x00,0xF0,0x00,0x00,0x00,0x06}}, + + /* ASG EQ Control */ + {LCM_SEND(13),{11,0,0xEE,0x40,0xA0,0x40,0xA0,0x00,0x00,0x00,0x00,0x00,0x00}}, + + {LCM_SEND(23),{21,0,0xEF,0x23,0x01,0x00,0x00,0x2A,0x49,0x08,0x27,0x21,0x40,0x10,0x24,0x02,0x21,0x21,0x03,0x03,0x40,0x00,0x08}}, + + /* Panel Gate Control */ + {LCM_SEND(33),{31,0,0xF7,0x02,0x1B,0x1A,0x00,0x01,0x0E,0x0E,0x0A,0x0A,0x0F,0x0F,0x0B,0x0B,0x05,0x07,0x02,0x1B,0x1A,0x00,0x01,0x0C,0x0C,0x08,0x08,0x0D,0x0D,0x09,0x09,0x04,0x06}}, + + /* Source Control */ + {LCM_SEND(9),{7,0,0xF6,0x63,0x25,0x15,0x00,0x00,0x20}}, + + /* Memory Data Access Control */ + {LCM_SEND(2),{0x36,0x10}}, + + /* Positive Gamma Control */ + {LCM_SEND(20),{18,0,0xFA,0x0C,0x36,0x0B,0x10,0x07,0x0C,0x10,0x10,0x14,0x1D,0x1F,0x1F,0x20,0x21,0x22,0x25,0x2F}}, + + /* Negative Gamma Control */ + {LCM_SEND(20),{18,0,0xFB,0x0C,0x36,0x0B,0x10,0x07,0x0C,0x10,0x0E,0x0E,0x15,0x1B,0x1E,0x20,0x1F,0x20,0x25,0x2F}}, + + /* display on */ + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(120)}, +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) + { + int32_t j =0; + uint8_t read_data[4] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ +#ifndef LCD_NEW_PANEL + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xda value is 0x%x!\n",read_data[0]); + + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xdb value is 0x%x!\n",read_data[1]); + + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xdc value is 0x%x!\n",read_data[2]); + + if((0x55 == read_data[0])&&(0xbf == read_data[1] || 0xc0 == read_data[1] || 0xbe == read_data[1])&&(0x90 == read_data[2])){ + LCD_PRINT("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } +#else + param[0] = 0x03; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0x04, 3, read_data); + LCD_PRINT("lcd_s6d77a1_mipi read id 0xda, 0xdb,0xdc is 0x%x,0x%x,0x%x!\n", + read_data[0], read_data[1], read_data[2]); + if ((0x55 == read_data[0]) && (0xB8 == read_data[1]) + && (0x10 == read_data[2])) { + LCD_PRINT("lcd_s6d77a1_mipi read id success!\n"); + return 0x8369; + } +#endif + } + + mipi_eotp_set(0,0); + + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { +#ifndef LCD_NEW_PANEL + .hfp = 115, /* unit: pixel */ + .hbp = 55, + .hsync = 4, + .vfp = 6, /*unit: line*/ + .vbp = 19, + .vsync = 4, +#else + .hfp = 74, /* unit: pixel */ + .hbp = 88, + .hsync = 26, + .vfp = 16, /* unit: line */ + .vbp = 12, + .vsync = 4, +#endif +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_sharkls_z3lte.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_sharkls_z3lte.c new file mode 100644 index 00000000..65e7014a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_sharkls_z3lte.c @@ -0,0 +1,348 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 +#define NEW_PANAL_BOE + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { +#ifndef NEW_PANAL_BOE + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + {LCM_SLEEP(10)}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(2),{0x36,0x00}}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x16,0x16,0x0C,0x0A}}, + {LCM_SEND(2),{0xB2,0x03}}, +// {LCM_SEND(5),{3,0,0xB2,0x00,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(5),{3,0,0xB6,0xA3,0xA3}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xc4,0x00}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x01,0x0D,0x18,0x14,0x13,0x2F,0x31,0x3B,0x09,0x10,0x12,0x16,0x17,0x16,0x16,0x11,0x14,0x01,\ + 0x0D,0x18,0x14,0x13,0x2F,0x30,0x3B,0x09,0x10,0x11,0x16,0x17,0x15,0x16,0x11,0x14,0x01}}, + {LCM_SEND(130),{128,0,0xC1,0x03,0x00,0x06,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,\ + 0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7C,0x84,0x8C,\ + 0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,\ + 0xE4,0xEC,0xF3,0xFD,0x0F,0xFA,0x95,0x40,0xFF,0xAA,\ + 0x54,0x03,0xC0,0x00,0x07,0x0F,0x17,0x1F,0x27,0x2F,\ + 0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F,\ + 0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,\ + 0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x17,0x1F,\ + 0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,\ + 0x77,0x7F,0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,\ + 0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,}}, + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x51,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#else + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x0F,0x0F,0x0B,0x0B,0x0C,0x0A}}, + {LCM_SEND(6),{4,0,0xC6,0x41,0xFF,0x7D}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(6),{4,0,0xC3,0x55,0xB8,0x90}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB1,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(7),{5,0,0xB3,0x83,0x00,0x31,0x03}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + + + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x07,0x00,0x09,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x01,0x42,0x37,\ + 0x00,0x00,0x08,0x2A,0x08,0x47,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x15,0x00,0x00,0x98,0x98,0x44,0x66,0x00,0x22,0x51,0x00,0x00,0x89,0x98,0x33,0x11,0x77,0x55,0x04,0x00,\ + 0x00,0x98,0x98,0x55,0x77,0x11,0x33,0x40,0x00,0x00,0x89,0x98,0x22,0x00,0x66,0x44,0x15,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x00,0x03,0x00,0x0F,0xFF,0xFF,0x03,0x00,0x0F,0xFF,0xFF,0x00,0x8C,0x5A}}, + + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x02,0x04,0x2C,0x33,0x3F,0x0D,0x32,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x00,\ +0x02,0x04,0x2C,0x32,0x3F,0x0F,0x31,0x05,0x0B,0x0E,0x11,0x14,0x12,0x13,0x13,0x1A,0x01, +}}, + + + {LCM_SEND(5),{3,0,0xC9,0x0F,0x00}}, + {LCM_SLEEP(5)}, +// {LCM_SEND(2),{0x51,0x80}}, +// {LCM_SEND(2),{0x53,0x24}}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + +#ifndef NEW_PANAL_BOE + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) +#else + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0x90 == read_data[2])) +#endif + { + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8369b_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 110, /* unit: pixel */ + .hbp = 110, + .hsync = 4, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_vivaltoVE.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_vivaltoVE.c new file mode 100644 index 00000000..6ffe813e --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_mipi_vivaltoVE.c @@ -0,0 +1,283 @@ +/* drivers/video/sprdfb/lcd_hx8369b_mipi.c + * + * Support for hx8369b mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x69}}, + //{LCM_SLEEP(10)}, + {LCM_SEND(13),{11,0,0xB1,0x0B,0x83,0x77,0x00,0x11,0x11,0x08,0x08,0x0C,0x12}}, + {LCM_SEND(7),{5,0,0xC6,0x41,0xFF,0x7A,0xFF}}, + {LCM_SEND(7),{5,0,0xE3,0x00,0x00,0x00,0x00}}, + {LCM_SEND(9),{7,0,0xC0,0x73,0x50,0x00,0x34,0xC4,0x00}}, + {LCM_SEND(18),{16,0,0xBA,0x31,0x00,0x16,0xCA,0xB0,0x0A,0x00,0x10,0x28,0x02,0x21,0x21,0x9A,0x1A,0x8F}}, + {LCM_SEND(2),{0x3A,0x70}}, + {LCM_SEND(10),{8,0,0xB3,0x83,0x00,0x31,0x03,0x01,0x13,0x06}}, + {LCM_SEND(2),{0xB4,0x00}}, + {LCM_SEND(2),{0xCC,0x0C}}, + {LCM_SEND(2),{0xEA,0x72}}, + {LCM_SEND(2),{0xB2,0x03}}, + //set GIP timing control + {LCM_SEND(95),{93,0,0xD5,0x00,0x00,0x0D,0x00,0x00,0x00,0x00,0x12,0x40,0x00,0x00,0x00,0x01,0x60,0x37,0x00,0x00,0x0F, + 0x01,0x02,0x47,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x18, + 0x00,0x00,0x89,0x00,0x11,0x33,0x55,0x77,0x31,0x00,0x00,0x98,0x00,0x66,0x44,0x22,0x00,0x02, + 0x00,0x00,0x89,0x00,0x00,0x22,0x44,0x66,0x20,0x00,0x00,0x98,0x00,0x77,0x55,0x33,0x11,0x13, + 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0xCF,0xFF,0xFF,0x03,0x00,0xCF,0xFF,0xFF,0x20,0x8C,0x5A}}, + //gamma setting + {LCM_SEND(38),{36,0,0xE0,0x00,0x00,0x00,0x0D,0x0C,0x3F,0x18,0x2C,0x04,0x0F,0x0E,0x14,0x17,0x15,0x16,0x10, + 0x13,0x00,0x00,0x00,0x0C,0x12,0x3F,0x17,0x2C,0x05,0x08,0x0E,0x12,0x16,0x14,0x15, + 0x11,0x13,0x01}}, + {LCM_SEND(130),{128,0,0xC1,0x01,0x00,0x08,0x10,0x18,0x1F,0x27,0x2E,0x34,0x3E,0x48,0x50,0x58,0x60,0x68,0x70,0x78, + 0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF7,0xFF, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x18,0x1F,0x27,0x2E,0x34, + 0x3E,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0, + 0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF7,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0x10,0x18,0x1F,0x27,0x2E,0x34,0x3E,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80, + 0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF7,0xFF,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, //40 + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t hx8369b_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t hx8369b_readid(struct panel_spec *self) + { + int32_t j =0; + uint8_t read_data[4] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8369b_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xda value is 0x%x!\n",read_data[0]); + + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xdb value is 0x%x!\n",read_data[1]); + + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + LCD_PRINT("lcd_hx8369b_mipi read id 0xdc value is 0x%x!\n",read_data[2]); + + if((0x55 == read_data[0])&&(0x0c == read_data[1])&&(0x90 == read_data[2])){ + printk("lcd_hx8369b_mipi read id success!\n"); + return 0x8369; + } + } + + mipi_eotp_set(0,0); + + return 0; +} + + +static int32_t hx8369b_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8369b_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8369b_mipi_operations = { + .panel_init = hx8369b_mipi_init, + .panel_readid = hx8369b_readid, + .panel_enter_sleep = hx8369b_enter_sleep, +}; + +static struct timing_rgb lcd_hx8369b_mipi_timing = { + .hfp = 115, /* unit: pixel */ + .hbp = 55, + .hsync = 50, + .vfp = 6, /*unit: line*/ + .vbp = 19, + .vsync = 4, +}; + + +static struct info_mipi lcd_hx8369b_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8369b_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8369b_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8369b_mipi_info + }, + .ops = &lcd_hx8369b_mipi_operations, +}; +struct panel_cfg lcd_hx8369b_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_hx8369b_mipi", + .panel = &lcd_hx8369b_mipi_spec, +}; + +//temp code +static int __init lcd_hx8369b_mipi_init(void) +{ +/* + printk("hx8369b_mipi_init: set lcd backlight.\n"); + + if (gpio_request(214, "LCD_BL")) { + printk("Failed ro request LCD_BL GPIO_%d \n", + 214); + return -ENODEV; + } + gpio_direction_output(214, 1); + gpio_set_value(214, 1); +*/ + + return sprdfb_panel_register(&lcd_hx8369b_mipi); +} + +subsys_initcall(lcd_hx8369b_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369b_tshark2_j3_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8369b_tshark2_j3_mipi.c new file mode 100755 index 00000000..5afb97e7 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8369b_tshark2_j3_mipi.c @@ -0,0 +1,290 @@ +/* drivers/video/sprdfb/lcd_tshark2_j3_mipi.c + * + * Support for tshark2_j3 mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x89}}, + {LCM_SEND(23),{21,0,0xB1,0x7F,0x10,0x10,0xD2,0x32,0x80,0x10,0xF0,0x56,0x80,0x20,0x20,0xF8,0xAA,0xAA,0xA1,0x00,0x80,0x30,0x00}}, + {LCM_SEND(13),{11,0,0xB2,0x82,0x50,0x05,0x07,0xF0,0x38,0x11,0x64,0x5D,0x09}}, + {LCM_SEND(14),{12,0,0xB4,0x66,0x66,0x66,0x70,0x00,0x00,0x18,0x76,0x28,0x76,0xA8}}, + {LCM_SEND(2),{0xD2,0x33}}, + {LCM_SEND(7),{5,0,0xC0,0x30,0x17,0x00,0x03}}, + {LCM_SEND(7),{5,0,0xC7,0x00,0x80,0x00,0xC0}}, + {LCM_SEND(7),{5,0,0xBF,0x05,0x50,0x00,0x3E}}, + {LCM_SLEEP(10)}, + //{LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x89}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(38),{36,0,0xD3,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x32,0x10,0x00,0x00,0x00,0x03,0xC6,0x03,0xC6,0x00,0x00,0x00,0x00 \ + ,0x35,0x33,0x04,0x04,0x37,0x00,0x00,0x00,0x05,0x08,0x00,0x00,0x0A,0x00,0x01}}, + {LCM_SEND(41),{39,0,0xD5,0x18,0x18,0x18,0x18,0x19,0x19,0x18,0x18,0x20,0x21,0x24,0x25,0x18,0x18,0x18,0x18,0x00,0x01,0x04,0x05 \ + ,0x02,0x03,0x06,0x07,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + {LCM_SEND(41),{0x39,0,0xD6,0x18,0x18,0x18,0x18,0x18,0x18,0x19,0x19,0x25,0x24,0x21,0x20,0x18,0x18 \ + ,0x18,0x18,0x07,0x06,0x03,0x02,0x05,0x04,0x01,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 \ + ,0x18,0x18,0x18,0x18,0x18,0x18}}, + {LCM_SEND(6),{4,0,0xB7,0x20,0x80,0x00}}, + +//gamma + {LCM_SEND(45),{43,0,0xE0,0x00,0x02,0x06,0x38,0x3C,0x3F,0x1B,0x46,0x06,0x09,0x0C,0x17 \ + ,0x10,0x13,0x16,0x13,0x14,0x08,0x13,0x15,0x19,0x00,0x02,0x06,0x37,0x3C,0x3F \ + ,0x1A,0x45,0x05,0x09,0x0B,0x16,0x0F,0x13,0x15,0x13,0x14,0x07,0x12,0x14,0x18}}, + + {LCM_SEND(2),{0xBD,0x00}}, + {LCM_SEND(46),{44,0,0xC1,0x00,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50 \ + ,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8 \ + ,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xBD,0x01}}, + {LCM_SEND(45),{43,0,0xC1,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78 \ + ,0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00 \ + ,0x00,0x00,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xBD,0x02}}, + {LCM_SEND(45),{43,0,0xC1,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90 \ + ,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}}, + +//CABC + {LCM_SEND(2),{0x51,0x80}}, + {LCM_SLEEP(5)}, + + {LCM_SEND(16),{14,0,0xC9,0x1F,0x2E,0x0A,0x1E,0x81,0x1E,0x00,0x00,0x01,0x19,0x00,0x00,0x20}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x55,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + +//display on + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; + + +static int32_t tshark2_j3_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel J3_tshark2_j3_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t tshark2_j3_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_tshark2_j3_mipi_J3 read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + + + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) + { + printk("lcd_tshark2_j3_mipi read id success!\n"); + return 0x8369; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_tshark2_j3_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t tshark2_j3_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel tshark2_j3_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_tshark2_j3_mipi_operations = { + .panel_init = tshark2_j3_mipi_init, + .panel_readid = tshark2_j3_readid, + .panel_enter_sleep = tshark2_j3_enter_sleep, +}; + +static struct timing_rgb lcd_tshark2_j3_mipi_timing = { + .hfp = 80, /* unit: pixel */ + .hbp = 80, + .hsync = 20, + .vfp = 18, /*unit: line*/ + .vbp = 13, + .vsync = 2, +}; + + +static struct info_mipi lcd_tshark2_j3_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =500*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_tshark2_j3_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_tshark2_j3_mipi_spec = { + .width = 540, + .height = 960, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_tshark2_j3_mipi_info + }, + .ops = &lcd_tshark2_j3_mipi_operations, +}; +struct panel_cfg lcd_tshark2_j3_mipi = { + + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8369, + .lcd_name = "lcd_tshark2_j3_mipi", + .panel = &lcd_tshark2_j3_mipi_spec, +}; + +//temp code +static int __init lcd_tshark2_j3_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_tshark2_j3_mipi); +} + +subsys_initcall(lcd_tshark2_j3_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8379a_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8379a_mipi.c new file mode 100644 index 00000000..4b6c4a08 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8379a_mipi.c @@ -0,0 +1,312 @@ +/* drivers/video/sprdfb/lcd_hx8379a_mipi.c
+ *
+ * Support for hx8379a mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */
+
+#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> +
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 100
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+// Set EXTC
+{LCM_SEND(6), {4, 0, 0xb9,0xff,0x83,0x79}},
+
+// Set MIPI
+{LCM_SEND(5), {3, 0, 0xba,0x51,0x93}},
+//Set Power
+{LCM_SEND(34), {32, 0, 0xB1,0x00,0x50,0x24,0xF5,0x98,0x08,0x11,0x17,0x77,0x29,0x31,0x9A,
+ 0x1A,0x12,0x0B,0x76,0xF1,0x00,0xE6,0xE6,0xE6,0xE6,0xE6,0x00,0x04,0x05,
+ 0x0A,0x0B,0x04,0x05,0x6F}},
+// Set Display
+{LCM_SEND(16), {14, 0, 0xB2,0x00,0x00,0xFE,0x0E,0x0A,0x19,0xE2,0x00,0xFF,0x0E,0x0A,0x19,0x20}},
+// Set CYC
+{LCM_SEND(34), {32, 0, 0xB4,0x80,0x12,0x00,0x32,0x10,0x03,0x54,0x13,0x67,0x32,0x13,0x6B,
+ 0x39,0x00,0x42,0x05,0x37,0x00,0x41,0x08,0x3C,0x3C,0x08,0x00,0x40,0x08,
+ 0x28,0x08,0x30,0x30,0x04}},
+// Set GIP
+{LCM_SEND(50), {48, 0, 0xD5,0x00,0x00,0x0A,0x00,0x01,0x00,0x00,0x06,0x01,0x01,0x01,
+ 0x23,0x45,0x67,0xAA,0xBB,0x88,0x88,0x67,0x45,0x88,0x88,0x88,0x88,0x88,
+ 0x54,0x10,0x76,0x54,0x32,0xAA,0xBB,0x88,0x88,0x76,0x10,0x88,0x88,0x88,
+ 0x88,0x88,0x39,0x01,0x00,0x00,0x00,0x00}},
+// Set Gamma
+{LCM_SEND(38), {36, 0, 0xE0,0x79,0x00,0x01,0x0F,0x25,0x26,0x3F,0x33,0x47,0x0A,0x11,0x11,
+ 0x15,0x17,0x14,0x16,0x11,0x17,0x00,0x01,0x0F,0x25,0x26,0x3F,0x33,0x47,
+ 0x0A,0x11,0x11,0x15,0x17,0x14,0x16,0x11,0x17}},
+// Set Panel
+//{LCM_SEND(2), {0xcc,0x02}}, //no rotation
+{LCM_SEND(2), {0xcc,0x0E}},//rotation 180
+// Set VCOM
+{LCM_SEND(7), {5, 0, 0xB6,0x00,0xAC,0x00,0xAC}},
+//set TE
+{LCM_SEND(2), {0x35,0x00}},
+
+{LCM_SEND(1), {0x11}},//0x11
+{LCM_SLEEP(200)},
+{LCM_SEND(1), {0x29}},//0x29
+{LCM_SLEEP(100)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(150)}, //>150ms
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(150)}, //>150ms
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},//>120ms
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)}, //>20ms
+};
+
+static int32_t hx8379a_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0; + LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel hx8369b_mipi_init\n"); +
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20); + }else if(tag & LCM_TAG_SLEEP){
+ msleep(init->tag & LCM_TAG_MASK); + }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t hx8379a_readid(struct panel_spec *self)
+{
+ uint32_t j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("lcd_hx8379a_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x01;
+ param[1] = 0x00;
+ mipi_force_write(0x37, param, 2);
+ read_rtn = mipi_force_read(0xda,1,&read_data[0]);
+ LCD_PRINT("lcd_hx8379a_mipi read id 0xda value is 0x%x!\n",read_data[0]);
+
+ read_rtn = mipi_force_read(0xdb,1,&read_data[1]);
+ LCD_PRINT("lcd_hx8379a_mipi read id 0xdb value is 0x%x!\n",read_data[1]);
+
+ read_rtn = mipi_force_read(0xdc,1,&read_data[2]);
+ LCD_PRINT("lcd_hx8379a_mipi read id 0xdc value is 0x%x!\n",read_data[2]);
+
+ if((0x83 == read_data[0])&&(0x79 == read_data[1])&&(0x0a == read_data[2])){
+ LCD_PRINT("lcd_hx8379a_mipi read id success!\n");
+ return 0x8379;
+ }
+ }
+
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t hx8379a_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_nt35516_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ pr_debug("lcd_hx8379a mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x1c == read_data[0]) && (0 == read_rtn)){
+ //printk("lcd_hx8379a_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x1c;
+ }
+ }
+
+ printk("lcd_hx8379a mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t hx8379a_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ pr_debug("hx8379a_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+#endif
+ power_mode = hx8379a_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+#endif
+ if(power_mode == 0x1c){
+ pr_debug("hx8379a_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("hx8379a_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_hx8379a_mipi_operations = {
+ .panel_init = hx8379a_mipi_init,
+ .panel_readid = hx8379a_readid,
+ .panel_esd_check = hx8379a_check_esd,
+};
+
+static struct timing_rgb lcd_hx8379a_mipi_timing = {
+ .hfp = 25, /* unit: pixel */
+ .hbp = 25,
+ .hsync = 11,
+ .vfp = 22, /*unit: line*/
+ .vbp = 12,
+ .vsync = 3,
+};
+
+
+static struct info_mipi lcd_hx8379a_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq =500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_hx8379a_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_hx8379a_mipi_spec = {
+ .width = 480,
+ .height = 854,
+ .fps = 62,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_hx8379a_mipi_info
+ },
+ .ops = &lcd_hx8379a_mipi_operations,
+};
+struct panel_cfg lcd_hx8379a_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8379, + .lcd_name = "lcd_hx8379a_mipi", + .panel = &lcd_hx8379a_mipi_spec, +}; + +static int __init lcd_hx8379a_mipi_init(void)
+{ + return sprdfb_panel_register(&lcd_hx8379a_mipi); +} + +subsys_initcall(lcd_hx8379a_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8389c_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8389c_mipi.c new file mode 100755 index 00000000..9ef8ed43 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8389c_mipi.c @@ -0,0 +1,318 @@ +/* drivers/video/sprdfb/lcd_hx8389c_mipi.c + * + * Support for hx8389c mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#if defined(CONFIG_MACH_GRANDPRIME3G_VE) || defined(CONFIG_MACH_GRANDPRIME_DTV) +static int is_gpio_request2=0; +#endif + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + + {LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x89}}, + {LCM_SEND(23),{21,0,0xB1,0x7F,0x10,0x10,0xD2,0x32,0x80,0x10,0xF0,0x56,0x80,0x20,0x20,0xF8,0xAA,0xAA,0xA1,0x00,0x80,0x30,0x00}}, + {LCM_SEND(13),{11,0,0xB2,0x82,0x50,0x05,0x07,0xF0,0x38,0x11,0x64,0x5D,0x09}}, + {LCM_SEND(14),{12,0,0xB4,0x66,0x66,0x66,0x70,0x00,0x00,0x18,0x76,0x28,0x76,0xA8}}, + {LCM_SEND(2),{0xD2,0x33}}, + {LCM_SEND(7),{5,0,0xC0,0x30,0x17,0x00,0x03}}, + {LCM_SEND(7),{5,0,0xC7,0x00,0x80,0x00,0xC0}}, + {LCM_SEND(7),{5,0,0xBF,0x05,0x50,0x00,0x3E}}, + {LCM_SLEEP(10)}, + //{LCM_SEND(6),{4,0,0xB9,0xFF,0x83,0x89}}, + {LCM_SEND(2),{0xCC,0x0E}}, + {LCM_SEND(38),{36,0,0xD3,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x32,0x10,0x00,0x00,0x00,0x03,0xC6,0x03,0xC6,0x00,0x00,0x00,0x00 \ + ,0x35,0x33,0x04,0x04,0x37,0x00,0x00,0x00,0x05,0x08,0x00,0x00,0x0A,0x00,0x01}}, + {LCM_SEND(41),{39,0,0xD5,0x18,0x18,0x18,0x18,0x19,0x19,0x18,0x18,0x20,0x21,0x24,0x25,0x18,0x18,0x18,0x18,0x00,0x01,0x04,0x05 \ + ,0x02,0x03,0x06,0x07,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + {LCM_SEND(41),{39,0,0xD6,0x18,0x18,0x18,0x18,0x18,0x18,0x19,0x19,0x25,0x24,0x21,0x20,0x18,0x18 \ + ,0x18,0x18,0x07,0x06,0x03,0x02,0x05,0x04,0x01,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 \ + ,0x18,0x18,0x18,0x18,0x18,0x18}}, + {LCM_SEND(6),{4,0,0xB7,0x20,0x80,0x00}}, + +//gamma + {LCM_SEND(45),{43,0,0xE0,0x00,0x02,0x06,0x38,0x3C,0x3F,0x1B,0x46,0x06,0x09,0x0C,0x17 \ + ,0x10,0x13,0x16,0x13,0x14,0x08,0x13,0x15,0x19,0x00,0x02,0x06,0x37,0x3C,0x3F \ + ,0x1A,0x45,0x05,0x09,0x0B,0x16,0x0F,0x13,0x15,0x13,0x14,0x07,0x12,0x14,0x18}}, + + {LCM_SEND(2),{0xBD,0x00}}, + {LCM_SEND(46),{44,0,0xC1,0x00,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50 \ + ,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8 \ + ,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xBD,0x01}}, + {LCM_SEND(45),{43,0,0xC1,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78 \ + ,0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00 \ + ,0x00,0x00,0x00,0x00,0x00,0x00}}, + {LCM_SEND(2),{0xBD,0x02}}, + {LCM_SEND(45),{43,0,0xC1,0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x90 \ + ,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}}, + +//CABC + {LCM_SEND(2),{0x51,0x80}}, + {LCM_SLEEP(5)}, + + {LCM_SEND(16),{14,0,0xC9,0x1F,0x2E,0x0A,0x1E,0x81,0x1E,0x00,0x00,0x01,0x19,0x00,0x00,0x20}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x55,0x00}}, + {LCM_SLEEP(5)}, + {LCM_SEND(2),{0x53,0x24}}, + {LCM_SLEEP(5)}, + +//display on + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(180)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(10)}, + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; + + +static int32_t hx8389c_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +#if defined(CONFIG_MACH_GRANDPRIME3G_VE) || defined(CONFIG_MACH_GRANDPRIME_DTV) +static uint32_t hx8389c_before_resume(struct panel_spec *self) +{ + if(is_gpio_request2==0){ + if (gpio_request(167, "LCD LDO")) { + printk("Failed ro request GPIO_%d \n",167); + return 0; + } + gpio_direction_output(167, 0); + is_gpio_request2=1; + } + gpio_set_value(167, 1); + return 0; +} + +static uint32_t hx8389c_after_suspend(struct panel_spec *self) +{ + if(is_gpio_request2==0){ + if (gpio_request(167, "LCD LDO")) { + printk("Failed ro request GPIO_%d \n",167); + return 0; + } + gpio_direction_output(167, 0); + is_gpio_request2=1; + } + gpio_set_value(167, 0); + return 0; +} +#endif + +static uint32_t hx8389c_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_hx8389c_mipi_J3 read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + + + if((0x55 == read_data[0])&&(0xc0 == read_data[1])&&(0x90 == read_data[2])) + { + printk("lcd_hx8389c_mipi read id success!\n"); + return 0x8389; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_hx8389c_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t hx8389c_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel hx8389c_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_hx8389c_mipi_operations = { + .panel_init = hx8389c_mipi_init, + .panel_readid = hx8389c_readid, + .panel_enter_sleep = hx8389c_enter_sleep, +#if defined(CONFIG_MACH_GRANDPRIME3G_VE) || defined(CONFIG_MACH_GRANDPRIME_DTV) + .panel_after_suspend=hx8389c_after_suspend, + .panel_before_resume=hx8389c_before_resume, +#endif +}; + +static struct timing_rgb lcd_hx8389c_mipi_timing = { + .hfp = 80, /* unit: pixel */ + .hbp = 80, + .hsync = 20, + .vfp = 18, /*unit: line*/ + .vbp = 13, + .vsync = 2, +}; + + +static struct info_mipi lcd_hx8389c_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =500*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_hx8389c_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_hx8389c_mipi_spec = { + .width = 540, + .height = 960, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8389c_mipi_info + }, + .ops = &lcd_hx8389c_mipi_operations, +}; +struct panel_cfg lcd_hx8389c_mipi = { + + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8389, + .lcd_name = "lcd_hx8389c_mipi", + .panel = &lcd_hx8389c_mipi_spec, +}; + +//temp code +static int __init lcd_hx8389c_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_hx8389c_mipi); +} + +subsys_initcall(lcd_hx8389c_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_hx8394a_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8394a_mipi.c new file mode 100644 index 00000000..b52eb976 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8394a_mipi.c @@ -0,0 +1,295 @@ +/* drivers/video/sprdfb/lcd_hx8389b_mipi.c
+ *
+ * Support for hx8389b mipi LCD device
+ *
+ * Copyright (C) 2015 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 150
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+{LCM_SEND(6), {4, 0, 0xB9,0xFF,0x83,0x94}},
+{LCM_SEND(19), {17, 0, 0xBA,0x63,0x82,0x00,0x16,0xC5,0x00,0x10,0xFF,0x0F,0x24,0x03,0x21,0x24,0x25,0x20,0x08}},
+{LCM_SEND(20), {18, 0, 0xB1,0x01,0x00,0x04,0xC4,0x03,0x12,0xF1,0x24,0x2C,0x3F,0x3F,0x57,0x02,0x00,0xE6,0xE2,0xA6}},
+{LCM_SEND(9), {7, 0, 0xB2,0x00,0xC8,0x0E,0x30,0x00,0x33}},
+{LCM_SEND(34), {32, 0, 0xB4,0x80,0x04,0x32,0x10,0x08,0x54,0x15,0x0F,0x22,0x10,0x08,0x47,0x53,0x54,0x0A,0x4B,0x53,0x54,0x02,0x61,0x61,0x02,0x06,0x44,0x06,0x5F,0x0A,0x6B,0x70,0x05,0x08}},
+{LCM_SEND(2), {0xB6, 0x21}},
+{LCM_SEND(57), {55, 0, 0xD5,0x00,0x00,0x00,0x00,0x0A,0x00,0x01,0x22,0x00,0x33,0xCC,0x00,0xAA,0xBB,0x01,0x23,0x45,0x67,0x9A,0xBC,0x45,0x67,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x01,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x3C,0x01}},
+
+{LCM_SEND(2), {0xCC, 0x09}},
+
+{LCM_SEND(7), {5, 0, 0xBF,0x06,0x02,0x10,0x04}},
+
+{LCM_SEND(7), {5, 0, 0xC7,0x00,0x10,0x00,0x10}},
+
+{LCM_SEND(28), {26, 0, 0xE0,0x00,0x04,0x08,0x28,0x2F,0x3F,0x15,0x34,0x06,0x0C,0x0E,0x12,0x14,0x13,0x14,0x11,0x19,0x00,0x04,0x08,0x29,0x2E,0x3F,0x15,0x35}},
+{LCM_SEND(19), {17, 0, 0x07,0x0C,0x0F,0x11,0x13,0x11,0x12,0x10,0x16,0x0A,0x17,0x07,0x12,0x0A,0x17,0x06,0x11}},
+
+{LCM_SEND(5), {3, 0, 0xC0,0x0C,0x17}},
+
+{LCM_SEND(5), {3, 0, 0xC6,0x08,0x08}},
+
+{LCM_SEND(2), {0xD4, 0x32}},
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(200)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(100)},
+
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(150)}, //>150ms
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(150)}, //>150ms
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},//>120ms
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)}, //>20ms
+};
+
+static int32_t hx8394a_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel hx8394a_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t hx8394a_readid(struct panel_spec *self)
+{
+ uint32_t j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("lcd_hx8394a_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x03;
+ param[1] = 0x00;
+ mipi_force_write(0x37, param, 2);
+ read_rtn = mipi_force_read(0x04,3, &read_data[0]);
+ LCD_PRINT("lcd_hx8394a_mipi read id 0x04 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if(0x83 == read_data[0] && 0x94 == read_data[1] && 0x1A == read_data[2]){
+ LCD_PRINT("hx8394a success!\n");
+ return 0x8394;
+ }
+ }
+
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t hx8394a_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_hx8394a_mipi read power mode!\n");
+ mipi_eotp_set(0,0);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ pr_debug("lcd_hx8389b mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x1c == read_data[0])){
+ //printk("lcd_hx8389b_mipi read power mode success!\n");
+ mipi_eotp_set(0,0);
+ return 0x1c;
+ }
+ }
+
+ printk("lcd_hx8394a mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(0,0);
+ return 0x0;
+}
+
+static int32_t hx8394a_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ pr_debug("hx8394a_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+#endif
+ power_mode = hx8394a_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+#endif
+ if(power_mode == 0x1c){
+ pr_debug("hx8394a_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("hx8394a_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_hx8394a_mipi_operations = {
+ .panel_init = hx8394a_mipi_init,
+ .panel_readid = hx8394a_readid,
+ .panel_esd_check = hx8394a_check_esd,
+};
+
+static struct timing_rgb lcd_hx8394a_mipi_timing = {
+ .hfp = 80, /* unit: pixel */
+ .hbp = 60,
+ .hsync = 60,
+ .vfp = 38, /*unit: line*/
+ .vbp = 12,
+ .vsync = 4,
+};
+
+
+static struct info_mipi lcd_hx8394a_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 4,
+ .phy_feq = 450*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_hx8394a_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_hx8394a_mipi_spec = {
+ .width = 720,
+ .height = 1280,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_hx8394a_mipi_info
+ },
+ .ops = &lcd_hx8394a_mipi_operations,
+};
+
+struct panel_cfg lcd_hx8394a_mipi = {
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x8394,
+ .lcd_name = "lcd_hx8394a_mipi",
+ .panel = &lcd_hx8394a_mipi_spec,
+};
+
+static int __init lcd_hx8394a_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_hx8394a_mipi);
+}
+
+subsys_initcall(lcd_hx8394a_mipi_init);
+
+
diff --git a/drivers/video/sprdfb/lcd/lcd_hx8394d_mipi.c b/drivers/video/sprdfb/lcd/lcd_hx8394d_mipi.c new file mode 100644 index 00000000..9643cf60 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_hx8394d_mipi.c @@ -0,0 +1,430 @@ +/* drivers/video/sprdfb/lcd_hx8394d_mipi.c + * + * Support for hx8394d mipi LCD device + * + * Copyright (C) 2014 Spreadtrum + * Author: Haibing.Yang <haibing.yang@spreadtrum.com> + * + * The panel info is got from raolihua@trulyopto.cn + * Panel: 5.0HD(720*1280) LG LTPS + * Driver IC: HX8394D + * Interface: MIPI 4LANES + * Test condition: IOVCC=VCC=2.8V + * DATE: 20150105 + * Version: 1.0 + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#define pr_fmt(fmt) "sprdfb_hx8394b: " fmt + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/bug.h> +#include <linux/delay.h> + +#include "../sprdfb_panel.h" + +#define MAX_DATA 100 +#define DATA_TYPE_SET_RX_PKT_SIZE 0x37 +#define PANEL_READ_CNT 3 + +#define PANEL_ID_LENGTH 3 +#define PANEL_RETURN_ID 0x8394 +#define PANEL_ACTUAL_ID 0x8394 +#define PANEL_ID_REG 0x04 +#define PANEL_ID_OFFSET 0 + +#define PANEL_POWER_MODE_REG 0x0A +#define PANEL_POWER_MODE_LEN 2 +#define PANEL_NOT_DEAD_STS 0x1C +#define PANEL_POWER_MODE_OFFSET 1 + +#define LCM_TAG_SHIFT 24 +#define LCM_DATA_TYPE_SHIFT 16 +#define LCM_TAG_MASK ((1 << LCM_DATA_TYPE_SHIFT) - 1) + +#define LCM_TAG_SEND (1 << LCM_TAG_SHIFT) +#define LCM_TAG_SLEEP (2 << LCM_TAG_SHIFT) + +#define LCM_SEND(len) (LCM_TAG_SEND | len) +#define LCM_SEND_WITH_TYPE(len, type) \ + (LCM_TAG_SEND | len | (type << LCM_DATA_TYPE_SHIFT)) +#define LCM_SLEEP(ms) (LCM_TAG_SLEEP | ms) + +struct panel_cmds { + u32 tag; + u8 data[MAX_DATA]; +}; + +static struct panel_cmds hx8394d_init_cmds[] = { + { + LCM_SEND(06), {04, 0, + 0xB9, 0xFF, 0x83, 0x94} + }, + { + LCM_SEND(05), {03, 0, + 0xBA,0x33,0x83} + }, + { /* Set power */ + LCM_SEND(20), {18, 0, + 0xB1, 0x6C, 0x12, 0x12, 0x26, 0x04, 0x11, 0xF1, + 0x81, 0x3A, 0x54, 0x23, 0x80, 0xC0, 0xD2, 0x58} + }, + { /* Set display related register */ + LCM_SEND(14), {12, 0, + 0xB2, 0x00, 0x64, 0x0E, 0x0D, 0x22, 0x1C, 0x08, + 0x08, 0x1C, 0x4D, 0x00} + }, + { /* Set panel driving timing */ + LCM_SEND(15), {13, 0, + 0xB4, 0x00, 0xFF, 0x51, 0x5A, 0x59, 0x5A, 0x03, + 0x5A, 0x01, 0x70, 0x01, 0x70} + }, + {LCM_SEND(2), {0xBC, 0x07}}, + { + LCM_SEND(06), {04, 0, + 0xBF, 0x41, 0x0E, 0x01} + }, + { /* Set GIP */ + LCM_SEND(40), {38, 0, + 0xD3, 0x00, 0x0F, 0x00, 0x40, 0x07, 0x10, 0x00, + 0x08, 0x10, 0x08, 0x00, 0x08, 0x54, 0x15, 0x0E, + 0x05, 0x0E, 0x02, 0x15, 0x06, 0x05, 0x06, 0x47, + 0x44, 0x0A, 0x0A, 0x4B, 0x10, 0x07, 0x07, 0x08, + 0x00, 0x00, 0x00, 0x0A, 0x00, 0x01} + }, + { /* Set GIP */ + LCM_SEND(47), {45, 0, + 0xD5, 0x1A, 0x1A, 0x1B, 0x1B, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, + 0x0B, 0x24, 0x25, 0x18, 0x18, 0x26, 0x27, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, + 0x21, 0x18, 0x18, 0x18, 0x18} + }, + { /* Set GIP */ + LCM_SEND(47), {45, 0, + 0xD6, 0x1A, 0x1A, 0x1B, 0x1B, 0x0B, 0x0A, 0x09, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, + 0x00, 0x21, 0x20, 0x58, 0x58, 0x27, 0x26, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, + 0x24, 0x18, 0x18, 0x18, 0x18} + }, + /* SETPANEL CCh: can set normally-white/black panel */ + {LCM_SEND(2), {0xCC, 0x09}}, + { + LCM_SEND(5), {3, 0, + 0xC0, 0x30, 0x14} + }, + { + LCM_SEND(7), {5, 0, + 0xC7, 0x00, 0xC0, 0x40, 0xC0} + }, + { + LCM_SEND(5), {3, 0, + 0xB6, 0x6B, 0x6B} + }, + { /* Analog gamma setting */ + LCM_SEND(45), {43, 0, + 0xE0, 0x00, 0x0A, 0x0F, 0x24, 0x3A, 0x3F, 0x20, + 0x3B, 0x08, 0x0D, 0x0E, 0x16, 0x0F, 0x12, 0x15, + 0x13, 0x15, 0x09, 0x12, 0x12, 0x18, 0x00, 0x0A, + 0x0F, 0x24, 0x3A, 0x3F, 0x20, 0x3B, 0x08, 0x0D, + 0x0E, 0x16, 0x0F, 0x12, 0x15, 0x13, 0x15, 0x09, + 0x12, 0x12, 0x18} + }, + + {LCM_SEND(2), {0xBD, 0x00}}, /* BANK: RED */ + { + LCM_SEND(46), {44, 0, + 0xC1, 0x01, 0x00, 0x06, 0x0C, 0x14, 0x1D, 0x27, + 0x2F, 0x38, 0x41, 0x49, 0x51, 0x59, 0x61, 0x69, + 0x71, 0x79, 0x81, 0x89, 0x91, 0x99, 0xA1, 0xA9, + 0xB2, 0xB9, 0xC1, 0xCA, 0xD1, 0xD8, 0xE2, 0xEA, + 0xF0, 0xF7, 0xFF, 0x38, 0xFC, 0x3F, 0x0B, 0xC1, + 0x13, 0xF1, 0x0D, 0xC0} + }, + {LCM_SEND(2), {0xBD, 0x01}}, /* BANK: GREEN */ + { + LCM_SEND(45), {43, 0, + 0xC1, 0x00, 0x06, 0x0C, 0x14, 0x1D, 0x27, 0x2F, + 0x38, 0x41, 0x49, 0x51, 0x59, 0x61, 0x69, 0x71, + 0x79, 0x81, 0x89, 0x91, 0x99, 0xA1, 0xA9, 0xB2, + 0xB9, 0xC1, 0xCA, 0xD1, 0xD8, 0xE2, 0xEA, 0xF0, + 0xF7, 0xFF, 0x38, 0xFC, 0x3F, 0x0B, 0xC1, 0x13, + 0xF1, 0x0D, 0xC0} + }, + {LCM_SEND(2), {0xBD, 0x02}}, /* BANK: BLUE */ + { + LCM_SEND(45), {43, 0, + 0xC1, 0x00, 0x06, 0x0C, 0x14, 0x1D, 0x27, 0x2F, + 0x38, 0x41, 0x49, 0x51, 0x59, 0x61, 0x69, 0x71, + 0x79, 0x81, 0x89, 0x91, 0x99, 0xA1, 0xA9, 0xB2, + 0xB9, 0xC1, 0xCA, 0xD1, 0xD8, 0xE2, 0xEA, 0xF0, + 0xF7, 0xFF, 0x38, 0xFC, 0x3F, 0x0B, 0xC1, 0x13, + 0xF1, 0x0D, 0xC0} + }, + + /* Set_address_mode (36h): RGB order and source/gate dir */ + {LCM_SEND(2), {0x36, 0x03}}, + + /* sleep out */ + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(10)}, +}; + +static struct panel_cmds sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(10)}, + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(120)}, +}; + +static struct panel_cmds sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(10)}, +}; + +int sprdfb_dsi_tx_cmds(struct panel_spec *panel, + struct panel_cmds *cmds, u32 cmds_len, bool force_lp) +{ + int i, time; + struct ops_mipi *ops = panel->info.mipi->ops; + u16 work_mode = panel->info.mipi->work_mode; + u8 write_type = (cmds->tag >> 16) & 0xff; + + pr_info("%s, len: %d\n", __func__, cmds_len); + + if (!ops->mipi_set_cmd_mode || + !ops->mipi_dcs_write || + !ops->mipi_set_hs_mode || + !ops->mipi_set_lp_mode || + !ops->mipi_force_write) { + pr_err("%s: Expected functions are NULL.\n", __func__); + return -EFAULT; + } + if (force_lp) { + if (work_mode == SPRDFB_MIPI_MODE_CMD) + ops->mipi_set_lp_mode(); + else + ops->mipi_set_data_lp_mode(); + } + + ops->mipi_set_cmd_mode(); + + for (i = 0; i < cmds_len; i++) { + if (cmds->tag & LCM_TAG_SEND) { + if (write_type) + ops->mipi_force_write(write_type, cmds->data, + cmds->tag & LCM_TAG_MASK); + else + ops->mipi_dcs_write(cmds->data, cmds->tag & LCM_TAG_MASK); + udelay(20); + } else if (cmds->tag & LCM_TAG_SLEEP) { + time = (cmds->tag & LCM_TAG_MASK) * 1000; + usleep_range(time, time); + } + cmds++; + } + + if (force_lp) { + if (work_mode == SPRDFB_MIPI_MODE_CMD) + ops->mipi_set_hs_mode(); + else + ops->mipi_set_data_hs_mode(); + } + return 0; +} + +int sprdfb_dsi_rx_cmds(struct panel_spec *panel, + u8 regs, u16 get_len, u8 *data, bool in_bllp) +{ + int ret; + struct ops_mipi *ops = panel->info.mipi->ops; + u8 pkt_size[2]; + u16 work_mode = panel->info.mipi->work_mode; + + pr_debug("%s, read data len: %d\n", __func__, get_len); + if (!data) { + pr_err("Expected registers or data is NULL.\n"); + return -EIO; + } + if (!ops->mipi_set_cmd_mode || + !ops->mipi_force_read || + !ops->mipi_force_write) { + pr_err("%s: Expected functions are NULL.\n", __func__); + return -EFAULT; + } + + if (!in_bllp) { + if (work_mode == SPRDFB_MIPI_MODE_CMD) + ops->mipi_set_lp_mode(); + else + ops->mipi_set_data_lp_mode(); + /* + * If cmds is transmitted in LP mode, not in BLLP, + * commands mode should be enabled + * */ + ops->mipi_set_cmd_mode(); + } + + pkt_size[0] = get_len & 0xff; + pkt_size[1] = (get_len >> 8) & 0xff; + + ops->mipi_force_write(DATA_TYPE_SET_RX_PKT_SIZE, + pkt_size, sizeof(pkt_size)); + + ret = ops->mipi_force_read(regs, get_len, data); + if (ret < 0) { + pr_err("%s: dsi read id fail\n", __func__); + return -EINVAL; + } + + if (!in_bllp) { + if (work_mode == SPRDFB_MIPI_MODE_CMD) + ops->mipi_set_hs_mode(); + else + ops->mipi_set_data_hs_mode(); + } + + return 0; +} + +int sprdfb_dsi_panel_sleep(struct panel_spec *panel, u8 is_sleep) +{ + int len; + struct panel_cmds *sleep_inout; + + if (is_sleep) { + sleep_inout = sleep_in; + len = ARRAY_SIZE(sleep_in); + } else { + sleep_inout = sleep_out; + len = ARRAY_SIZE(sleep_out); + } + + return sprdfb_dsi_tx_cmds(panel, sleep_inout, len, false); +} + +u32 sprdfb_dsi_panel_readid(struct panel_spec *panel) +{ + int i, cnt = PANEL_READ_CNT; + u8 regs = PANEL_ID_REG; + u8 data[PANEL_ID_LENGTH] = { 0 }; + u8 id[PANEL_ID_LENGTH] = { 0 }; + + i = PANEL_ID_OFFSET; + id[i++] = (PANEL_RETURN_ID >> 8) & 0xFF; + id[i] = PANEL_RETURN_ID & 0xFF; + do { + sprdfb_dsi_rx_cmds(panel, regs, PANEL_ID_LENGTH, data, true); + i = PANEL_ID_OFFSET; + pr_debug("%s: reading panel id(0x%2x) is 0x%x, 0x%x", + __func__, regs, data[i], data[i+1]); + if (data[i] == id[i] && data[i + 1] == id[i + 1]) + return PANEL_ACTUAL_ID; + } while (cnt-- > 0); + + pr_err("%s: failed to read panel id, 0x%x, 0x%x.\n", + __func__, data[i], data[i + 1]); + return 0; +} + +static int hx8394d_dsi_panel_dead(struct panel_spec *panel) +{ + int i, cnt = PANEL_READ_CNT; + u8 regs = PANEL_POWER_MODE_REG; + u8 data[PANEL_POWER_MODE_LEN] = { 0 }; + bool in_bllp = false; + +#ifdef FB_CHECK_ESD_IN_VFP + in_bllp = true; +#endif + do { + sprdfb_dsi_rx_cmds(panel, regs, PANEL_POWER_MODE_LEN, data, in_bllp); + i = PANEL_POWER_MODE_OFFSET; + pr_debug("%s: reading panel power mode(0x%2x) is 0x%x", + __func__, regs, data[i]); + if ((data[i] & PANEL_NOT_DEAD_STS) == PANEL_NOT_DEAD_STS) + return true; + } while (cnt-- > 0); + + pr_err("panel is dead, read power mode is 0x%x.\n", data[i]); + return false; +} + +static int hx8394d_dsi_panel_init(struct panel_spec *panel) +{ + return sprdfb_dsi_tx_cmds(panel, hx8394d_init_cmds, + ARRAY_SIZE(hx8394d_init_cmds), false); +} + +static struct panel_operations lcd_hx8394d_mipi_ops = { + .panel_init = hx8394d_dsi_panel_init, + .panel_readid = sprdfb_dsi_panel_readid, + .panel_enter_sleep = sprdfb_dsi_panel_sleep, + .panel_esd_check = hx8394d_dsi_panel_dead, +}; + +static struct timing_rgb lcd_hx8394d_mipi_timing = { + .hfp = 16, /* unit: pixel */ + .hbp = 16, + .hsync = 10, + .vfp = 12, /*unit: line */ + .vbp = 15, + .vsync = 4, +}; + +static struct info_mipi lcd_hx8394d_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, + .lan_number = 4, + .phy_feq = 430000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_POS, + .shut_down_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_hx8394d_mipi_timing, + .ops = NULL, +}; + +static struct panel_spec lcd_hx8394d_mipi_spec = { + .width = 720, + .height = 1280, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_hx8394d_mipi_info + }, + .ops = &lcd_hx8394d_mipi_ops, +}; + +static struct panel_cfg lcd_hx8394d_mipi = { + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = PANEL_ACTUAL_ID, + .lcd_name = "lcd_hx8394d_mipi", + .panel = &lcd_hx8394d_mipi_spec, +}; + +static int __init lcd_hx8394d_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_hx8394d_mipi); +} +subsys_initcall(lcd_hx8394d_mipi_init); diff --git a/drivers/video/sprdfb/lcd/lcd_ili6150_lvds.c b/drivers/video/sprdfb/lcd/lcd_ili6150_lvds.c new file mode 100644 index 00000000..b6d5b12c --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili6150_lvds.c @@ -0,0 +1,81 @@ +/* + * drivers/video/sprdfb/lcd/lcd_ili6150_lvds.c + * + * Copyright (C) 2014 Spreadtrum Communications Inc. + * + * Author: Haibing.Yang <haibing.yang@spreadtrum.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include "../sprdfb.h" +#include "../sprdfb_panel.h" + +static uint32_t ili6150_lvds_readid(struct panel_spec *self) +{ + return 0x1806; +} + +static struct panel_operations ili6150_lvds_ops = { + .panel_init = sprdchip_lvds_init, + .panel_readid = ili6150_lvds_readid, +}; + +static struct timing_rgb ili6150_lvds_timing = { + .hfp = 150, /* unit: pixel */ + .hbp = 150, + .hsync = 1,//4 + .vfp = 16, /*unit: line*/ + .vbp = 16, + .vsync = 1, +}; + +static struct info_rgb ili6150_lvds_info = { + .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_LVDS, + .video_bus_width = 24, /*18,16*/ +#if 0 + .h_sync_pol = SPRDFB_POLARITY_NEG, + .v_sync_pol = SPRDFB_POLARITY_NEG, + .de_pol = SPRDFB_POLARITY_POS, +#endif + .timing = &ili6150_lvds_timing, + .bus_info = { + .spi = NULL, + } +}; + +static struct panel_spec ili6150_lvds_spec = { + //.cap = PANEL_CAP_NOT_TEAR_SYNC, + .width = 1024, + .height = 600, + .fps = 60, + .type = SPRDFB_PANEL_TYPE_LVDS, + .direction = LCD_DIRECT_NORMAL, + .info = { + .rgb = &ili6150_lvds_info + }, + .ops = &ili6150_lvds_ops, +}; + +struct panel_cfg lcd_ili6150_lvds = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x1806, + .lcd_name = "lcd_ili6150_lvds", + .panel = &ili6150_lvds_spec, +}; + +static int __init lcd_ili6150_lvds_init(void) +{ + return sprdfb_panel_register(&lcd_ili6150_lvds); +} + +subsys_initcall(lcd_ili6150_lvds_init); diff --git a/drivers/video/sprdfb/lcd/lcd_ili9341.c b/drivers/video/sprdfb/lcd/lcd_ili9341.c new file mode 100644 index 00000000..c857c4bc --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9341.c @@ -0,0 +1,428 @@ +/* drivers/video/sc8810/lcd_ili9341.c
+ *
+ * Support for ili9341 LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+static int32_t ili9341_init(struct panel_spec *self)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ pr_debug("ili9341_init\n");
+
+ //Power Setting
+ send_cmd(0xCF);
+ send_data(0x00);
+ send_data(0xE1);
+ send_data(0x30);
+
+ send_cmd(0xED);
+ send_data(0x64);
+ send_data(0x03);
+ send_data(0x12);
+ send_data(0x81);
+
+ send_cmd(0xCB);
+ send_data(0x39);
+ send_data(0x2C);
+ send_data(0x00);
+ send_data(0x34);
+ send_data(0x02);
+
+ send_cmd(0xF7);
+ send_data(0x20);
+
+ send_cmd(0xEA);
+ send_data(0x00);
+ send_data(0x00);
+
+ send_cmd(0xC5);
+ send_data(0x4C);
+ send_data(0x2B);
+
+ send_cmd(0xC7);
+ send_data(0x00);
+
+ send_cmd(0xC0);
+ send_data(0x22);
+
+ send_cmd(0xC1);
+ send_data(0x11);
+
+ //Initializing Sequence
+ send_cmd(0x35);
+ send_data(0x00);
+
+ send_cmd(0x36);
+ send_data(0x08);
+
+ send_cmd(0x3A);
+ send_data(0x05);
+
+ send_cmd(0xF2);
+ send_data(0x02);
+
+ send_cmd(0xB6);
+ send_data(0x01);
+ send_data(0xC2);
+
+ send_cmd(0xF6);
+ send_data(0x01);
+ send_data(0x10);
+ send_data(0x00);
+
+ send_cmd(0xB1);
+ send_data(0x00);
+ send_data(0x1A);
+
+ send_cmd(0xB5);
+ send_data(0x02);
+ send_data(0x02);
+ send_data(0x0A);
+ send_data(0x14);
+
+ send_cmd(0xE8);
+ send_data(0x85);
+ send_data(0x01);
+ send_data(0x78);
+
+ //Gamma Setting
+ send_cmd(0xE0);
+ send_data(0x0F);
+ send_data(0x31);
+ send_data(0x2F);
+ send_data(0x0D);
+ send_data(0x10);
+ send_data(0x08);
+ send_data(0x5F);
+ send_data(0xB6);
+ send_data(0x50);
+ send_data(0x07);
+ send_data(0x14);
+ send_data(0x07);
+ send_data(0x2A);
+ send_data(0x1F);
+ send_data(0x08);
+
+ send_cmd(0xE1);
+ send_data(0x00);
+ send_data(0x0E);
+ send_data(0x10);
+ send_data(0x04);
+ send_data(0x10);
+ send_data(0x04);
+ send_data(0x23);
+ send_data(0x54);
+ send_data(0x35);
+ send_data(0x03);
+ send_data(0x0B);
+ send_data(0x09);
+ send_data(0x20);
+ send_data(0x2A);
+ send_data(0x08);
+
+ send_cmd(0xE2);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+
+ send_cmd(0xE3);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x22);
+ send_data(0x22);
+ send_data(0x22);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x33);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x02);
+ send_data(0x01);
+ send_data(0x00);
+#if 1
+ //Display on
+ send_cmd(0x11); // (SLPOUT)
+ mdelay(10); // 100ms
+ send_cmd(0x29); // (DISPON)
+ mdelay(10); // 100ms
+ pr_debug("ili9341_init: end\n");
+
+ return 0;
+#else
+ if (1) { // for test the lcd
+ int i;
+ send_cmd(0x2C); //Write data
+ for (i = 0; i < 240*320/3; i++)
+ send_data(0xff);
+ for (i = 0; i < 240*320/3; i++)
+ send_data(0xff00);
+ for (i = 0; i < 24*320/3; i++)
+ send_data(0xff0000);
+ }
+ send_cmd(0x11); //Display On
+ mdelay(10); //120ms
+ send_cmd(0x29); //Write data
+ mdelay(10); //120ms
+#endif
+ pr_debug("ili9341_init: end\n");
+
+ return 0;
+}
+
+static int32_t ili9341_set_window(struct panel_spec *self,
+ uint16_t left, uint16_t top, uint16_t right, uint16_t bottom)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ pr_debug("ili9341_set_window\n");
+
+ send_cmd(0x2A); // col
+ send_data((left >> 8));
+ send_data((left & 0xFF));
+ send_data((right >> 8));
+ send_data((right & 0xFF));
+
+ send_cmd(0x2B); // row
+ send_data((top >> 8));
+ send_data((top & 0xFF));
+ send_data((bottom >> 8));
+ send_data((bottom & 0xFF));
+
+ send_cmd(0x2C);
+
+ return 0;
+}
+
+
+static int32_t ili9341_invalidate(struct panel_spec *self)
+{
+ pr_debug("ili9341_invalidate\n");
+
+ return self->ops->panel_set_window(self, 0, 0,
+ self->width-1, self->height-1);
+}
+
+static int32_t ili9341_invalidate_rect(struct panel_spec *self,
+ uint16_t left, uint16_t top,
+ uint16_t right, uint16_t bottom)
+{
+
+ pr_debug("ili9341_invalidate_rect : (%d, %d, %d, %d)\n",left, top, right, bottom);
+
+ return self->ops->panel_set_window(self, left, top,
+ right, bottom);
+}
+
+static int32_t ili9341_set_direction(struct panel_spec *self, uint16_t direction)
+{
+
+ pr_debug("ili9341_set_direction\n");
+ return 0;
+}
+
+static int32_t ili9341_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ //send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+
+ if(is_sleep) {
+ //send_cmd(0x10);
+ mdelay(120);
+ }
+ else {
+ //send_cmd(0x11);
+ mdelay(120);
+ }
+ return 0;
+}
+
+static uint32_t ili9341_read_id(struct panel_spec *self)
+{
+ int32_t read_value = 0;
+#if 0
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ read_data_t read_data = self->info.mcu->ops->read_data;
+
+ send_cmd(0x04);
+
+ read_data();
+ read_value += read_data()<< 16;
+ read_value += read_data()<< 8;
+ read_value += read_data();
+#endif
+ pr_debug("ili9341_read_id=%x\n",read_value);
+
+ read_value = 0x9341;
+
+ return read_value;
+}
+
+static int32_t ili9341_change_epf(struct panel_spec *self, bool is_default)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ return 0;
+ + if(is_default){
+ send_cmd(0xF6);
+ send_data(0x01);
+ send_data(0x30);
+ send_data(0x00);
+ }else{ + send_cmd(0xF6);
+ send_data(0x01);
+ send_data(0x10);
+ send_data(0x00);
+ } + + return 0;
+}
+
+static struct panel_operations lcd_ili9341_operations = {
+ .panel_init = ili9341_init,
+ .panel_set_window = ili9341_set_window,
+ .panel_invalidate = ili9341_invalidate,
+ //.lcd_invalidate_rect = ili9341_invalidate_rect,
+ .panel_set_direction = ili9341_set_direction,
+ .panel_enter_sleep = ili9341_enter_sleep,
+ .panel_readid = ili9341_read_id,
+ .panel_change_epf = ili9341_change_epf,
+};
+
+static struct timing_mcu lcd_ili9341_timing[] = {
+ [MCU_LCD_REGISTER_TIMING] = {
+ .rcss = 25,
+ .rlpw = 45,
+ .rhpw = 90,
+ .wcss = 30,
+ .wlpw = 20,
+ .whpw = 20,
+ },
+ [MCU_LCD_GRAM_TIMING] = {
+ .rcss = 25,
+ .rlpw = 45,
+ .rhpw = 90,
+ .wcss = 30,
+ .wlpw = 20,
+ .whpw = 20,
+ }
+};
+
+static struct info_mcu lcd_ili9341_info = {
+ .bus_mode = LCD_BUS_8080,
+ .bus_width = 16,
+ .bpp = 16, /*RGB88*/
+ .timing = &lcd_ili9341_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_panel_ili9341 = {
+ .width = 240,
+ .height = 320,
+ .fps = 60,
+ .type = LCD_MODE_MCU,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mcu = &lcd_ili9341_info
+ },
+ .ops = &lcd_ili9341_operations,
+};
+
+struct panel_cfg lcd_ili9341 = {
+ /* this panel may on both CS0/1 */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x9341,
+ .lcd_name = "lcd_ili9341",
+ .panel = &lcd_panel_ili9341,
+};
+
+static int __init lcd_ili9341_init(void)
+{
+ printk(KERN_INFO "sprdfb_111: [%s]: 0x%x!\n", __FUNCTION__,lcd_ili9341.lcd_id);
+
+ return sprdfb_panel_register(&lcd_ili9341);
+}
+
+subsys_initcall(lcd_ili9341_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_ili9486.c b/drivers/video/sprdfb/lcd/lcd_ili9486.c new file mode 100644 index 00000000..885e8f76 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9486.c @@ -0,0 +1,434 @@ +/* drivers/video/sc8810/lcd_ili9486.c + * + * Support for ili9486 LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +static int32_t ili9486_init(struct panel_spec *self) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("ili9486_init\n"); +#if 0 + // Hidden register setting + send_cmd(0xF9); + send_data(0x00); + send_data(0x08); + + send_cmd(0xF2); + send_data(0x18); + send_data(0xA3); + send_data(0x02); + send_data(0x02); + send_data(0xB2); + send_data(0x12); + send_data(0xFF); + send_data(0x10); + send_data(0x00); + + send_cmd(0xF1); + send_data(0x36); + send_data(0x04); + send_data(0x00); + send_data(0x3C); + send_data(0x0F); + send_data(0x8F); +#endif + //Power setting sequence + send_cmd(0xC0); + send_data(0x0B); + send_data(0x0B); + + send_cmd(0xC1); + send_data(0x45); + + send_cmd(0xC2); + send_data(0x22); + + mdelay(150); // 150ms + + //Display parameter setting + send_cmd(0x2A); + send_data(0x00); + send_data(0x00); + send_data(0x01); + send_data(0x3F); + + send_cmd(0x2B); + send_data(0x00); + send_data(0x00); + send_data(0x01); + send_data(0xDF); + + send_cmd(0xB1); + send_data(0xB0); + send_data(0x12);//11: 67hz, 12:63.5hz + + send_cmd(0xB4); + send_data(0x02); + + send_cmd(0xB5); + send_data(0x08); + send_data(0x0C); + send_data(0x10); + send_data(0x0A); + + send_cmd(0xB6); + send_data(0x02); + send_data(0x22);//0x42 + send_data(0x3B); + + send_cmd(0xB7); + send_data(0xC6); + + send_cmd(0xF2); + send_data(0x18); + send_data(0xA3); + send_data(0x12); + send_data(0x02); + send_data(0xB2); + send_data(0x12); + send_data(0xFF); + send_data(0x10); + send_data(0x00); + + send_cmd(0xF4); + send_data(0x00); + send_data(0x00); + send_data(0x08); + send_data(0x91); + send_data(0x04); + + send_cmd(0x3A); + send_data(0x06); + + send_cmd(0x35); + + send_cmd(0x36); + send_data(0xD8);//0xC8 + + send_cmd(0x44); + send_data(0x01); + send_data(0xD5); + + //Gamma setting + send_cmd(0xF8); + send_data(0x21); + send_data(0x06); + + send_cmd(0xE0); + send_data(0x0F); + send_data(0x18); + send_data(0x13); + send_data(0x08); + send_data(0x0B); + send_data(0x07); + send_data(0x4A); + send_data(0xA7); + send_data(0x3A); + send_data(0x0C); + send_data(0x16); + send_data(0x07); + send_data(0x09); + send_data(0x06); + send_data(0x00); + + send_cmd(0xE1); + send_data(0x0F); + send_data(0x34); + send_data(0x31); + send_data(0x09); + send_data(0x0B); + send_data(0x02); + send_data(0x41); + send_data(0x53); + send_data(0x30); + send_data(0x04); + send_data(0x0F); + send_data(0x02); + send_data(0x17); + send_data(0x14); + send_data(0x00); + + send_cmd(0xE2); + send_data(0x19); + send_data(0x19); + send_data(0x19); + send_data(0x19); + send_data(0x19); + send_data(0x19); + send_data(0x1A); + send_data(0x1A); + send_data(0x1A); + send_data(0x1A); + send_data(0x1A); + send_data(0x1A); + send_data(0x19); + send_data(0x19); + send_data(0x09); + send_data(0x09); + + send_cmd(0xE3); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x04); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x24); + send_data(0x25); + send_data(0x3D); + send_data(0x4D); + send_data(0x4D); + send_data(0x4D); + send_data(0x4C); + send_data(0x7C); + send_data(0x6D); + send_data(0x6D); + send_data(0x7D); + send_data(0x6D); + send_data(0x6E); + send_data(0x6D); + send_data(0x6D); + send_data(0x6D); + send_data(0x6D); + send_data(0x6D); + send_data(0x5C); + send_data(0x5C); + send_data(0x5C); + send_data(0x6B); + send_data(0x6B); + send_data(0x6A); + send_data(0x5B); + send_data(0x5B); + send_data(0x53); + send_data(0x53); + send_data(0x53); + send_data(0x53); + send_data(0x53); + send_data(0x53); + send_data(0x43); + send_data(0x33); + send_data(0xB4); + send_data(0x94); + send_data(0x74); + send_data(0x64); + send_data(0x64); + send_data(0x43); + send_data(0x13); + send_data(0x24); +#if 1 + //Display on + send_cmd(0x11); // (SLPOUT) + + mdelay(120); // 100ms + + send_cmd(0x29); // (DISPON) + + mdelay(100); // 100ms +#else + if (1) { // for test the lcd + int i; + send_cmd(0x2C); //Write data + for (i = 0; i < 480*320/3; i++) + send_data(0xff); + for (i = 0; i < 480*320/3; i++) + send_data(0xff00); + for (i = 0; i < 480*320/3; i++) + send_data(0xff0000); + } + send_cmd(0x29); //Display On + mdelay(120); //120ms + send_cmd(0x2C); //Write data + mdelay(1200); //120ms +#endif + pr_debug("ili9486_init: end\n"); + + return 0; +} + +static int32_t ili9486_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("ili9486_set_window\n"); + + send_cmd(0x2A); // col + send_data((left >> 8)); + send_data((left & 0xFF)); + send_data((right >> 8)); + send_data((right & 0xFF)); + + send_cmd(0x2B); // row + send_data((top >> 8)); + send_data((top & 0xFF)); + send_data((bottom >> 8)); + send_data((bottom & 0xFF)); + + send_cmd(0x2C); + + return 0; +} + + +static int32_t ili9486_invalidate(struct panel_spec *self) +{ + pr_debug("ili9486_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width-1, self->height-1); +} + +static int32_t ili9486_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + + pr_debug("ili9486_invalidate_rect : (%d, %d, %d, %d)\n",left, top, right, bottom); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t ili9486_set_direction(struct panel_spec *self, uint16_t direction) +{ + + pr_debug("ili9486_set_direction\n"); + return 0; +} + +static int32_t ili9486_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + //send_data_t send_cmd = self->info.mcu->ops->send_cmd; + + if(is_sleep) { + //send_cmd(0x10); + mdelay(120); + } + else { + //send_cmd(0x11); + mdelay(120); + } + return 0; +} + +static uint32_t ili9486_read_id(struct panel_spec *self) +{ + int32_t read_value = 0; +#if 0 + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + read_data_t read_data = self->info.mcu->ops->read_data; + + send_cmd(0x04); + + read_data(); + read_value += read_data()<< 16; + read_value += read_data()<< 8; + read_value += read_data(); +#endif + pr_debug("ili9486_read_id=%x\n",read_value); + + read_value = 0x9486; + + return read_value; +} + +static struct panel_operations lcd_ili9486_operations = { + .panel_init = ili9486_init, + .panel_set_window = ili9486_set_window, + .panel_invalidate = ili9486_invalidate, + //.lcd_invalidate_rect = ili9486_invalidate_rect, + .panel_set_direction = ili9486_set_direction, + .panel_enter_sleep = ili9486_enter_sleep, + .panel_readid = ili9486_read_id, +}; + +static struct timing_mcu lcd_ili9486_timing[] = { + [MCU_LCD_REGISTER_TIMING] = { + .rcss = 25, + .rlpw = 45, + .rhpw = 90, + .wcss = 30, + .wlpw = 20, + .whpw = 20, + }, + [MCU_LCD_GRAM_TIMING] = { + .rcss = 25, + .rlpw = 45, + .rhpw = 90, + .wcss = 30, + .wlpw = 20, + .whpw = 20, + } +}; + +static struct info_mcu lcd_ili9486_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 18, + .bpp = 18, /*RGB88*/ + .timing = &lcd_ili9486_timing, + .ops = NULL, +}; + +struct panel_spec lcd_panel_ili9486 = { + .width = 320, + .height = 480, + .fps = 60, + .type = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_ili9486_info + }, + .ops = &lcd_ili9486_operations, +}; + +struct panel_cfg lcd_ili9486 = { + /* this panel may on both CS0/1 */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x9486, + .lcd_name = "lcd_ili9486", + .panel = &lcd_panel_ili9486, +}; + +static int __init lcd_ili9486_init(void) +{ + printk(KERN_INFO "sprdfb_111: [%s]: 0x%x!\n", __FUNCTION__,lcd_ili9486.lcd_id); + + return sprdfb_panel_register(&lcd_ili9486); +} + +subsys_initcall(lcd_ili9486_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_ili9486_rgb_spi.c b/drivers/video/sprdfb/lcd/lcd_ili9486_rgb_spi.c new file mode 100644 index 00000000..1eac114c --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9486_rgb_spi.c @@ -0,0 +1,397 @@ +/* drivers/video/sc8810/lcd_ili9486_rgb_spi.c + * + * + * + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +#define ili9486_SpiWriteCmd(cmd) \ +{ \ + spi_send_cmd((cmd & 0xFF));\ +} + +#define ili9486_SpiWriteData(data)\ +{ \ + spi_send_data((data & 0xFF));\ +} + + +static int32_t ili9486_init(struct panel_spec *self) +{ + uint32_t test_data[8] = {0}; + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 480; + uint32_t bottom = 854; + uint32_t data = 0; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + + printk("ili9486_init\n"); + + ili9486_SpiWriteCmd(0xC0); + + ili9486_SpiWriteData(0x15); + ili9486_SpiWriteData(0x15); + + ili9486_SpiWriteCmd(0xC1); + ili9486_SpiWriteData(0x42); + + ili9486_SpiWriteCmd(0xC2); + ili9486_SpiWriteData(0x22); + + ili9486_SpiWriteCmd(0xC5); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x3A); + + //Display parameter setting + ili9486_SpiWriteCmd(0x2A); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x01); + ili9486_SpiWriteData(0x3F); + + ili9486_SpiWriteCmd(0x2B); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x01); + ili9486_SpiWriteData(0xDF); + + ili9486_SpiWriteCmd(0x36); + ili9486_SpiWriteData(0x08); + + ili9486_SpiWriteCmd(0x35); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0x3A); + ili9486_SpiWriteData(0x66); + + ili9486_SpiWriteCmd(0xB0); + ili9486_SpiWriteData(0x80); + + ili9486_SpiWriteCmd(0xB4); + ili9486_SpiWriteData(0x02); + + ili9486_SpiWriteCmd(0xB5); + ili9486_SpiWriteData(0x0C); + ili9486_SpiWriteData(0x08); + ili9486_SpiWriteData(0x2C); + ili9486_SpiWriteData(0x26); + + ili9486_SpiWriteCmd(0xB6); + ili9486_SpiWriteData(0x20); + ili9486_SpiWriteData(0x42);//0x42 + ili9486_SpiWriteData(0x3B); + + ili9486_SpiWriteCmd(0xB7); + ili9486_SpiWriteData(0x07); + + ili9486_SpiWriteCmd(0xF9); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x08); + + //Gamma setting + ili9486_SpiWriteCmd(0xE0); + ili9486_SpiWriteData(0x1E); + ili9486_SpiWriteData(0x21); + ili9486_SpiWriteData(0x1F); + ili9486_SpiWriteData(0x0C); + ili9486_SpiWriteData(0x0B); + ili9486_SpiWriteData(0x0C); + ili9486_SpiWriteData(0x4E); + ili9486_SpiWriteData(0xB9); + ili9486_SpiWriteData(0x40); + ili9486_SpiWriteData(0x07); + ili9486_SpiWriteData(0x16); + ili9486_SpiWriteData(0x06); + ili9486_SpiWriteData(0x12); + ili9486_SpiWriteData(0x12); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0xE1); + ili9486_SpiWriteData(0x1F); + ili9486_SpiWriteData(0x2A); + ili9486_SpiWriteData(0x25); + ili9486_SpiWriteData(0x0C); + ili9486_SpiWriteData(0x11); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x4C); + ili9486_SpiWriteData(0x42); + ili9486_SpiWriteData(0x35); + ili9486_SpiWriteData(0x08); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x02); + ili9486_SpiWriteData(0x26); + ili9486_SpiWriteData(0x23); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0xF8); + ili9486_SpiWriteData(0x21); + ili9486_SpiWriteData(0x07); + ili9486_SpiWriteData(0x02); + + ili9486_SpiWriteCmd(0xE2); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x09); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0xE3); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x04); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0xF4); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x08); + ili9486_SpiWriteData(0x91); + ili9486_SpiWriteData(0x04); + + ili9486_SpiWriteCmd(0xF2); + ili9486_SpiWriteData(0x18); + ili9486_SpiWriteData(0xA3); + ili9486_SpiWriteData(0x12); + ili9486_SpiWriteData(0x02); + ili9486_SpiWriteData(0x82); + ili9486_SpiWriteData(0x32); + ili9486_SpiWriteData(0xFF); + ili9486_SpiWriteData(0x10); + ili9486_SpiWriteData(0x00); + + ili9486_SpiWriteCmd(0xFC); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x00); + ili9486_SpiWriteData(0x83); + + //Display on + ili9486_SpiWriteCmd(0x11); // (SLPOUT) + mdelay(120); // 100ms + ili9486_SpiWriteCmd(0x29); // (DISPON) + mdelay(10); // 100ms + printk("ili9486_init: end\n"); + + return 0; +} + +static int32_t ili9486_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + + if(is_sleep==1){ + //Sleep In + ili9486_SpiWriteCmd(0x28); + mdelay(120); + ili9486_SpiWriteCmd(0x10); + mdelay(10); + }else{ + //Sleep Out + ili9486_SpiWriteCmd(0x11); + mdelay(120); + ili9486_SpiWriteCmd(0x29); + mdelay(10); + } + + return 0; +} + + + + +static int32_t ili9486_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + uint32_t *test_data[4] = {0}; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + return 0; +} +static int32_t ili9486_invalidate(struct panel_spec *self) +{ + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + +static int32_t ili9486_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t ili9486_read_id(struct panel_spec *self) +{ + int32_t id = 0x62; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + printk("sprdfb ili9486_read_id \n"); + ili9486_SpiWriteCmd(0xB9); // SET password + ili9486_SpiWriteData(0xFF); // + ili9486_SpiWriteData(0x83); // + ili9486_SpiWriteData(0x63); // + + ili9486_SpiWriteCmd(0xFE); // SET SPI READ INDEX + ili9486_SpiWriteData(0xF4); // GETHXID + ili9486_SpiWriteCmd(0xFF); // GET SPI READ + + spi_read(&id); + id &= 0xff; + printk(" ili9486_read_id kernel id = %x\n",id); + return 0x9486; +} + +static struct panel_operations lcd_ili9486_rgb_spi_operations = { + .panel_init = ili9486_init, + .panel_set_window = ili9486_set_window, + .panel_invalidate_rect= ili9486_invalidate_rect, + .panel_invalidate = ili9486_invalidate, + .panel_enter_sleep = ili9486_enter_sleep, + .panel_readid = ili9486_read_id +}; + +static struct timing_rgb lcd_ili9486_rgb_timing = { + .hfp = 30, + .hbp = 26, + .hsync = 4, + .vfp = 12, + .vbp = 8, + .vsync = 2, +}; + +static struct spi_info lcd_ili9486_rgb_spi_info = { + .ops = NULL, +}; + +static struct info_rgb lcd_ili9486_rgb_info = { + .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_SPI, + .video_bus_width = 18, /*18,16*/ + .h_sync_pol = SPRDFB_POLARITY_NEG, + .v_sync_pol = SPRDFB_POLARITY_NEG, + .de_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_ili9486_rgb_timing, + .bus_info = { + .spi = &lcd_ili9486_rgb_spi_info, + } +}; + +struct panel_spec lcd_panel_ili9486_rgb_spi = { + .width = 320, + .height = 480, + .fps = 61, + .type = LCD_MODE_RGB, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .rgb = &lcd_ili9486_rgb_info + }, + .ops = &lcd_ili9486_rgb_spi_operations, +}; + +struct panel_cfg lcd_ili9486_rgb_spi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x9486, + .lcd_name = "lcd_ili9486_rgb_spi", + .panel = &lcd_panel_ili9486_rgb_spi, +}; +static int __init lcd_ili9486_rgb_spi_init(void) +{ + return sprdfb_panel_register(&lcd_ili9486_rgb_spi); +} + +subsys_initcall(lcd_ili9486_rgb_spi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_ili9486s1_mipi.c b/drivers/video/sprdfb/lcd/lcd_ili9486s1_mipi.c new file mode 100644 index 00000000..b25e6390 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9486s1_mipi.c @@ -0,0 +1,268 @@ +#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+#include <mach/gpio.h>
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 100
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ //Power setting Sequence
+ {LCM_SEND(5),{3,0,0xC0,0x0A,0x0A}},
+ {LCM_SEND(2),{0xc1,0x45}},
+ {LCM_SEND(2),{0xc2, 0x00}},
+
+ //Initializing Sequence
+ {LCM_SEND(7),{5,0,0x2A,0x00,0x00,0x01,0x3F}},
+ {LCM_SEND(7),{5,0,0x2B,0x00,0x00,0x01,0xDF}},
+ {LCM_SEND(2),{0x36,0xc8}},
+ {LCM_SEND(2),{0x3A,0x66}},
+ {LCM_SEND(2),{0xB0,0x8c}},
+ {LCM_SEND(2),{0xB4,0x02}},
+ {LCM_SEND(6),{4,0,0xB6,0x32,0x22,0x3B}},
+ {LCM_SEND(2),{0xB7,0xC6}},
+ {LCM_SEND(5),{3,0,0xF9,0x00,0x08}},
+ {LCM_SEND(7),{5,0,0xF7,0xA9,0x91,0x2D,0x8A}},
+ {LCM_SEND(6),{4,0,0xF8,0x21,0x07,0x02}},
+ {LCM_SEND(11),{9,0,0xF1,0x36,0x04,0x00,0x3C,0x0F,0x0F,0x04,0x02}},
+ {LCM_SEND(12),{10,0,0xF2,0x18,0xA3,0x12,0x02,0xB2,0x12,0xFF,0x10,0x00}},
+ {LCM_SEND(6),{4,0,0xFC,0x00,0x0C,0x80}},
+ //gamma setting
+ {LCM_SEND(18),{16,0,0xE0,0x01,0x15,0x17,0x0C,0x0F,0x07,0x44,0x65,0x35,0x07,0x12,0x04,0x09,0x06,0x06}},
+ {LCM_SEND(18),{16,0,0xE1,0x0F,0x38,0x34,0x0B,0x0B,0x03,0x43,0x22,0x30,0x03,0x0E,0x03,0x21,0x1B,0x00}},
+ // 3Gamma Setting Sequence
+ {LCM_SEND(19),{17,0,0xE2,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x00}},
+ {LCM_SEND(67),{65,0,0xE3,0x00,0x00,0x00,0x00,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00}},
+
+ //Display on
+ {LCM_SEND(1),{0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1),{0x29}},
+ {LCM_SLEEP(100)},
+
+};
+
+static LCM_Init_Code disp_on[] = {
+ {LCM_SEND(1),{0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1),{0x29}},
+ {LCM_SLEEP(100)},
+};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(50)}, //>150ms
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(120)}, //>150ms
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},//>120ms
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)}, //>20ms
+};
+
+static int32_t ili9486s1_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel ili9486s1_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t ili9486s1_readid(struct panel_spec *self)
+{
+#if 0
+ uint8_t j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("ili9486s1_readid!\n");
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x01;
+ param[1] = 0x00;
+
+ mipi_force_write(0x04, param, 2);
+
+ read_rtn = mipi_force_read(0xda,1,&read_data[0]);
+ LCD_PRINT("lcdili9486s1_mipi read id 0xda value is 0x%x!\n",read_data[0]);
+
+ read_rtn = mipi_force_read(0xdb,1,&read_data[1]);
+ LCD_PRINT("lcd_ili9486s1_mipi read id 0xdb value is 0x%x!\n",read_data[1]);
+
+ read_rtn = mipi_force_read(0xdc,1,&read_data[2]);
+ LCD_PRINT("lcd_ili9486s1_mipi read id 0xdc value is 0x%x!\n",read_data[2]);
+
+ if((0x55 == read_data[0])&&(0x4c == read_data[1])&&(0xc0 == read_data[2])){
+ printk("lcd_nili9486s1_mipi read id success!\n");
+ return 0x8370;
+ }
+ }
+
+ mipi_eotp_set(0,0);
+#endif
+ return 0x8370;
+}
+
+
+
+static int32_t ili9486s1_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel nt35502_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(sleep_in_out->tag & LCM_TAG_MASK);
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static struct panel_operations lcd_ili9486s1_mipi_operations = {
+ .panel_init = ili9486s1_mipi_init,
+ .panel_readid = ili9486s1_readid,
+ .panel_enter_sleep = ili9486s1_enter_sleep,
+};
+
+static struct timing_rgb lcd_ili9486s1_mipi_timing = {
+ .hfp = 30, /* unit: pixel */
+ .hbp = 26,
+ .hsync = 0,
+ .vfp = 12, /*unit: line*/
+ .vbp = 8,
+ .vsync = 1,
+};
+
+
+
+static struct info_mipi lcd_ili9486s1_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 18, /*18,16*/
+ .lan_number = 1,
+ .phy_feq =340*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_ili9486s1_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_ili9486s1_mipi_spec = {
+ .width = 320,
+ .height = 480,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_ili9486s1_mipi_info
+ },
+ .ops = &lcd_ili9486s1_mipi_operations,
+};
+struct panel_cfg lcd_ili9486s1_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x8370,
+ .lcd_name = "lcd_ili9486s1_mipi",
+ .panel = &lcd_ili9486s1_mipi_spec,
+};
+
+//temp code
+static int __init lcd_ili9486s1_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_ili9486s1_mipi);
+}
+
+subsys_initcall(lcd_ili9486s1_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_ili9806e_2_mipi.c b/drivers/video/sprdfb/lcd/lcd_ili9806e_2_mipi.c new file mode 100644 index 00000000..e391ef26 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9806e_2_mipi.c @@ -0,0 +1,487 @@ +/* drivers/video/sc8825/lcd_ili9806e_2_mipi.c
+ *
+ * Support for ili9806e_2 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},// Change to Page 1
+ {LCM_SLEEP(5)},
+
+ {LCM_SEND(2), {0x08,0x10}},// output SDA
+
+ {LCM_SEND(2), {0x21,0x01}},// DE = 1 Active
+
+ {LCM_SEND(2), {0x30,0x02}},// 480 X 800 Ó¦¸ÃÉèΪ2
+ {LCM_SEND(2), {0x31,0x02}}, // 2-dot Inversion
+
+ {LCM_SEND(2), {0x50,0x78}},// VGMP
+ {LCM_SEND(2), {0x51,0x78}},// VGMN
+ {LCM_SEND(2), {0x52,0x00}}, //Flicker
+ {LCM_SEND(2), {0x53,0x77}},//Flicker
+ {LCM_SEND(2), {0x54,0x00}},//Flicker
+ {LCM_SEND(2), {0x55,0x77}},//Flicker
+
+ {LCM_SEND(2), {0x60,0x07}},// SDTI
+ {LCM_SEND(2), {0x61,0x00}},// CRTI
+ {LCM_SEND(2), {0x62,0x08}},// EQTI
+ {LCM_SEND(2), {0x63,0x00}}, // PCTI
+
+ {LCM_SEND(2), {0x40,0x10}},// VGH/VGL
+ {LCM_SEND(2), {0x41,0x33}}, // VGH/VGL
+ {LCM_SEND(2), {0x42,0x02}},// VGH/VGL
+ {LCM_SEND(2), {0x43,0x09}},// VGH/VGL
+ {LCM_SEND(2), {0x44,0x07}},// VGH/VGL
+
+//++++++++++++++++++ Gamma Setting ++++++++++++++++++//
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},// Change to Page 1
+
+ {LCM_SEND(2), {0xA0,0x00}},// Gamma 0
+ {LCM_SEND(2), {0xA1,0x04}},// Gamma 4
+ {LCM_SEND(2), {0xA2,0x0A}},// Gamma 8
+ {LCM_SEND(2), {0xA3,0x11}},// Gamma 16
+ {LCM_SEND(2), {0xA4,0x0C}},// Gamma 24
+ {LCM_SEND(2), {0xA5,0x1D}},// Gamma 52
+ {LCM_SEND(2), {0xA6,0x0D}},// Gamma 80
+ {LCM_SEND(2), {0xA7,0x07}},// Gamma 108
+ {LCM_SEND(2), {0xA8,0x05}},// Gamma 147
+ {LCM_SEND(2), {0xA9,0x0B}},// Gamma 175
+ {LCM_SEND(2), {0xAA,0x07}},// Gamma 203
+ {LCM_SEND(2), {0xAB,0x04}},// Gamma 231
+ {LCM_SEND(2), {0xAC,0x0F}},// Gamma 239
+ {LCM_SEND(2), {0xAD,0x2B}},// Gamma 247
+ {LCM_SEND(2), {0xAE,0x24}},// Gamma 251
+ {LCM_SEND(2), {0xAF,0x00}},// Gamma 255
+
+///==============Nagitive
+ {LCM_SEND(2), {0xC0,0x00}}, // Gamma 0
+ {LCM_SEND(2), {0xC1,0x04}}, // Gamma 4
+ {LCM_SEND(2), {0xC2,0x0D}}, // Gamma 8
+ {LCM_SEND(2), {0xC3,0x0E}}, // Gamma 16
+ {LCM_SEND(2), {0xC4,0x0B}}, // Gamma 24
+ {LCM_SEND(2), {0xC5,0x15}}, // Gamma 52
+ {LCM_SEND(2), {0xC6,0x07}}, // Gamma 80
+ {LCM_SEND(2), {0xC7,0x09}}, // Gamma 108
+ {LCM_SEND(2), {0xC8,0x02}}, // Gamma 147
+ {LCM_SEND(2), {0xC9,0x06}}, // Gamma 175
+ {LCM_SEND(2), {0xCA,0x05}}, // Gamma 203
+ {LCM_SEND(2), {0xCB,0x04}}, // Gamma 231
+ {LCM_SEND(2), {0xCC,0x09}}, // Gamma 239
+ {LCM_SEND(2), {0xCD,0x2C}}, // Gamma 247
+ {LCM_SEND(2), {0xCE,0x27}}, // Gamma 251
+ {LCM_SEND(2), {0xCF,0x00}}, // Gamma 255
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x06}}, // Change to Page 6
+
+ {LCM_SEND(2), {0x00,0x21}},
+ {LCM_SEND(2), {0x01,0x09}},
+ {LCM_SEND(2), {0x02,0x00}},
+ {LCM_SEND(2), {0x03,0x00}},
+ {LCM_SEND(2), {0x04,0x01}},
+ {LCM_SEND(2), {0x05,0x01}},
+ {LCM_SEND(2), {0x06,0x80}},
+ {LCM_SEND(2), {0x07,0x05}},
+ {LCM_SEND(2), {0x08,0x02}},
+ {LCM_SEND(2), {0x09,0x80}},
+ {LCM_SEND(2), {0x0A,0x00}},
+ {LCM_SEND(2), {0x0B,0x00}},
+ {LCM_SEND(2), {0x0C,0x0a}},
+ {LCM_SEND(2), {0x0D,0x0a}},
+ {LCM_SEND(2), {0x0E,0x00}},
+ {LCM_SEND(2), {0x0F,0x00}},
+
+ {LCM_SEND(2), {0x10,0xE0}},
+ {LCM_SEND(2), {0x11,0xE4}},
+ {LCM_SEND(2), {0x12,0x04}},
+ {LCM_SEND(2), {0x13,0x00}},
+ {LCM_SEND(2), {0x14,0x00}},
+ {LCM_SEND(2), {0x15,0xC0}},
+ {LCM_SEND(2), {0x16,0x08}},
+ {LCM_SEND(2), {0x17,0x00}},
+ {LCM_SEND(2), {0x18,0x00}},
+ {LCM_SEND(2), {0x19,0x00}},
+ {LCM_SEND(2), {0x1A,0x00}},
+ {LCM_SEND(2), {0x1B,0x00}},
+ {LCM_SEND(2), {0x1C,0x00}},
+ {LCM_SEND(2), {0x1D,0x00}},
+
+ {LCM_SEND(2), {0x20,0x01}},
+ {LCM_SEND(2), {0x21,0x23}},
+ {LCM_SEND(2), {0x22,0x45}},
+ {LCM_SEND(2), {0x23,0x67}},
+ {LCM_SEND(2), {0x24,0x01}},
+ {LCM_SEND(2), {0x25,0x23}},
+ {LCM_SEND(2), {0x26,0x45}},
+ {LCM_SEND(2), {0x27,0x67}},
+
+ {LCM_SEND(2), {0x30,0x01}},
+ {LCM_SEND(2), {0x31,0x11}},
+ {LCM_SEND(2), {0x32,0x00}},
+ {LCM_SEND(2), {0x33,0xee}},
+ {LCM_SEND(2), {0x34,0xff}},
+ {LCM_SEND(2), {0x35,0xCB}},
+ {LCM_SEND(2), {0x36,0xDA}},
+ {LCM_SEND(2), {0x37,0xAD}},
+ {LCM_SEND(2), {0x38,0xBC}},
+ {LCM_SEND(2), {0x39,0x76}},
+ {LCM_SEND(2), {0x3A,0x67}},
+ {LCM_SEND(2), {0x3B,0x22}},
+ {LCM_SEND(2), {0x3C,0x22}},
+ {LCM_SEND(2), {0x3D,0x22}},
+ {LCM_SEND(2), {0x3E,0x22}},
+ {LCM_SEND(2), {0x3F,0x22}},
+
+ {LCM_SEND(2), {0x40,0x22}},
+
+ {LCM_SEND(2), {0x52,0x10}},
+
+ {LCM_SEND(2), {0x53,0x10}},
+
+// {LCM_SEND(2), {0x58,0x97}},
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x07}}, // Change to Page 7
+ {LCM_SEND(2), {0x17,0x22}},
+
+ {LCM_SEND(2), {0x02,0x77}},
+
+ {LCM_SEND(2), {0xe1,0x79}},
+ {LCM_SEND(2), {0x26,0xB2}},
+ //{LCM_SEND(2), {0x06,0x13}},
+
+//****************************************************************************//
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}}, // Change to Page 0
+
+ {LCM_SEND(2), {0x35,0x00}},
+ {LCM_SEND(2), {0x55,0xB0}},
+
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)},
+ };
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(20)},
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(120)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39, {LCM_SEND(8), {0x6, 0, 0xFF, 0xFF, 0x98, 0x06,0x04,0x01}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t ili9806e_2_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug(KERN_DEBUG "ili9806e_2_mipi_init\n");
+
+ msleep(2);
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((init->tag & LCM_TAG_MASK) * 1000);
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t ili9806e_2_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_ili9806e_2_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x02, 3,(uint8_t *)read_data);
+ printk("lcd_ili9806e_2_mipi read id 0xc5 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if((0x04 == read_data[0])){
+ printk("lcd_ili9806e_2_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x980602;
+ }
+ }
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t ili9806e_2_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "ili9806e_2_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((sleep_in_out->tag & LCM_TAG_MASK) * 1000);
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t ili9806e_2_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ uint32_t reg_val_1 = 0;
+ uint32_t reg_val_2 = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_ili9806e_2_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_ili9806e_2 mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_ili9806e_2_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+
+static uint32_t ili9806e_2_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ pr_debug("ili9806e_2_check_esd!\n");
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = ili9806e_2_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0x9c){
+ pr_debug("ili9806e_2_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("ili9806e_2_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static uint32_t ili9806e_2_mipi_after_suspend(struct panel_spec *self)
+{
+ return 0;
+}
+
+static struct panel_operations lcd_ili9806e_2_mipi_operations = {
+ .panel_init = ili9806e_2_mipi_init,
+ .panel_readid = ili9806e_2_readid,
+ .panel_enter_sleep = ili9806e_2_enter_sleep,
+ .panel_esd_check = ili9806e_2_check_esd,
+ .panel_after_suspend = ili9806e_2_mipi_after_suspend,
+};
+ +static struct timing_rgb lcd_ili9806e_2_mipi_timing = {
+ .hfp = 80, //60 /* unit: pixel */// 100
+ .hbp = 80,//80
+ .hsync = 10,//60
+ .vfp = 20, /*unit: line*/
+ .vbp = 16, //14
+ .vsync =4, //6,
+};
+
+static struct info_mipi lcd_ili9806e_2_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 400*1000, //500->10MHz,400->8M in lp mode
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_ili9806e_2_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_ili9806e_2_mipi_spec = {
+ //.cap = PANEL_CAP_NOT_TEAR_SYNC,
+ .width = 480,
+ .height = 800,
+ .fps = 59,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .reset_timing = {5, 15, 120},
+ .info = {
+ .mipi = &lcd_ili9806e_2_mipi_info
+ },
+ .ops = &lcd_ili9806e_2_mipi_operations,
+};
+
+struct panel_cfg lcd_ili9806e_2_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x980602,
+ .lcd_name = "lcd_ili9806e_2_mipi",
+ .panel = &lcd_ili9806e_2_mipi_spec,
+};
+
+static int __init lcd_ili9806e_2_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_ili9806e_2_mipi);
+}
+
+subsys_initcall(lcd_ili9806e_2_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_ili9806e_mipi.c b/drivers/video/sprdfb/lcd/lcd_ili9806e_mipi.c new file mode 100644 index 00000000..075c7058 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ili9806e_mipi.c @@ -0,0 +1,632 @@ +/* drivers/video/sc8825/lcd_ili9806e_mipi.c
+ *
+ * Support for ili9806e mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+#if 0 /*For SS*/
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+ {LCM_SLEEP(5)},
+
+ {LCM_SEND(2), {0x08,0x10}},
+
+ {LCM_SEND(2), {0x21,0x01}},
+
+ {LCM_SEND(2), {0x30,0x02}},
+ {LCM_SEND(2), {0x31,0x00}}, //0x02
+
+ {LCM_SEND(2), {0x60,0x07}},
+ {LCM_SEND(2), {0x61,0x06}},
+ {LCM_SEND(2), {0x62,0x06}},
+ {LCM_SEND(2), {0x63,0x04}},
+
+ {LCM_SEND(2), {0x40,0x14}},
+ {LCM_SEND(2), {0x41,0x44}},//22
+ {LCM_SEND(2), {0x42,0x01}},
+ {LCM_SEND(2), {0x43,0x89}},
+ {LCM_SEND(2), {0x44,0x89}},
+ {LCM_SEND(2), {0x45,0x1b}},
+ {LCM_SEND(2), {0x46,0x44}},
+ {LCM_SEND(2), {0x47,0x44}},
+
+ {LCM_SEND(2), {0x50,0x85}},
+ {LCM_SEND(2), {0x51,0x85}},
+ {LCM_SEND(2), {0x52,0x00}},
+ {LCM_SEND(2), {0x53,0x64}},//90
+
+ //{LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+
+ {LCM_SEND(2), {0xA0,0x00}},
+ {LCM_SEND(2), {0xA1,0x00}},//01
+ {LCM_SEND(2), {0xA2,0x03}},//08
+ {LCM_SEND(2), {0xA3,0x0e}},//0e
+ {LCM_SEND(2), {0xA4,0x08}},//08
+ {LCM_SEND(2), {0xA5,0x1f}},//19
+ {LCM_SEND(2), {0xA6,0x0f}},//0b
+ {LCM_SEND(2), {0xA7,0x0b}},//0a
+ {LCM_SEND(2), {0xA8,0x03}},//02
+ {LCM_SEND(2), {0xA9,0x06}},//08
+ {LCM_SEND(2), {0xAA,0x05}},//04
+ {LCM_SEND(2), {0xAB,0x02}},//03
+ {LCM_SEND(2), {0xAC,0x0e}},//0a
+ {LCM_SEND(2), {0xAD,0x25}},//2c
+ {LCM_SEND(2), {0xAE,0x1d}},//28
+ {LCM_SEND(2), {0xAF,0x00}},
+
+ {LCM_SEND(2), {0xC0,0x00}},//00
+ {LCM_SEND(2), {0xC1,0x04}},//02
+ {LCM_SEND(2), {0xC2,0x0f}},//09
+ {LCM_SEND(2), {0xC3,0x10}},//0e
+ {LCM_SEND(2), {0xC4,0x0b}},//09
+ {LCM_SEND(2), {0xC5,0x1e}},//19
+ {LCM_SEND(2), {0xC6,0x09}},//0a
+ {LCM_SEND(2), {0xC7,0x0a}},//0a
+ {LCM_SEND(2), {0xC8,0x00}},//02
+ {LCM_SEND(2), {0xC9,0x0a}},//07
+ {LCM_SEND(2), {0xCA,0x01}},//05
+ {LCM_SEND(2), {0xCB,0x06}},//04
+ {LCM_SEND(2), {0xCC,0x09}},//0a
+ {LCM_SEND(2), {0xCD,0x2a}},//2d
+ {LCM_SEND(2), {0xCE,0x28}},//28
+ {LCM_SEND(2), {0xCF,0x00}},//00
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x06}},
+ {LCM_SEND(2), {0x00,0xa0}},
+ {LCM_SEND(2), {0x01,0x05}},
+ {LCM_SEND(2), {0x02,0x00}},
+ {LCM_SEND(2), {0x03,0x00}},
+ {LCM_SEND(2), {0x04,0x01}},
+ {LCM_SEND(2), {0x05,0x01}},
+ {LCM_SEND(2), {0x06,0x88}},
+ {LCM_SEND(2), {0x07,0x04}},
+ {LCM_SEND(2), {0x08,0x01}},
+ {LCM_SEND(2), {0x09,0x90}},
+ {LCM_SEND(2), {0x0A,0x04}},
+ {LCM_SEND(2), {0x0B,0x01}},
+ {LCM_SEND(2), {0x0C,0x01}},
+ {LCM_SEND(2), {0x0D,0x01}},
+ {LCM_SEND(2), {0x0E,0x00}},
+ {LCM_SEND(2), {0x0F,0x00}},
+
+ {LCM_SEND(2), {0x10,0x55}},
+ {LCM_SEND(2), {0x11,0x50}},
+ {LCM_SEND(2), {0x12,0x01}},
+ {LCM_SEND(2), {0x13,0x85}},
+ {LCM_SEND(2), {0x14,0x85}},
+ {LCM_SEND(2), {0x15,0xc0}},
+ {LCM_SEND(2), {0x16,0x0B}},
+ {LCM_SEND(2), {0x17,0x00}},
+ {LCM_SEND(2), {0x18,0x00}},
+ {LCM_SEND(2), {0x19,0x00}},
+ {LCM_SEND(2), {0x1A,0x00}},
+ {LCM_SEND(2), {0x1B,0x00}},
+ {LCM_SEND(2), {0x1C,0x00}},
+ {LCM_SEND(2), {0x1D,0x00}},
+
+ {LCM_SEND(2), {0x20,0x01}},
+ {LCM_SEND(2), {0x21,0x23}},
+ {LCM_SEND(2), {0x22,0x45}},
+ {LCM_SEND(2), {0x23,0x67}},
+ {LCM_SEND(2), {0x24,0x01}},
+ {LCM_SEND(2), {0x25,0x23}},
+ {LCM_SEND(2), {0x26,0x45}},
+ {LCM_SEND(2), {0x27,0x67}},
+
+ {LCM_SEND(2), {0x30,0x02}},
+ {LCM_SEND(2), {0x31,0x22}},
+ {LCM_SEND(2), {0x32,0x11}},
+ {LCM_SEND(2), {0x33,0xaa}},
+ {LCM_SEND(2), {0x34,0xbb}},
+ {LCM_SEND(2), {0x35,0x66}},
+ {LCM_SEND(2), {0x36,0x00}},
+ {LCM_SEND(2), {0x37,0x22}},
+ {LCM_SEND(2), {0x38,0x22}},
+ {LCM_SEND(2), {0x39,0x22}},
+ {LCM_SEND(2), {0x3A,0x22}},
+ {LCM_SEND(2), {0x3B,0x22}},
+ {LCM_SEND(2), {0x3C,0x22}},
+ {LCM_SEND(2), {0x3D,0x22}},
+ {LCM_SEND(2), {0x3E,0x22}},
+ {LCM_SEND(2), {0x3F,0x22}},
+
+ {LCM_SEND(2), {0x40,0x22}},
+ {LCM_SEND(2), {0x53,0x1a}},
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x07}},
+ {LCM_SEND(2), {0x18,0x1d}},
+ {LCM_SEND(2), {0x17,0x12}},
+
+ {LCM_SEND(2), {0x02,0x77}},
+
+ {LCM_SEND(2), {0xe1,0x79}},
+
+ {LCM_SEND(2), {0x06,0x13}},
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+
+// {LCM_SEND(2), {0x35,0x00}},
+
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(1)},
+
+// {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x08}},
+};
+
+#else /*For SPRD*/
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},// Change to Page 1
+ {LCM_SLEEP(5)},
+
+ {LCM_SEND(2), {0x08,0x10}},// output SDA
+
+ {LCM_SEND(2), {0x21,0x01}},// DE = 1 Active
+
+ {LCM_SEND(2), {0x30,0x02}},// 480 X 800
+ {LCM_SEND(2), {0x31,0x02}}, // 2-dot Inversion
+
+ {LCM_SEND(2), {0x50,0x78}},// VGMP
+ {LCM_SEND(2), {0x51,0x78}},// VGMN
+ {LCM_SEND(2), {0x52,0x00}}, //Flicker
+ {LCM_SEND(2), {0x53,0x61}},//Flicker
+
+ {LCM_SEND(2), {0x60,0x07}},// SDTI
+ {LCM_SEND(2), {0x61,0x00}},// CRTI
+ {LCM_SEND(2), {0x62,0x08}},// EQTI
+ {LCM_SEND(2), {0x63,0x00}}, // PCTI
+
+ {LCM_SEND(2), {0x40,0x15}},// VGH/VGL
+ {LCM_SEND(2), {0x41,0x44}}, // VGH/VGL
+ {LCM_SEND(2), {0x42,0x03}},// VGH/VGL
+ {LCM_SEND(2), {0x43,0x89}},// VGH/VGL
+ {LCM_SEND(2), {0x44,0x82}},// VGH/VGL
+
+//++++++++++++++++++ Gamma Setting ++++++++++++++++++//
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},// Change to Page 1
+
+ {LCM_SEND(2), {0xA0,0x00}},// Gamma 0
+ {LCM_SEND(2), {0xA1,0x06}},// Gamma 4
+ {LCM_SEND(2), {0xA2,0x0c}},// Gamma 8
+ {LCM_SEND(2), {0xA3,0x12}},// Gamma 16
+ {LCM_SEND(2), {0xA4,0x0d}},// Gamma 24
+ {LCM_SEND(2), {0xA5,0x1f}},// Gamma 52
+ {LCM_SEND(2), {0xA6,0x0b}},// Gamma 80
+ {LCM_SEND(2), {0xA7,0x08}},// Gamma 108
+ {LCM_SEND(2), {0xA8,0x04}},// Gamma 147
+ {LCM_SEND(2), {0xA9,0x0a}},// Gamma 175
+ {LCM_SEND(2), {0xAA,0x06}},// Gamma 203
+ {LCM_SEND(2), {0xAB,0x04}},// Gamma 231
+ {LCM_SEND(2), {0xAC,0x10}},// Gamma 239
+ {LCM_SEND(2), {0xAD,0x37}},// Gamma 247
+ {LCM_SEND(2), {0xAE,0x30}},// Gamma 251
+ {LCM_SEND(2), {0xAF,0x07}},// Gamma 255
+
+///==============Nagitive
+ {LCM_SEND(2), {0xC0,0x00}}, // Gamma 0
+ {LCM_SEND(2), {0xC1,0x06}}, // Gamma 4
+ {LCM_SEND(2), {0xC2,0x1f}}, // Gamma 8
+ {LCM_SEND(2), {0xC3,0x06}}, // Gamma 16
+ {LCM_SEND(2), {0xC4,0x04}}, // Gamma 24
+ {LCM_SEND(2), {0xC5,0x13}}, // Gamma 52
+ {LCM_SEND(2), {0xC6,0x05}}, // Gamma 80
+ {LCM_SEND(2), {0xC7,0x05}}, // Gamma 108
+ {LCM_SEND(2), {0xC8,0x03}}, // Gamma 147
+ {LCM_SEND(2), {0xC9,0x06}}, // Gamma 175
+ {LCM_SEND(2), {0xCA,0x06}}, // Gamma 203
+ {LCM_SEND(2), {0xCB,0x03}}, // Gamma 231
+ {LCM_SEND(2), {0xCC,0x01}}, // Gamma 239
+ {LCM_SEND(2), {0xCD,0x27}}, // Gamma 247
+ {LCM_SEND(2), {0xCE,0x24}}, // Gamma 251
+ {LCM_SEND(2), {0xCF,0x07}}, // Gamma 255
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x06}}, // Change to Page 6
+
+ {LCM_SEND(2), {0x00,0x3c}},
+ {LCM_SEND(2), {0x01,0x06}},
+ {LCM_SEND(2), {0x02,0x00}},
+ {LCM_SEND(2), {0x03,0x00}},
+ {LCM_SEND(2), {0x04,0x0d}},
+ {LCM_SEND(2), {0x05,0x0d}},
+ {LCM_SEND(2), {0x06,0x80}},
+ {LCM_SEND(2), {0x07,0x04}},
+ {LCM_SEND(2), {0x08,0x03}},
+ {LCM_SEND(2), {0x09,0x00}},
+ {LCM_SEND(2), {0x0A,0x00}},
+ {LCM_SEND(2), {0x0B,0x00}},
+ {LCM_SEND(2), {0x0C,0x0d}},
+ {LCM_SEND(2), {0x0D,0x0d}},
+ {LCM_SEND(2), {0x0E,0x00}},
+ {LCM_SEND(2), {0x0F,0x00}},
+
+ {LCM_SEND(2), {0x10,0x50}},
+ {LCM_SEND(2), {0x11,0xd0}},
+ {LCM_SEND(2), {0x12,0x00}},
+ {LCM_SEND(2), {0x13,0x00}},
+ {LCM_SEND(2), {0x14,0x00}},
+ {LCM_SEND(2), {0x15,0xc0}},
+ {LCM_SEND(2), {0x16,0x08}},
+ {LCM_SEND(2), {0x17,0x00}},
+ {LCM_SEND(2), {0x18,0x00}},
+ {LCM_SEND(2), {0x19,0x00}},
+ {LCM_SEND(2), {0x1A,0x00}},
+ {LCM_SEND(2), {0x1B,0x00}},
+ {LCM_SEND(2), {0x1C,0x48}},
+ {LCM_SEND(2), {0x1D,0x00}},
+
+ {LCM_SEND(2), {0x20,0x01}},
+ {LCM_SEND(2), {0x21,0x23}},
+ {LCM_SEND(2), {0x22,0x45}},
+ {LCM_SEND(2), {0x23,0x67}},
+ {LCM_SEND(2), {0x24,0x01}},
+ {LCM_SEND(2), {0x25,0x23}},
+ {LCM_SEND(2), {0x26,0x45}},
+ {LCM_SEND(2), {0x27,0x67}},
+
+ {LCM_SEND(2), {0x30,0x13}},
+ {LCM_SEND(2), {0x31,0x22}},
+ {LCM_SEND(2), {0x32,0xdd}},
+ {LCM_SEND(2), {0x33,0xcc}},
+ {LCM_SEND(2), {0x34,0xbb}},
+ {LCM_SEND(2), {0x35,0xaa}},
+ {LCM_SEND(2), {0x36,0x22}},
+ {LCM_SEND(2), {0x37,0x26}},
+ {LCM_SEND(2), {0x38,0x72}},
+ {LCM_SEND(2), {0x39,0xff}},
+ {LCM_SEND(2), {0x3A,0x22}},
+ {LCM_SEND(2), {0x3B,0xee}},
+ {LCM_SEND(2), {0x3C,0x22}},
+ {LCM_SEND(2), {0x3D,0x22}},
+ {LCM_SEND(2), {0x3E,0x22}},
+ {LCM_SEND(2), {0x3F,0x22}},
+ {LCM_SEND(2), {0x52,0x10}}, /*reduce current when battery charging*/
+
+ {LCM_SEND(2), {0x40,0x22}},
+
+ {LCM_SEND(2), {0x58,0xa7}},//refresh black after resume
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x07}}, // Change to Page 7
+ {LCM_SEND(2), {0x17,0x22}},
+
+ {LCM_SEND(2), {0x02,0x77}},
+
+//****************************************************************************//
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}}, // Change to Page 0
+
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(10)},
+ };
+
+#endif
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(10)},
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(2), {0x58,0x91}},
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39, {LCM_SEND(8), {0x6, 0, 0xFF, 0xFF, 0x98, 0x06,0x04,0x01}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t ili9806e_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug(KERN_DEBUG "ili9806e_mipi_init\n");
+
+ msleep(2);
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((init->tag & LCM_TAG_MASK) * 1000);
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t ili9806e_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_ili9806e_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x02, 3,(uint8_t *)read_data);
+ printk("lcd_ili9806e_mipi read id 0xc5 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if((0x04 == read_data[0])){
+ printk("lcd_ili9806e_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x04;
+ }
+ }
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t ili9806e_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "ili9806e_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((sleep_in_out->tag & LCM_TAG_MASK) * 1000);
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t ili9806e_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ uint32_t reg_val_1 = 0;
+ uint32_t reg_val_2 = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_ili9806e_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_ili9806e mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_ili9806e_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+
+static uint32_t ili9806e_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ pr_debug("ili9806e_check_esd!\n");
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = ili9806e_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0x9c){
+ pr_debug("ili9806e_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("ili9806e_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static uint32_t ili9806e_mipi_after_suspend(struct panel_spec *self)
+{
+ return 0;
+}
+
+static struct panel_operations lcd_ili9806e_mipi_operations = {
+ .panel_init = ili9806e_mipi_init,
+ .panel_readid = ili9806e_readid,
+ .panel_enter_sleep = ili9806e_enter_sleep,
+ .panel_esd_check = ili9806e_check_esd,
+ .panel_after_suspend = ili9806e_mipi_after_suspend,
+
+};
+ +static struct timing_rgb lcd_ili9806e_mipi_timing = {
+ .hfp = 60, /* unit: pixel */// 100
+ .hbp = 80,//80
+ .hsync = 60,//6
+ .vfp = 20, /*unit: line*/
+ .vbp = 14,
+ .vsync =6, //6,
+};
+
+static struct info_mipi lcd_ili9806e_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000, //500->10MHz,400->8M in lp mode
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_ili9806e_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_ili9806e_mipi_spec = {
+ //.cap = PANEL_CAP_NOT_TEAR_SYNC,
+ .width = 480,
+ .height = 800,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .reset_timing = {5, 15, 120},
+ .info = {
+ .mipi = &lcd_ili9806e_mipi_info
+ },
+ .ops = &lcd_ili9806e_mipi_operations,
+};
+
+struct panel_cfg lcd_ili9806e_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x04,
+ .lcd_name = "lcd_ili9806e_mipi",
+ .panel = &lcd_ili9806e_mipi_spec,
+};
+
+static int __init lcd_ili9806e_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_ili9806e_mipi);
+}
+
+subsys_initcall(lcd_ili9806e_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_jd9161_mipi.c b/drivers/video/sprdfb/lcd/lcd_jd9161_mipi.c new file mode 100644 index 00000000..ae6311cf --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_jd9161_mipi.c @@ -0,0 +1,380 @@ +/* drivers/video/sc8825/lcd_jd9161_mipi.c
+ *
+ * Support for jd9161 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(6), {4,0,0xBF,0x91,0x61,0xF2}},
+ {LCM_SLEEP(1)},
+ {LCM_SEND(5), {3,0,0xB3,0x00,0x7F}},//VCOM
+ {LCM_SLEEP(1)},
+ {LCM_SEND(5), {3,0,0xB4,0x00,0x7F}},//VCOM_R
+ {LCM_SLEEP(1)},
+ {LCM_SEND(9), {7,0,0xB8,0x00,0xB6,0x01,0x00,0xB6,0x01}},//VGMP, VGSP, VGMN
+ {LCM_SLEEP(1)},
+ {LCM_SEND(6), {4,0,0xBA,0x34,0x23,0x00}},//GIP output volta
+ {LCM_SLEEP(1)},
+ {LCM_SEND(2), {0xC3,0x02}},//column
+ {LCM_SLEEP(1)},
+ {LCM_SEND(5), {3,0,0xC4,0x00,0x64}},//TCON
+ {LCM_SLEEP(1)},
+ {LCM_SEND(12), {10,0,0xC7,0x00,0x01,0x32,0x05,0x65,0x2C,0x13,0xA5,0xA5}},//POWER CTRL
+ {LCM_SLEEP(1)},
+ //Gamma
+ {LCM_SEND(41), {39,0,0xC8,0x74,0x70,0x2C,0x3A,0x1C,0x11,0x17,0x06,0x24,0x29,
+ 0x2F,0x55,0x4B,0x5D,0x58,0x61,0x5D,0x57,0x50,
+ 0x74,0x70,0x2C,0x3A,0x1C,0x11,0x17,0x06,0x24,0x29,
+ 0x2F,0x55,0x4B,0x5D,0x58,0x61,0x5D,0x57,0x50}},
+ {LCM_SLEEP(1)},
+ {LCM_SEND(19), {17,0,0xD4,0x1F,0x1E,0x1F,0x00,0x10,0x1F,0x1F,0x04,0x08,0x06,
+ 0x0A,0x1F,0x1F,0x1F,0x1F,0x1F}}, //SET GIP_L
+ {LCM_SLEEP(1)},
+ {LCM_SEND(19), {17,0,0xD5,0x1F,0x1E,0x1F,0x01,0x11,0x1F,0x1F,0x05,0x09,0x07,
+ 0x0B,0x1F,0x1F,0x1F,0x1F,0x1F}}, //SET GIP_R
+ {LCM_SLEEP(1)},
+ {LCM_SEND(19), {17,0,0xD6,0x1F,0x1F,0x1E,0x11,0x01,0x1F,0x1F,0x0B,0x07,0x09,
+ 0x05,0x1F,0x1F,0x1F,0x1F,0x1F}}, //SET GIP_GS_L
+ {LCM_SLEEP(1)},
+ {LCM_SEND(19), {17,0,0xD7,0x1F,0x1F,0x1E,0x10,0x00,0x1F,0x1F,0x0A,0x06,0x08,
+ 0x04,0x1F,0x1F,0x1F,0x1F,0x1F}}, //SET GIP_GS_R
+ {LCM_SLEEP(1)},
+ {LCM_SEND(23), {21,0,0xD8,0x20,0x02,0x0A,0x10,0x05,0x30,0x01,0x02,0x30,0x01,0x02,0x06,0x70,
+ 0x53,0x2C,0x73,0x09,0x06,0x70,0x08}}, //SET GIP1
+ {LCM_SLEEP(1)},
+ {LCM_SEND(22), {20,0,0xD9,0x00,0x0A,0x0A,0x88,0x00,0x00,0x06,0x7B,0x00,0x00,
+ 0x00,0x3B,0x2F,0x1F,0x00,0x00,0x00,0x03,0x7B}}, //SET GIP2
+ {LCM_SLEEP(1)},
+ {LCM_SEND(1), {0x11}},//SLP OUT
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29}},//DISP ON
+ {LCM_SLEEP(50)},
+
+ };
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(10)},
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(2), {0x58,0x91}},
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39, {LCM_SEND(6), {4,0,0xBF,0x91,0x61,0xF2}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t jd9161_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk( "kernel jd9161_mipi_init\n");
+
+ msleep(2);
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((init->tag & LCM_TAG_MASK) * 1000);
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t jd9161_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel lcd_jd9161_mipi read id!\n");
+#if 1
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x04, 3,(uint8_t *)read_data);
+ printk("lcd_jd9161_mipi read id 0x04 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if((0x91 == read_data[0])){
+ printk("lcd_jd9161_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x916100;
+ }
+ }
+ mipi_eotp_set(1,1);
+ #endif
+ return 0x916100;
+}
+
+static int32_t jd9161_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("jd9161_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((sleep_in_out->tag & LCM_TAG_MASK) * 1000);
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t jd9161_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ uint32_t reg_val_1 = 0;
+ uint32_t reg_val_2 = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_jd9161_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_jd9161 mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_jd9161_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+
+static uint32_t jd9161_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ pr_debug("jd9161_check_esd!\n");
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = jd9161_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0x9c){
+ pr_debug("jd9161_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("jd9161_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+
+static struct panel_operations lcd_jd9161_mipi_operations = {
+ .panel_init = jd9161_mipi_init,
+ .panel_readid = jd9161_readid,
+ .panel_enter_sleep = jd9161_enter_sleep,
+ .panel_esd_check = jd9161_check_esd,
+};
+ +static struct timing_rgb lcd_jd9161_mipi_timing = {
+ .hfp = 20, /* unit: pixel */// 100
+ .hbp = 20,//80
+ .hsync = 20,//6
+ .vfp = 6, /*unit: line*/
+ .vbp = 6,
+ .vsync =6, //6,
+};
+
+static struct info_mipi lcd_jd9161_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 450*1000, //500->10MHz,400->8M in lp mode
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_jd9161_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_jd9161_mipi_spec = {
+ //.cap = PANEL_CAP_NOT_TEAR_SYNC,
+ .width = 480,
+ .height = 800,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .reset_timing = {5, 15, 120},
+ .info = {
+ .mipi = &lcd_jd9161_mipi_info
+ },
+ .ops = &lcd_jd9161_mipi_operations,
+};
+
+struct panel_cfg lcd_jd9161_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x916100,
+ .lcd_name = "lcd_jd9161_mipi",
+ .panel = &lcd_jd9161_mipi_spec,
+};
+
+static int __init lcd_jd9161_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_jd9161_mipi);
+}
+
+subsys_initcall(lcd_jd9161_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35502_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt35502_mipi.c new file mode 100755 index 00000000..cccb146f --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35502_mipi.c @@ -0,0 +1,300 @@ +#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+#include <mach/gpio.h>
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 100
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ //Power setting Sequence
+ {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x01}},
+ {LCM_SEND(4),{2,0,0xB0,0x08}},
+ {LCM_SEND(4),{2,0,0xB2,0x40}},
+ {LCM_SEND(4),{2,0,0xB3,0x28}},
+ {LCM_SEND(4),{2,0,0xB4,0x19}},
+ {LCM_SEND(4),{2,0,0xB5,0x54}},
+ {LCM_SEND(4),{2,0,0xB9,0x36}},
+ {LCM_SEND(4),{2,0,0xBA,0x024}},
+ {LCM_SEND(5),{3,0,0xBC,0xA0,0x00}},
+ {LCM_SEND(5),{3,0,0xBD,0xA0,0x00}},
+
+
+ //gamma setting
+ {LCM_SEND(19),{17,0,0xD1,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xD2,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xD3,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xD4,0x03,0x5A,0x03,0x9A}},
+ {LCM_SEND(19),{17,0,0xD5,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xD6,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xD7,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xD8,0x03,0x5A,0x03,0x9A}},
+ {LCM_SEND(19),{17,0,0xD9,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xDD,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xDE,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xDF,0x03,0x5A,0x03,0x9A}},
+ {LCM_SEND(19),{17,0,0xE0,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xE1,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xE2,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xE3,0x03,0x5A,0x03,0x9A}},
+ {LCM_SEND(19),{17,0,0xE4,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xE5,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xE6,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xE7,0x03,0x5A,0x03,0x9A}},
+ {LCM_SEND(19),{17,0,0xE8,0x00,0x3D,0x00,0x67,0x00,0x97,0x00,0xBE,0x00,0xE4,0x01,0x1B,0x01,0x45,0x01,0x80}},
+ {LCM_SEND(19),{17,0,0xE9,0x01,0xA8,0x01,0xDF,0x02,0x06,0x02,0x3C,0x02,0x65,0x02,0x66,0x02,0x89,0x02,0xAC}},
+ {LCM_SEND(19),{17,0,0xEA,0x02,0xC0,0x02,0xD8,0x02,0xE6,0x02,0xF8,0x03,0x04,0x03,0x14,0x03,0x1E,0x03,0x2B}},
+ {LCM_SEND(7),{5,0,0xEB,0x03,0x5A,0x03,0x9A}},
+
+ //initializing sequence
+
+ {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x00}},
+ {LCM_SEND(5),{3,0,0xB1,0x16,0x08}},
+ {LCM_SEND(5),{3,0,0xB4,0x08,0x50}},
+ {LCM_SEND(4),{2,0,0xB6,0x03}},
+ {LCM_SEND(5),{3,0,0xB7,0x70,0x70}},
+ {LCM_SEND(5),{3,0,0xB8,0x61,0x66}},
+ {LCM_SEND(4),{2,0,0xBC,0x02}},
+
+ {LCM_SEND(21),{19,0,0xC8,0x80,0x00,0x46,0x64,0x46,0x64,0x46,0x64,0x46,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64}},
+ {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x00,0x00}},
+ {LCM_SEND(7),{5,0,0xFF,0xAA,0x55,0x25,0x01}},
+ {LCM_SEND(4),{2,0,0x6F,0x02}},
+ {LCM_SEND(4),{2,0,0xF4,0x57}},
+ {LCM_SEND(6),{4,0,0xAA,0x55,0x25,0x00}},
+ {LCM_SEND(4),{2,0,0x36,0x00}},
+ {LCM_SEND(4),{2,0,0x35,0x00}},
+ {LCM_SEND(4),{2,0,0x0B,0xD8}},
+
+ //Display on
+ {LCM_SEND(1),{0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1),{0x29}},
+ {LCM_SLEEP(100)},
+
+};
+
+static LCM_Init_Code disp_on[] = {
+ {LCM_SEND(1),{0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1),{0x29}},
+ {LCM_SLEEP(100)},
+
+};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(150)}, //>150ms
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(150)}, //>150ms
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},//>120ms
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)}, //>20ms
+};
+static int32_t nt35502_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel nt35502_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t nt35502_readid(struct panel_spec *self)
+{
+ int32_t j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("kernel lcd_nt35502_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x01;
+ param[1] = 0x00;
+ mipi_force_write(0x04, param, 2);
+ read_rtn = mipi_force_read(0xda,1,&read_data[0]);
+ LCD_PRINT("lcd_nt35502_mipi read id 0xda value is 0x%x!\n",read_data[0]);
+ read_rtn = mipi_force_read(0xdb,1,&read_data[1]);
+ LCD_PRINT("lcd_nt35502_mipi read id 0xdb value is 0x%x!\n",read_data[1]);
+ read_rtn = mipi_force_read(0xdc,1,&read_data[2]);
+ LCD_PRINT("lcd_nt35502_mipi read id 0xdc value is 0x%x!\n",read_data[2]);
+
+ // if((0x55 == read_data[0])&&(0xbc == read_data[1])&&(0x90 == read_data[2])){
+ printk("lcd_nt35502_mipi read id success!\n");
+ return 0x8370;
+ // }
+ }
+
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+
+static int32_t nt35502_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel nt35502_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(sleep_in_out->tag & LCM_TAG_MASK);
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static struct panel_operations lcd_nt35502_mipi_operations = {
+ .panel_init = nt35502_mipi_init,
+ .panel_readid = nt35502_readid,
+ .panel_enter_sleep = nt35502_enter_sleep,
+};
+
+static struct timing_rgb lcd_nt35502_mipi_timing = {
+ .hfp = 160, /* unit: pixel */
+ .hbp = 20,
+ .hsync = 20,
+ .vfp = 1, /*unit: line*/
+ .vbp = 11,
+ .vsync = 4,
+};
+
+
+static struct info_mipi lcd_nt35502_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq =500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt35502_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt35502_mipi_spec = {
+ .width = 480,
+ .height = 800,
+ .fps = 62,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_nt35502_mipi_info
+ },
+ .ops = &lcd_nt35502_mipi_operations,
+};
+struct panel_cfg lcd_nt35502_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x8370,
+ .lcd_name = "lcd_nt35502_mipi",
+ .panel = &lcd_nt35502_mipi_spec,
+};
+
+//temp code
+static int __init lcd_nt35502_mipi_init(void)
+{
+/*
+ printk("nt35502_mipi_init: set lcd backlight.\n");
+
+ if (gpio_request(214, "LCD_BL")) {
+ printk("Failed ro request LCD_BL GPIO_%d \n",
+ 214);
+ return -ENODEV;
+ }
+ gpio_direction_output(214, 1);
+ gpio_set_value(214, 1);
+*/
+
+ return sprdfb_panel_register(&lcd_nt35502_mipi);
+}
+
+subsys_initcall(lcd_nt35502_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35510_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt35510_mipi.c new file mode 100644 index 00000000..3ef26edb --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35510_mipi.c @@ -0,0 +1,291 @@ +/* drivers/video/sc8825/lcd_nt35516_mipi.c
+ *
+ * Support for nt35516 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_Delay(ms) uDelay(ms*1000)
+
+#define MAX_DATA 56
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x01}},
+
+{LCM_SEND(6), {4, 0, 0xB0,0x09,0x09,0x09}},
+{LCM_SEND(6), {4, 0, 0xB6,0x34,0x34,0x34}},
+{LCM_SEND(6), {4, 0, 0xB1,0x09,0x09,0x09}},
+{LCM_SEND(6), {4, 0, 0xB7,0x24,0x24,0x24}},
+{LCM_SEND(6), {4, 0, 0xB3,0x05,0x05,0x05}},
+{LCM_SEND(6), {4, 0, 0xB9,0x24,0x24,0x24}},
+
+{LCM_SEND(2), {0xBF,0x01}},
+
+{LCM_SEND(6), {4, 0, 0xB5,0x0B,0x0B,0x0B}},
+{LCM_SEND(6), {4, 0, 0xBA,0x24,0x24,0x24}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0xA3,0x00}},
+{LCM_SEND(6), {4, 0, 0xBD,0x00,0xA3,0x00}},
+
+{LCM_SEND(5), {3, 0, 0xBE,0x00,0x58}},
+
+{LCM_SEND(55), {53, 0, 0xD1,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD2,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD3,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD4,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD5,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD6,0x00,0x01,0x00,0x43,0x00,0x6B,0x00,0x87,0x00,0xA3,
+0x00,0xCE,0x00,0xF1,0x01,0x27,0x01,0x53,0x01,0x98,0x01,0xCE,0x02,0x22,0x02,
+0x83,0x02,0x78,0x02,0x9E,0x02,0xDD,0x03,0x00,0x03,0x2E,0x03,0x54,0x03,0x7F,
+0x03,0x95,0x03,0xB3,0x03,0xC2,0x03,0xE1,0x03,0xF1,0x03,0xFE}},
+
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+
+{LCM_SEND(5), {3, 0, 0xB1,0xFC,0x04}},
+{LCM_SEND(2), {0x36,0x02}},
+{LCM_SEND(2), {0xB6,0x0A}},
+{LCM_SEND(5), {3, 0, 0xB7,0x00,0x00}},
+{LCM_SEND(7), {5, 0, 0xB8,0x01,0x05,0x05,0x05}},
+{LCM_SEND(2), {0xBA,0x01}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0x00,0x00}},
+{LCM_SEND(8), {6, 0, 0xBD,0x01,0x84,0x07,0x32,0x00}},
+{LCM_SEND(8), {6, 0, 0xBE,0x01,0x84,0x07,0x31,0x00}},
+{LCM_SEND(8), {6, 0, 0xBF,0x01,0x84,0x07,0x31,0x00}},
+{LCM_SEND(2), {0x35,0x00}},// Tearing Effect On
+{LCM_SEND(6), {4, 0, 0xCC,0x03,0x00,0x00}},
+{LCM_SEND(2), {0x3A, 0x77}},
+
+{LCM_SEND(1), {0x11}}, // sleep out
+{LCM_SLEEP(120),},
+{LCM_SEND(1), {0x29}}, // display on
+{LCM_SLEEP(100),},
+{LCM_SEND(1), {0x2c}}, // normal on
+
+
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+{LCM_SEND(2), {0x4f, 0x01}},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Init_Code change_fps_40[] = {
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+{LCM_SEND(8), {6, 0, 0xBD,0x02,0x46,0x1C,0x1C,0x00}},
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x00,0x00}},
+};
+
+static LCM_Init_Code change_fps_60[] = {
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+{LCM_SEND(8), {6, 0, 0xBD,0x01,0x84,0x1C,0x1C,0x00}},
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x00,0x00}},
+};
+
+static int32_t nt35510_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+
+ pr_debug(KERN_DEBUG "nt35510_mipi_init\n");
+
+ mipi_set_cmd_mode();
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ return 0;
+}
+
+static uint32_t nt35510_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ return 0x10;
+}
+
+static int32_t nt35510_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ printk(KERN_DEBUG "nt35516_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static int32_t nt35510_change_fps(struct panel_spec *self, int fps_level)
+{
+ int32_t i = 0;
+ LCM_Init_Code *change_fps = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ printk(KERN_DEBUG "nt35510_change_fps, fps_level = %d\n", fps_level);
+
+ if(fps_level < 50){
+ change_fps = change_fps_40;
+ size = ARRAY_SIZE(change_fps_40);
+ }else{
+ change_fps = change_fps_60;
+ size = ARRAY_SIZE(change_fps_60);
+ }
+
+ for(i = 0; i <size ; i++){
+ tag = (change_fps->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(change_fps->data, (change_fps->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((change_fps->tag & LCM_TAG_MASK));
+ }
+ change_fps++;
+ }
+ return 0;
+
+}
+
+static struct panel_operations lcd_nt35510_mipi_operations = {
+ .panel_init = nt35510_mipi_init,
+ .panel_readid = nt35510_readid,
+ .panel_enter_sleep = nt35510_enter_sleep,
+ .panel_change_fps= nt35510_change_fps,
+};
+
+static struct timing_rgb lcd_nt35510_mipi_timing = {
+ .hfp = 20, /* unit: pixel */
+ .hbp = 20,
+ .hsync = 4,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_nt35510_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_CMD,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt35510_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt35510_mipi_spec = {
+ .width = 480,
+ .height = 800,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_nt35510_mipi_info
+ },
+ .ops = &lcd_nt35510_mipi_operations,
+};
+
+
+struct panel_cfg lcd_nt35510_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x10,
+ .lcd_name = "lcd_nt35510_mipi",
+ .panel = &lcd_nt35510_mipi_spec,
+};
+
+static int __init lcd_nt35510_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35510_mipi);
+}
+
+subsys_initcall(lcd_nt35510_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35512_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt35512_mipi.c new file mode 100644 index 00000000..f17864e8 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35512_mipi.c @@ -0,0 +1,183 @@ +/* drivers/video/sc8825/lcd_nt35516_mipi.c
+ *
+ * Support for nt35516 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_Delay(ms) uDelay(ms*1000)
+
+#define MAX_DATA 56
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x01}},
+
+{LCM_SEND(6), {4, 0, 0xB0,0x09,0x09,0x09}},
+{LCM_SEND(6), {4, 0, 0xB6,0x34,0x34,0x34}},
+{LCM_SEND(6), {4, 0, 0xB1,0x09,0x09,0x09}},
+{LCM_SEND(6), {4, 0, 0xB7,0x24,0x24,0x24}},
+{LCM_SEND(6), {4, 0, 0xB3,0x05,0x05,0x05}},
+{LCM_SEND(6), {4, 0, 0xB9,0x24,0x24,0x24}},
+
+{LCM_SEND(2), {0xBF,0x01}},
+
+{LCM_SEND(6), {4, 0, 0xB5,0x03,0x03,0x03}},
+{LCM_SEND(6), {4, 0, 0xBA,0x24,0x24,0x24}},
+{LCM_SEND(2), {0xC2,0x01}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0x90,0x00}},
+{LCM_SEND(6), {4, 0, 0xBD,0x00,0x90,0x00}},
+
+{LCM_SEND(5), {3, 0, 0xBE,0x00,0x57}},
+
+{LCM_SEND(55), {53, 0, 0xD1,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD2,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD3,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD4,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD5,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+{LCM_SEND(55), {53, 0, 0xD6,0x00,0x01,0x00,0x1D,0x00,0x48,0x00,0x64,0x00,0x7E,0x00,0xB1,0x00,0xD3,0x01,0x07,0x01,0x35,0x01,0x7B,0x01,0xB3,0x02,0x03,0x02,0x48,0x02,0x49,0x02,0x88,0x02,0xC7,0x02,0xF3,0x03,0x21,0x03,0x46,0x03,0x74,0x03,0x8F,0x03,0xA3,0x03,0xAC,0x03,0xB7,0x03,0xBF,0x03,0xFE}},
+
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+
+{LCM_SEND(2), {0xB6,0x0A}},
+{LCM_SEND(5), {3, 0, 0xB7,0x00,0x00}},
+{LCM_SEND(7), {5, 0, 0xB8,0x01,0x05,0x05,0x05}},
+{LCM_SEND(2), {0xBA,0x01}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0x00,0x00}},
+//{LCM_SEND(8), {6, 0, 0xBD,0x01,0x4D,0x07,0x31,0x00}},
+//{LCM_SEND(8), {6, 0, 0xBE,0x01,0x84,0x07,0x31,0x00}},
+//{LCM_SEND(8), {6, 0, 0xBF,0x01,0x84,0x07,0x31,0x00}},
+{LCM_SEND(6), {4, 0, 0xCC,0x03,0x00,0x00}},
+{LCM_SEND(5), {3, 0, 0xB1,0xFC,0x00}},
+{LCM_SEND(2), {0x35,0x00}}, // Tearing Effect On
+{LCM_SEND(2), {0x36,0xC2}},
+{LCM_SEND(2), {0x3A, 0x77}},
+
+
+
+{LCM_SEND(1), {0x11}}, // sleep out
+{LCM_SLEEP(120),},
+{LCM_SEND(1), {0x29}}, // display on
+{LCM_SLEEP(100),},
+{LCM_SEND(1), {0x2c}}, // normal on
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in = {LCM_SEND(1), {0x10}};
+
+static LCM_Init_Code sleep_out = {LCM_SEND(1), {0x11}};
+
+static int32_t nt35512_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ pr_debug(KERN_DEBUG "nt35512_init\n");
+
+ mipi_set_cmd_mode();
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ return 0;
+}
+
+static uint32_t nt35512_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ return 0x12;
+}
+
+static struct panel_operations lcd_nt35512_mipi_operations = {
+ .panel_init = nt35516_mipi_init,
+ .panel_readid = nt35516_readid,
+};
+
+static struct timing_rgb lcd_nt35512_mipi_timing = {
+ .hfp = 200, /* unit: pixel */
+ .hbp = 200,
+ .hsync = 8,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_nt35512_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt35512_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt35512_mipi_spec = {
+ .width = 480,
+ .height = 800,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_nt35512_mipi_info
+ },
+ .ops = &lcd_nt35512_mipi_operations,
+};
+
+struct panel_cfg lcd_nt35512_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x12,
+ .lcd_name = "lcd_nt35516_mipi",
+ .panel = &lcd_nt35516_mipi_spec,
+};
+
+static int __init lcd_nt35512_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35516_mipi);
+}
+
+subsys_initcall(lcd_nt35512_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35516_mcu.c b/drivers/video/sprdfb/lcd/lcd_nt35516_mcu.c new file mode 100644 index 00000000..af2df710 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35516_mcu.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +static int32_t nt35516_init(struct panel_spec *self) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("nt35516_init\n"); + + send_cmd(0xFF00); send_data(0x00AA); /*AA*/ + send_cmd(0xFF01); send_data(0x0055);/*55*/ + send_cmd(0xFF02); send_data(0x0025);/*08*/ + send_cmd(0xFF03); send_data(0x0001);/*01*/ + + send_cmd(0xF300); send_data(0x0002); + send_cmd(0xF303); send_data(0x0015); + + /*ENABPAGE 0*/ + send_cmd(0xF000); send_data(0x0055); /*Manufacture Command Set Control*/ + send_cmd(0xF001); send_data(0x00AA); + send_cmd(0xF002); send_data(0x0052); + send_cmd(0xF003); send_data(0x0008); + send_cmd(0xF004); send_data(0x0000); + + send_cmd(0xB800); send_data(0x0001); + send_cmd(0xB801); send_data(0x0002); + send_cmd(0xB802); send_data(0x0002); + send_cmd(0xB803); send_data(0x0002); + + send_cmd(0xBC00); send_data(0x0005); /*Zig-Zag Inversion*/ + send_cmd(0xBC01); send_data(0x0005); + send_cmd(0xBC02); send_data(0x0005); + + send_cmd(0xBD00);send_data(0x0001); + send_cmd(0xBD01);send_data(0x0063);//54fps + send_cmd(0xBD02);send_data(0x0010); + send_cmd(0xBD03);send_data(0x0038); + send_cmd(0xBD04);send_data(0x0001); + + + send_cmd(0x4C00); send_data(0x0011); /*DB4=1,Enable Vivid Color,DB4=0 Disable Vivid Color*/ + + /* ENA PAGE 1*/ + send_cmd(0xF000); send_data(0x0055); /*Manufacture Command Set Control */ + send_cmd(0xF001); send_data(0x00AA); + send_cmd(0xF002); send_data(0x0052); + send_cmd(0xF003); send_data(0x0008); + send_cmd(0xF004); send_data(0x0001);/*Page1*/ + + send_cmd(0xB000); send_data(0x0005); /*Setting AVDD Voltage 6V*/ + send_cmd(0xB001); send_data(0x0005); + send_cmd(0xB002); send_data(0x0005); + + send_cmd(0xB600); send_data(0x0044); /* Setting AVEE boosting time 2.5*vpnl */ + send_cmd(0xB601); send_data(0x0044); + send_cmd(0xB602); send_data(0x0044); + + send_cmd(0xB100); send_data(0x0005); /*Setting AVEE Voltage -6V*/ + send_cmd(0xB101); send_data(0x0005); + send_cmd(0xB102); send_data(0x0005); + + /*Sett AVEE boosting time -2.5NL*/ + send_cmd(0xB700); send_data(0x0034); + send_cmd(0xB701); send_data(0x0034); + send_cmd(0xB702); send_data(0x0034); + + /*Sett VGLX boosting time AVEVDD */ + send_cmd(0xBA00); send_data(0x0014); /*0x24 --> 0x14*/ + send_cmd(0xBA01); send_data(0x0014); + send_cmd(0xBA02); send_data(0x0014); + + /*Gammoltage */ + send_cmd(0xBC00); send_data(0x0000); + send_cmd(0xBC01); send_data(0x00A0);/*VGMP 0x88=4.7V 0x78=4.5V 0xA0=5.0V */ + send_cmd(0xBC02); send_data(0x0000);/*VGSP*/ + + //Gammoltage */ + send_cmd(0xBD00); send_data(0x0000); + send_cmd(0xBD01); send_data(0x00A0);/*VGMN 0x88=-4.7V 0x78=-4.5V 0xA0=-5.0V*/ + send_cmd(0xBD02); send_data(0x0000);/*VGSN*/ + + send_cmd(0xBE00); send_data(0x0057); /* Setting VCOM Offset Voltage 0x4E\u017eÄΪ0x57 20111019 LIYAN*/ + + /*GAMMED Positive*/ + send_cmd(0xD100); send_data(0x0000); + send_cmd(0xD101); send_data(0x0032); + send_cmd(0xD102); send_data(0x0000); + send_cmd(0xD103); send_data(0x0041); + send_cmd(0xD104); send_data(0x0000); + send_cmd(0xD105); send_data(0x0054); + send_cmd(0xD106); send_data(0x0000); + send_cmd(0xD107); send_data(0x0067); + send_cmd(0xD108); send_data(0x0000); + send_cmd(0xD109); send_data(0x007A); + send_cmd(0xD10A); send_data(0x0000); + send_cmd(0xD10B); send_data(0x0098); + send_cmd(0xD10C); send_data(0x0000); + send_cmd(0xD10D); send_data(0x00B0); + send_cmd(0xD10E); send_data(0x0000); + send_cmd(0xD10F); send_data(0x00DB); + send_cmd(0xD200); send_data(0x0001); + send_cmd(0xD201); send_data(0x0001); + send_cmd(0xD202); send_data(0x0001); + send_cmd(0xD203); send_data(0x003F); + send_cmd(0xD204); send_data(0x0001); + send_cmd(0xD205); send_data(0x0070); + send_cmd(0xD206); send_data(0x0001); + send_cmd(0xD207); send_data(0x00B4); + send_cmd(0xD208); send_data(0x0001); + send_cmd(0xD209); send_data(0x00EC); + send_cmd(0xD20A); send_data(0x0001); + send_cmd(0xD20B); send_data(0x00ED); + send_cmd(0xD20C); send_data(0x0002); + send_cmd(0xD20D); send_data(0x001E); + send_cmd(0xD20E); send_data(0x0002); + send_cmd(0xD20F); send_data(0x0051); + send_cmd(0xD300); send_data(0x0002); + send_cmd(0xD301); send_data(0x006C); + send_cmd(0xD302); send_data(0x0002); + send_cmd(0xD303); send_data(0x008D); + send_cmd(0xD304); send_data(0x0002); + send_cmd(0xD305); send_data(0x00A5); + send_cmd(0xD306); send_data(0x0002); + send_cmd(0xD307); send_data(0x00C9); + send_cmd(0xD308); send_data(0x0002); + send_cmd(0xD309); send_data(0x00EA); + send_cmd(0xD30A); send_data(0x0003); + send_cmd(0xD30B); send_data(0x0019); + send_cmd(0xD30C); send_data(0x0003); + send_cmd(0xD30D); send_data(0x0045); + send_cmd(0xD30E); send_data(0x0003); + send_cmd(0xD30F); send_data(0x007A); + send_cmd(0xD400); send_data(0x0003); + send_cmd(0xD401); send_data(0x00B0); + send_cmd(0xD402); send_data(0x0003); + send_cmd(0xD403); send_data(0x00F4); + + /*Posie Gamma for GREEN*/ + send_cmd(0xD500); send_data(0x0000); + send_cmd(0xD501); send_data(0x0037); + send_cmd(0xD502); send_data(0x0000); + send_cmd(0xD503); send_data(0x0041); + send_cmd(0xD504); send_data(0x0000); + send_cmd(0xD505); send_data(0x0054); + send_cmd(0xD506); send_data(0x0000); + send_cmd(0xD507); send_data(0x0067); + send_cmd(0xD508); send_data(0x0000); + send_cmd(0xD509); send_data(0x007A); + send_cmd(0xD50A); send_data(0x0000); + send_cmd(0xD50B); send_data(0x0098); + send_cmd(0xD50C); send_data(0x0000); + send_cmd(0xD50D); send_data(0x00B0); + send_cmd(0xD50E); send_data(0x0000); + send_cmd(0xD50F); send_data(0x00DB); + send_cmd(0xD600); send_data(0x0001); + send_cmd(0xD601); send_data(0x0001); + send_cmd(0xD602); send_data(0x0001); + send_cmd(0xD603); send_data(0x003F); + send_cmd(0xD604); send_data(0x0001); + send_cmd(0xD605); send_data(0x0070); + send_cmd(0xD606); send_data(0x0001); + send_cmd(0xD607); send_data(0x00B4); + send_cmd(0xD608); send_data(0x0001); + send_cmd(0xD609); send_data(0x00EC); + send_cmd(0xD60A); send_data(0x0001); + send_cmd(0xD60B); send_data(0x00ED); + send_cmd(0xD60C); send_data(0x0002); + send_cmd(0xD60D); send_data(0x001E); + send_cmd(0xD60E); send_data(0x0002); + send_cmd(0xD60F); send_data(0x0051); + send_cmd(0xD700); send_data(0x0002); + send_cmd(0xD701); send_data(0x006C); + send_cmd(0xD702); send_data(0x0002); + send_cmd(0xD703); send_data(0x008D); + send_cmd(0xD704); send_data(0x0002); + send_cmd(0xD705); send_data(0x00A5); + send_cmd(0xD706); send_data(0x0002); + send_cmd(0xD707); send_data(0x00C9); + send_cmd(0xD708); send_data(0x0002); + send_cmd(0xD709); send_data(0x00EA); + send_cmd(0xD70A); send_data(0x0003); + send_cmd(0xD70B); send_data(0x0019); + send_cmd(0xD70C); send_data(0x0003); + send_cmd(0xD70D); send_data(0x0045); + send_cmd(0xD70E); send_data(0x0003); + send_cmd(0xD70F); send_data(0x007A); + send_cmd(0xD800); send_data(0x0003); + send_cmd(0xD801); send_data(0x00A0); + send_cmd(0xD802); send_data(0x0003); + send_cmd(0xD803); send_data(0x00F4); + + /*Posie Gamma for BLUE*/ + send_cmd(0xD900); send_data(0x0000); + send_cmd(0xD901); send_data(0x0032); + send_cmd(0xD902); send_data(0x0000); + send_cmd(0xD903); send_data(0x0041); + send_cmd(0xD904); send_data(0x0000); + send_cmd(0xD905); send_data(0x0054); + send_cmd(0xD906); send_data(0x0000); + send_cmd(0xD907); send_data(0x0067); + send_cmd(0xD908); send_data(0x0000); + send_cmd(0xD909); send_data(0x007A); + send_cmd(0xD90A); send_data(0x0000); + send_cmd(0xD90B); send_data(0x0098); + send_cmd(0xD90C); send_data(0x0000); + send_cmd(0xD90D); send_data(0x00B0); + send_cmd(0xD90E); send_data(0x0000); + send_cmd(0xD90F); send_data(0x00DB); + send_cmd(0xDD00); send_data(0x0001); + send_cmd(0xDD01); send_data(0x0001); + send_cmd(0xDD02); send_data(0x0001); + send_cmd(0xDD03); send_data(0x003F); + send_cmd(0xDD04); send_data(0x0001); + send_cmd(0xDD05); send_data(0x0070); + send_cmd(0xDD06); send_data(0x0001); + send_cmd(0xDD07); send_data(0x00B4); + send_cmd(0xDD08); send_data(0x0001); + send_cmd(0xDD09); send_data(0x00EC); + send_cmd(0xDD0A); send_data(0x0001); + send_cmd(0xDD0B); send_data(0x00ED); + send_cmd(0xDD0C); send_data(0x0002); + send_cmd(0xDD0D); send_data(0x001E); + send_cmd(0xDD0E); send_data(0x0002); + send_cmd(0xDD0F); send_data(0x0051); + send_cmd(0xDE00); send_data(0x0002); + send_cmd(0xDE01); send_data(0x006C); + send_cmd(0xDE02); send_data(0x0002); + send_cmd(0xDE03); send_data(0x008D); + send_cmd(0xDE04); send_data(0x0002); + send_cmd(0xDE05); send_data(0x00A5); + send_cmd(0xDE06); send_data(0x0002); + send_cmd(0xDE07); send_data(0x00C9); + send_cmd(0xDE08); send_data(0x0002); + send_cmd(0xDE09); send_data(0x00EA); + send_cmd(0xDE0A); send_data(0x0003); + send_cmd(0xDE0B); send_data(0x0019); + send_cmd(0xDE0C); send_data(0x0003); + send_cmd(0xDE0D); send_data(0x0045); + send_cmd(0xDE0E); send_data(0x0003); + send_cmd(0xDE0F); send_data(0x007A); + send_cmd(0xDF00); send_data(0x0003); + send_cmd(0xDF01); send_data(0x00A0); + send_cmd(0xDF02); send_data(0x0003); + send_cmd(0xDF03); send_data(0x00F4); + + /*Negae Gamma for RED*/ + send_cmd(0xE000); send_data(0x0000); + send_cmd(0xE001); send_data(0x0032); + send_cmd(0xE002); send_data(0x0000); + send_cmd(0xE003); send_data(0x0041); + send_cmd(0xE004); send_data(0x0000); + send_cmd(0xE005); send_data(0x0054); + send_cmd(0xE006); send_data(0x0000); + send_cmd(0xE007); send_data(0x0067); + send_cmd(0xE008); send_data(0x0000); + send_cmd(0xE009); send_data(0x007A); + send_cmd(0xE00A); send_data(0x0000); + send_cmd(0xE00B); send_data(0x0098); + send_cmd(0xE00C); send_data(0x0000); + send_cmd(0xE00D); send_data(0x00B0); + send_cmd(0xE00E); send_data(0x0000); + send_cmd(0xE00F); send_data(0x00DB); + send_cmd(0xE100); send_data(0x0001); + send_cmd(0xE101); send_data(0x0001); + send_cmd(0xE102); send_data(0x0001); + send_cmd(0xE103); send_data(0x003F); + send_cmd(0xE104); send_data(0x0001); + send_cmd(0xE105); send_data(0x0070); + send_cmd(0xE106); send_data(0x0001); + send_cmd(0xE107); send_data(0x00B4); + send_cmd(0xE108); send_data(0x0001); + send_cmd(0xE109); send_data(0x00EC); + send_cmd(0xE10A); send_data(0x0001); + send_cmd(0xE10B); send_data(0x00ED); + send_cmd(0xE10C); send_data(0x0002); + send_cmd(0xE10D); send_data(0x001E); + send_cmd(0xE10E); send_data(0x0002); + send_cmd(0xE10F); send_data(0x0051); + send_cmd(0xE200); send_data(0x0002); + send_cmd(0xE201); send_data(0x006C); + send_cmd(0xE202); send_data(0x0002); + send_cmd(0xE203); send_data(0x008D); + send_cmd(0xE204); send_data(0x0002); + send_cmd(0xE205); send_data(0x00A5); + send_cmd(0xE206); send_data(0x0002); + send_cmd(0xE207); send_data(0x00C9); + send_cmd(0xE208); send_data(0x0002); + send_cmd(0xE209); send_data(0x00EA); + send_cmd(0xE20A); send_data(0x0003); + send_cmd(0xE20B); send_data(0x0019); + send_cmd(0xE20C); send_data(0x0003); + send_cmd(0xE20D); send_data(0x0045); + send_cmd(0xE20E); send_data(0x0003); + send_cmd(0xE20F); send_data(0x007A); + send_cmd(0xE300); send_data(0x0003); + send_cmd(0xE301); send_data(0x00A0); + send_cmd(0xE302); send_data(0x0003); + send_cmd(0xE303); send_data(0x00F4); + + /*Negae Gamma for GERREN*/ + send_cmd(0xE400); send_data(0x0000); + send_cmd(0xE401); send_data(0x0032); + send_cmd(0xE402); send_data(0x0000); + send_cmd(0xE403); send_data(0x0041); + send_cmd(0xE404); send_data(0x0000); + send_cmd(0xE405); send_data(0x0054); + send_cmd(0xE406); send_data(0x0000); + send_cmd(0xE407); send_data(0x0067); + send_cmd(0xE408); send_data(0x0000); + send_cmd(0xE409); send_data(0x007A); + send_cmd(0xE40A); send_data(0x0000); + send_cmd(0xE40B); send_data(0x0098); + send_cmd(0xE40C); send_data(0x0000); + send_cmd(0xE40D); send_data(0x00B0); + send_cmd(0xE40E); send_data(0x0000); + send_cmd(0xE40F); send_data(0x00DB); + send_cmd(0xE500); send_data(0x0001); + send_cmd(0xE501); send_data(0x0001); + send_cmd(0xE502); send_data(0x0001); + send_cmd(0xE503); send_data(0x003F); + send_cmd(0xE504); send_data(0x0001); + send_cmd(0xE505); send_data(0x0070); + send_cmd(0xE506); send_data(0x0001); + send_cmd(0xE507); send_data(0x00B4); + send_cmd(0xE508); send_data(0x0001); + send_cmd(0xE509); send_data(0x00EC); + send_cmd(0xE50A); send_data(0x0001); + send_cmd(0xE50B); send_data(0x00ED); + send_cmd(0xE50C); send_data(0x0002); + send_cmd(0xE50D); send_data(0x001E); + send_cmd(0xE50E); send_data(0x0002); + send_cmd(0xE50F); send_data(0x0051); + send_cmd(0xE600); send_data(0x0002); + send_cmd(0xE601); send_data(0x006C); + send_cmd(0xE602); send_data(0x0002); + send_cmd(0xE603); send_data(0x008D); + send_cmd(0xE604); send_data(0x0002); + send_cmd(0xE605); send_data(0x00A5); + send_cmd(0xE606); send_data(0x0002); + send_cmd(0xE607); send_data(0x00C9); + send_cmd(0xE608); send_data(0x0002); + send_cmd(0xE609); send_data(0x00EA); + send_cmd(0xE60A); send_data(0x0003); + send_cmd(0xE60B); send_data(0x0019); + send_cmd(0xE60C); send_data(0x0003); + send_cmd(0xE60D); send_data(0x0045); + send_cmd(0xE60E); send_data(0x0003); + send_cmd(0xE60F); send_data(0x007A); + send_cmd(0xE700); send_data(0x0003); + send_cmd(0xE701); send_data(0x00A0); + send_cmd(0xE702); send_data(0x0003); + send_cmd(0xE703); send_data(0x00F4); + + /*Negae Gamma for BLUE*/ + send_cmd(0xE800); send_data(0x0000); + send_cmd(0xE801); send_data(0x0032); + send_cmd(0xE802); send_data(0x0000); + send_cmd(0xE803); send_data(0x0041); + send_cmd(0xE804); send_data(0x0000); + send_cmd(0xE805); send_data(0x0054); + send_cmd(0xE806); send_data(0x0000); + send_cmd(0xE807); send_data(0x0067); + send_cmd(0xE808); send_data(0x0000); + send_cmd(0xE809); send_data(0x007A); + send_cmd(0xE80A); send_data(0x0000); + send_cmd(0xE80B); send_data(0x0098); + send_cmd(0xE80C); send_data(0x0000); + send_cmd(0xE80D); send_data(0x00B0); + send_cmd(0xE80E); send_data(0x0000); + send_cmd(0xE80F); send_data(0x00DB); + send_cmd(0xE900); send_data(0x0001); + send_cmd(0xE901); send_data(0x0001); + send_cmd(0xE902); send_data(0x0001); + send_cmd(0xE903); send_data(0x003F); + send_cmd(0xE904); send_data(0x0001); + send_cmd(0xE905); send_data(0x0070); + send_cmd(0xE906); send_data(0x0001); + send_cmd(0xE907); send_data(0x00B4); + send_cmd(0xE908); send_data(0x0001); + send_cmd(0xE909); send_data(0x00EC); + send_cmd(0xE90A); send_data(0x0001); + send_cmd(0xE90B); send_data(0x00ED); + send_cmd(0xE90C); send_data(0x0002); + send_cmd(0xE90D); send_data(0x001E); + send_cmd(0xE90E); send_data(0x0002); + send_cmd(0xE90F); send_data(0x0051); + send_cmd(0xEA00); send_data(0x0002); + send_cmd(0xEA01); send_data(0x006C); + send_cmd(0xEA02); send_data(0x0002); + send_cmd(0xEA03); send_data(0x008D); + send_cmd(0xEA04); send_data(0x0002); + send_cmd(0xEA05); send_data(0x00A5); + send_cmd(0xEA06); send_data(0x0002); + send_cmd(0xEA07); send_data(0x00C9); + send_cmd(0xEA08); send_data(0x0002); + send_cmd(0xEA09); send_data(0x00EA); + send_cmd(0xEA0A); send_data(0x0003); + send_cmd(0xEA0B); send_data(0x0019); + send_cmd(0xEA0C); send_data(0x0003); + send_cmd(0xEA0D); send_data(0x0045); + send_cmd(0xEA0E); send_data(0x0003); + send_cmd(0xEA0F); send_data(0x007A); + send_cmd(0xEB00); send_data(0x0003); + send_cmd(0xEB01); send_data(0x00A0); + send_cmd(0xEB02); send_data(0x0003); + send_cmd(0xEB03); send_data(0x00F4); + + send_cmd(0x3A00); send_data(0x0007); + + send_cmd(0x3500); send_data(0x0000); + + send_cmd(0x1100); /* Sleep out*/ + LCD_DelayMS(120); + send_cmd(0x2900); /* Display On*/ + + send_cmd(0x2900); /* Display On*/ + return 0; +} + +static int32_t nt35516_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + return 0; + + if(is_sleep==1){ + send_cmd(0x2800); + LCD_DelayMS(200); + send_cmd(0x1000); + LCD_DelayMS(200); + /*Lcd_EnvidOnOff(0);*//*RGB TIMENG OFF*/ + /*LCD_Delay(200);*/ + }else{ + /*Lcd_EnvidOnOff(1);*//*RGB TIMENG ON*/ + /*LCD_Delay(200);*/ + /*LCDinit_TFT();*/ + /*LCD_Delay(200);*/ + } + + return 0; +} + + + + +static int32_t nt35516_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("nt35516_set_window: %d, %d, %d, %d\n",left, top, right, bottom); + + send_cmd(0x2A00); send_data((left>>8));// set left address + send_cmd(0x2A01); send_data((left&0xff)); + send_cmd(0x2A02); send_data((right>>8));// set right address + send_cmd(0x2A03); send_data((right&0xff)); + + send_cmd(0x2B00); send_data((top>>8));// set left address + send_cmd(0x2B01); send_data((top&0xff)); + send_cmd(0x2B02); send_data((bottom>>8));// set bottom address + send_cmd(0x2B03); send_data((bottom&0xff)); + + send_cmd(0x2C00); + + return 0; +} +static int32_t nt35516_invalidate(struct panel_spec *self) +{ + pr_debug("nt35516_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + + + +static int32_t nt35516_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + pr_debug("nt35516_invalidate_rect \n"); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static uint32_t nt35516_read_id(struct panel_spec *self) +{ + int32_t id = 0; + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + read_data_t read_data = self->info.mcu->ops->read_data; + send_data_t send_data = self->info.mcu->ops->send_data; + + //Get ID + send_cmd(0xF000); send_data(0x0055); /*Manufacture Command Set Control */ + send_cmd(0xF001); send_data(0x00AA); + send_cmd(0xF002); send_data(0x0052); + send_cmd(0xF003); send_data(0x0008); + send_cmd(0xF004); send_data(0x0001);/*Page1*/ + + send_cmd(0xc501); //0xc500 + id = read_data(); + + return id; +} + +static struct panel_operations lcd_nt35516_operations = { + .panel_init = nt35516_init, + .panel_set_window = nt35516_set_window, + .panel_invalidate_rect= nt35516_invalidate_rect, + .panel_invalidate = nt35516_invalidate, + .panel_enter_sleep = nt35516_enter_sleep, + .panel_readid = nt35516_read_id +}; + +static struct timing_mcu lcd_nt35516_timing[] = { +[MCU_LCD_REGISTER_TIMING] = { // read/write register timing + .rcss = 15, // 15ns + .rlpw = 60, + .rhpw = 60, + .wcss = 10, + .wlpw = 35, + .whpw = 35, + }, +[MCU_LCD_GRAM_TIMING] = { // read/write gram timing + .rcss = 15, // 15ns + .rlpw = 60, + .rhpw = 60, + .wcss = 0, + .wlpw = 16, + .whpw = 16, + }, +}; + +static struct info_mcu lcd_nt35516_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 24, + .bpp = 24, /*RGB88*/ + .timing = lcd_nt35516_timing, + .ops = NULL, +}; + +//lcd_panel_nt35516 +struct panel_spec lcd_nt35516_spec = { + .width = 540, + .height = 960, + .type = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_nt35516_info + }, + .ops = &lcd_nt35516_operations, +}; + +struct panel_cfg lcd_nt35516 = { + /* this panel may on both CS0/1 */ + .dev_id = SPRDFB_UNDEFINELCD_ID, + .lcd_id = 0x16, + .lcd_name = "lcd_nt35516", + .panel = &lcd_nt35516_spec, +}; + +static int __init lcd_nt35516_init(void) +{ + return sprdfb_panel_register(&lcd_nt35516); +} + +subsys_initcall(lcd_nt35516_init); diff --git a/drivers/video/sprdfb/lcd/lcd_nt35516_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt35516_mipi.c new file mode 100644 index 00000000..0fa94268 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35516_mipi.c @@ -0,0 +1,441 @@ +/* drivers/video/sc8825/lcd_nt35516_mipi.c
+ *
+ * Support for nt35516 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_Delay(ms) uDelay(ms*1000)
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+#if 1
+// NT35516, LGD
+// VCC=2.8V, IOVCC=1.8V
+{LCM_SEND(7), {5, 0, 0xFF,0xAA,0x55,0x25,0x01}},
+{LCM_SEND(38), {36, 0, 0xF2,0x00,0x00,0x4A,0x0A,0xA8,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x51,
+ 0x00,0x01,0x00,0x01}},
+{LCM_SEND(10), {8, 0, 0xF3,0x02,0x03,0x07,0x45,0x88,0xD1,0x0D}},
+// Manufacture Command Set for Page 0
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+{LCM_SEND(6), {4, 0, 0xB1,0x7C,0x00,0x00}}, // command/video mode
+#if (defined CONFIG_FB_SCX35) || (defined CONFIG_FB_SCX30G)
+{LCM_SEND(6), {4, 0, 0xB1,0x7C,0x06,0x00}}, // command/video mode,rotate 180^M
+#else
+ {LCM_SEND(6), {4, 0, 0xB1,0x7C,0x00,0x00}}, // command/video mode
+#endif
+{LCM_SEND(7), {5, 0, 0xB8,0x01,0x02,0x02,0x02}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0x00,0x00}}, // inversion
+{LCM_SEND(9), {7, 0, 0xC9,0x63,0x06,0x0D,0x1A,0x17,0x00}},
+// Manufacture Command Set for Page 1
+{LCM_SEND(8), {6, 0, 0xF0,0x55,0xAA,0x52,0x08,0x01}},
+{LCM_SEND(6), {4, 0, 0xB0,0x05,0x05,0x05}},
+{LCM_SEND(6), {4, 0, 0xB1,0x05,0x05,0x05}},
+{LCM_SEND(6), {4, 0, 0xB2,0x01,0x01,0x01}},
+{LCM_SEND(6), {4, 0, 0xB3,0x0D,0x0D,0x0D}},
+{LCM_SEND(6), {4, 0, 0xB4,0x09,0x09,0x09}},
+{LCM_SEND(6), {4, 0, 0xB6,0x44,0x44,0x44}},
+{LCM_SEND(6), {4, 0, 0xB7,0x34,0x34,0x34}},
+{LCM_SEND(6), {4, 0, 0xB8,0x10,0x10,0x10}},
+{LCM_SEND(6), {4, 0, 0xB9,0x36,0x36,0x36}},
+{LCM_SEND(6), {4, 0, 0xBA,0x24,0x24,0x24}},
+{LCM_SEND(6), {4, 0, 0xBC,0x00,0xD0,0x00}},
+{LCM_SEND(6), {4, 0, 0xBD,0x00,0xD0,0x00}},
+{LCM_SEND(2), {0xBE,0x5D}},
+{LCM_SEND(5), {3, 0, 0xC0,0x04,0x00}},
+{LCM_SEND(2), {0xCA,0x00}},
+// Gradient Control for Gamma Voltage
+{LCM_SEND(7), {5, 0, 0xD0,0x0A,0x10,0x0D,0x0F}},
+{LCM_SEND(19), {17, 0, 0xD1,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xD2,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xD3,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xD4,0x03,0xEF,0x03,0xFF}},
+{LCM_SEND(19), {17, 0, 0xD5,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xD6,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xD7,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xD8,0x03,0xEF,0x03,0xFF}},
+{LCM_SEND(19), {17, 0, 0xD9,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xDD,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xDE,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xDF,0x03,0xEF,0x03,0xFF}},
+{LCM_SEND(19), {17, 0, 0xE0,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xE1,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xE2,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xE3,0x03,0xEF,0x03,0xFF}},
+{LCM_SEND(19), {17, 0, 0xE4,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xE5,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xE6,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xE7,0x03,0xEF,0x03,0xFF}},
+{LCM_SEND(19), {17, 0, 0xE8,0x00,0xA7,0x01,0x0F,0x01,0x34,0x01,0x49,0x01,0x56,0x01,0x75,0x01,0x8F,0x01,0xB7}},
+{LCM_SEND(19), {17, 0, 0xE9,0x01,0xD1,0x02,0x03,0x02,0x23,0x02,0x57,0x02,0x85,0x02,0x87,0x02,0xAA,0x02,0xE1}},
+{LCM_SEND(19), {17, 0, 0xEA,0x03,0x04,0x03,0x31,0x03,0x42,0x03,0x6D,0x03,0x83,0x03,0x9C,0x03,0xAA,0x03,0xCD}},
+{LCM_SEND(7), {5, 0, 0xEB,0x03,0xEF,0x03,0xFF}},
+// User Command Set
+{LCM_SEND(2), {0x35,0x00}}, // Tearing Effect On
+{LCM_SEND(5), {3, 0, 0x44, 0x03, 0x98}}, //set te scan line to 920
+{LCM_SEND(2), {0x3A,0x77}}, // Interface Pixel Format
+{LCM_SEND(2), {0x36,0x00}}, // Memory Data Access Control
+{LCM_SEND(1), {0x22}}, // all pixel off
+{LCM_SEND(1), {0x11}}, // sleep out
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}}, // display on
+{LCM_SLEEP(100)},
+{LCM_SEND(2), {0x13,0x00}}, // normal on
+#endif
+
+#if 0
+{LCM_SEND(7), {0x5, 0, 0xFF, 0xAA, 0x55, 0x25, 0x01}},
+{LCM_SEND(7), {0x5, 0, 0xF3, 0x02, 0x03, 0x07, 0x15}},
+{LCM_SEND(8), {0x6, 0, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00}},
+//{LCM_SEND(8), {0x06, 0, 0xF0,0x55,0xAA,0x52,0x08,0x00}},
+//{LCM_SEND(8), {0x06, 0, 0xBD,0x02,0xC8,0x14,0x3C,0x01}},
+{LCM_SEND(2), {0xB1, 0xFC}},
+
+{LCM_SEND(7), {0x5, 0, 0xB8, 0x01, 0x02, 0x02, 0x02}},
+{LCM_SEND(6), {0x4, 0, 0xBC, 0x05, 0x05, 0x05}}, //Zig-Zag Inversion
+{LCM_SEND(8), {0x6, 0, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01}},
+{LCM_SEND(6), {0x4, 0, 0xB0, 0x05, 0x05, 0x05}},
+{LCM_SEND(6), {0x4, 0, 0xB1, 0x05, 0x05, 0x05}},
+{LCM_SEND(6), {0x4, 0, 0xB6, 0x34, 0x34, 0x34}},
+{LCM_SEND(6), {0x4, 0, 0xB7, 0x24, 0x24, 0x24}},
+{LCM_SEND(6), {0x4, 0, 0xB3, 0x10, 0x10, 0x10}},
+{LCM_SEND(6), {0x4, 0, 0xB9, 0x34, 0x34, 0x34}},
+{LCM_SEND(6), {0x4, 0, 0xB4, 0x0A, 0x0A, 0x0A}},
+{LCM_SEND(6), {0x4, 0, 0xBA, 0x14, 0x14, 0x14}},
+{LCM_SEND(6), {0x4, 0, 0xBC, 0x00, 0xA0, 0x00}},
+{LCM_SEND(6), {0x4, 0, 0xBD, 0x00, 0xA0, 0x00}},
+{LCM_SEND(2), {0xBE, 0x4E}},
+
+{LCM_SEND(19),{17, 0, 0xD1, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0, 0xD2, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0, 0xD3, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), { 5, 0, 0xD4, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(19),{17, 0, 0xD5, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0, 0xD6, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0, 0xD7, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), {0x7, 0, 0xD8, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(19),{17, 0, 0xD9, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0,0xDD, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0, 0xDE, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), {0x5, 0, 0xDF, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(19),{17, 0, 0xE0, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0 ,0xE1, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0,0xE2, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), {5, 0, 0xE3, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(19),{17, 0, 0xE4, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0,0xE5, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0, 0xE6, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), {5, 0, 0xE7, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(19),{17 , 0, 0xE8, 0x00, 0x32, 0x00, 0x41, 0x00, 0x54, 0x00, 0x67, 0x00, 0x7A, 0x00, 0x98, 0x00, 0xB0, 0x00, 0xDB}},
+{LCM_SEND(19),{17, 0, 0xE9, 0x01, 0x01, 0x01, 0x3F, 0x01, 0x70, 0x01, 0xB4, 0x01, 0xEC, 0x01, 0xED, 0x02, 0x1E, 0x02, 0x51}},
+{LCM_SEND(19),{17, 0, 0xEA, 0x02, 0x6C, 0x02, 0x8D, 0x02, 0xA5, 0x02, 0xC9, 0x02, 0xEA, 0x03, 0x19, 0x03, 0x45, 0x03, 0x7A}},
+{LCM_SEND(7), {0x5, 0, 0xEB, 0x03, 0xB0, 0x03, 0xF4}},
+{LCM_SEND(2), {0x3A, 0x77}},
+{LCM_SEND(2), {0x35, 0x00}},
+{LCM_SEND(2), {0x4C, 0x11}},
+
+#endif
+#if 0
+{LCM_SEND(1), {0x11}},//0x11
+{LCM_SLEEP(200),},
+{LCM_SEND(1), {0x29}},//0x29
+#endif
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+//{LCM_SEND(2), {0x4f, 0x01}}, /* this code may cause not resume bug*/
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39, {LCM_SEND(8), {0x6, 0, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t nt35516_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ pr_debug(KERN_DEBUG "nt35516_mipi_init\n");
+
+ mipi_set_cmd_mode();
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ return 0;
+}
+
+static uint32_t nt35516_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_nt35516_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0xc5, 3,(uint8_t *)read_data);
+ printk("lcd_nt35516_mipi read id 0xc5 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if((0x55 == read_data[0])&&(0x16 == read_data[1])){
+ printk("lcd_nt35516_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x16;
+ }
+ }
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t nt35516_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ printk(KERN_DEBUG "nt35516_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t nt35516_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_nt35516_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_nt35516 mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_nt35516_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ printk("lcd_nt35516 mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t nt35516_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+#ifndef FB_CHECK_ESD_IN_VFP
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+#endif
+
+ pr_debug("nt35516_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+#endif
+ power_mode = nt35516_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+#endif
+ if(power_mode == 0x9c){
+ pr_debug("nt35516_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("nt35516_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_nt35516_mipi_operations = {
+ .panel_init = nt35516_mipi_init,
+ .panel_readid = nt35516_readid,
+ .panel_enter_sleep = nt35516_enter_sleep,
+ .panel_esd_check = nt35516_check_esd,
+};
+
+static struct timing_rgb lcd_nt35516_mipi_timing = {
+ .hfp = 20, /* unit: pixel */
+ .hbp = 20,
+ .hsync = 20,//4,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_nt35516_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 3,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt35516_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt35516_mipi_spec = {
+ .width = 540,
+ .height = 960,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .info = {
+ .mipi = &lcd_nt35516_mipi_info
+ },
+ .ops = &lcd_nt35516_mipi_operations,
+};
+
+struct panel_cfg lcd_nt35516_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x16,
+ .lcd_name = "lcd_nt35516_mipi",
+ .panel = &lcd_nt35516_mipi_spec,
+};
+
+static int __init lcd_nt35516_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35516_mipi);
+}
+
+subsys_initcall(lcd_nt35516_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_i2c.c b/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_i2c.c new file mode 100644 index 00000000..cdbfd220 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_i2c.c @@ -0,0 +1,623 @@ +/* drivers/video/sc8825/lcd_nt35516_i2c.c
+ *
+ * Support for nt35516 i2c LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+#define NT35516_I2C_ADDR 0x4C
+#define NT35516_I2C_DATA_LENGHT 0x2
+#define NT35516_I2C_ACK 0x01
+//#define Set_NT35516_I2C_Send(len, data) I2C_WriteCmdArr(NT35516_I2C_ADDR, data ,len, NT35516_I2C_ACK)
+#define Set_NT35516_I2C_Send(len, data) i2c_write_burst(data ,len)
+#define LCDI2C_ID_ADDR 0xDB00
+
+#define NT35516_MAX_PARAM 4
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[NT35516_MAX_PARAM];
+}LCM_Init_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(4), {0xFF, 0x00, 0x00, 0xAA}},//AA
+ {LCM_SEND(4), {0xFF, 0x01, 0x00, 0x55}},//55
+ {LCM_SEND(4), {0xFF, 0x02, 0x00, 0x25}},//08
+ {LCM_SEND(4), {0xFF, 0x03, 0x00, 0x01}},//01
+ {LCM_SEND(4), {0xF3, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xF3, 0x03, 0x00, 0x15}},
+ {LCM_SEND(4), {0xF0, 0x00, 0x00, 0x55}}, //Manufacture Command Set Control
+ {LCM_SEND(4), {0xF0, 0x01, 0x00, 0xAA}},
+ {LCM_SEND(4), {0xF0, 0x02, 0x00, 0x52}},
+ {LCM_SEND(4), {0xF0, 0x03, 0x00, 0x08}},
+ {LCM_SEND(4), {0xF0, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xB8, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xB8, 0x01, 0x00, 0x02}},
+ {LCM_SEND(4), {0xB8, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xB8, 0x03, 0x00, 0x02}},
+ {LCM_SEND(4), {0xBC, 0x00, 0x00, 0x05}}, //Zig-Zag Inversion
+ {LCM_SEND(4), {0xBC, 0x01, 0x00, 0x05}},
+ {LCM_SEND(4), {0xBC, 0x02, 0x00, 0x05}},
+ {LCM_SEND(4), {0x4C, 0x00, 0x00, 0x11}}, //DB4=1,Enable Vivid Color,DB4=0 Disable Vivid Color
+ {LCM_SEND(4), {0xF0, 0x00, 0x00, 0x55}}, //Manufacture Command Set Control
+ {LCM_SEND(4), {0xF0, 0x01, 0x00, 0xAA}},
+ {LCM_SEND(4), {0xF0, 0x02, 0x00, 0x52}},
+ {LCM_SEND(4), {0xF0, 0x03, 0x00, 0x08}},
+ {LCM_SEND(4), {0xF0, 0x04, 0x00, 0x01}},//Page1
+ {LCM_SEND(4), {0xB0, 0x00, 0x00, 0x05}}, // Setting AVDD Voltage 6V
+ {LCM_SEND(4), {0xB0, 0x01, 0x00, 0x05}},
+ {LCM_SEND(4), {0xB0, 0x02, 0x00, 0x05}},
+ {LCM_SEND(4), {0xB6, 0x00, 0x00, 0x44}}, // Setting AVEE boosting time 2.5*vpnl
+ {LCM_SEND(4), {0xB6, 0x01, 0x00, 0x44}},
+ {LCM_SEND(4), {0xB6, 0x02, 0x00, 0x44}},
+ {LCM_SEND(4), {0xB1, 0x00, 0x00, 0x05}}, // Setting AVEE Voltage -6V
+ {LCM_SEND(4), {0xB1, 0x01, 0x00, 0x05}},
+ {LCM_SEND(4), {0xB1, 0x02, 0x00, 0x05}},
+ {LCM_SEND(4), {0xB7, 0x00, 0x00, 0x34}},
+ {LCM_SEND(4), {0xB7, 0x01, 0x00, 0x34}},
+ {LCM_SEND(4), {0xB7, 0x02, 0x00, 0x34}},
+ {LCM_SEND(4), {0xBA, 0x00, 0x00, 0x14}}, //0x24 --> 0x14
+ {LCM_SEND(4), {0xBA, 0x01, 0x00, 0x14}},
+ {LCM_SEND(4), {0xBA, 0x02, 0x00, 0x14}},
+ {LCM_SEND(4), {0xBC, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xBC, 0x01, 0x00, 0xA0}},//VGMP 0x88=4.7V 0x78=4.5V 0xA0=5.0V
+ {LCM_SEND(4), {0xBC, 0x02, 0x00, 0x00}},//VGSP
+ {LCM_SEND(4), {0xBD, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xBD, 0x01, 0x00, 0xA0}},//VGMN 0x88=-4.7V 0x78=-4.5V 0xA0=-5.0V
+ {LCM_SEND(4), {0xBD, 0x02, 0x00, 0x00}},//VGSN
+ {LCM_SEND(4), {0xBE, 0x00, 0x00, 0x57}}, // Setting VCOM Offset Voltage 0x4E¸ÄΪ0x57 20111019 LIYAN
+ {LCM_SEND(4), {0xD1, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x01, 0x00, 0x32}},
+ {LCM_SEND(4), {0xD1, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xD1, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xD1, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xD1, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xD1, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xD1, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xD1, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD1, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xD2, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xD2, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xD2, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xD2, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xD2, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD2, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xD2, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD2, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xD2, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD2, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xD3, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD3, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xD3, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD3, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xD3, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD3, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xD3, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD3, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xD3, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD3, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xD3, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD3, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xD3, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD3, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xD3, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD3, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xD4, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD4, 0x01, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xD4, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD4, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0xD5, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x01, 0x00, 0x37}},
+ {LCM_SEND(4), {0xD5, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xD5, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xD5, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xD5, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xD5, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xD5, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xD5, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD5, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xD6, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xD6, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xD6, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xD6, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xD6, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xD6, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xD6, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD6, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xD6, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD6, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xD7, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD7, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xD7, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD7, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xD7, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD7, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xD7, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD7, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xD7, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xD7, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xD7, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD7, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xD7, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD7, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xD7, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD7, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xD8, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD8, 0x01, 0x00, 0xA0}},
+ {LCM_SEND(4), {0xD8, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xD8, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0xD9, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x01, 0x00, 0x32}},
+ {LCM_SEND(4), {0xD9, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xD9, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xD9, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xD9, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xD9, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xD9, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xD9, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xD9, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xDD, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xDD, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xDD, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xDD, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xDD, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xDD, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xDD, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDD, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xDD, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDD, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xDE, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDE, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xDE, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDE, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xDE, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDE, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xDE, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDE, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xDE, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xDE, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xDE, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xDE, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xDE, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xDE, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xDE, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xDE, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xDF, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xDF, 0x01, 0x00, 0xA0}},
+ {LCM_SEND(4), {0xDF, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xDF, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0xE0, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x01, 0x00, 0x32}},
+ {LCM_SEND(4), {0xE0, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xE0, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xE0, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xE0, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xE0, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xE0, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xE0, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE0, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xE1, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xE1, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xE1, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xE1, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xE1, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE1, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xE1, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE1, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xE1, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE1, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xE2, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE2, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xE2, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE2, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xE2, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE2, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xE2, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE2, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xE2, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE2, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xE2, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE2, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xE2, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE2, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xE2, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE2, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xE3, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE3, 0x01, 0x00, 0xA0}},
+ {LCM_SEND(4), {0xE3, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE3, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0xE4, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x01, 0x00, 0x32}},
+ {LCM_SEND(4), {0xE4, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xE4, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xE4, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xE4, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xE4, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xE4, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xE4, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE4, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xE5, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xE5, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xE5, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xE5, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xE5, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE5, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xE5, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE5, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xE5, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE5, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xE6, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE6, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xE6, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE6, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xE6, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE6, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xE6, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE6, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xE6, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE6, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xE6, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE6, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xE6, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE6, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xE6, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE6, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xE7, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE7, 0x01, 0x00, 0xA0}},
+ {LCM_SEND(4), {0xE7, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xE7, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0xE8, 0x00, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x01, 0x00, 0x32}},
+ {LCM_SEND(4), {0xE8, 0x02, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x03, 0x00, 0x41}},
+ {LCM_SEND(4), {0xE8, 0x04, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x05, 0x00, 0x54}},
+ {LCM_SEND(4), {0xE8, 0x06, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x07, 0x00, 0x67}},
+ {LCM_SEND(4), {0xE8, 0x08, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x09, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xE8, 0x0A, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x0B, 0x00, 0x98}},
+ {LCM_SEND(4), {0xE8, 0x0C, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x0D, 0x00, 0xB0}},
+ {LCM_SEND(4), {0xE8, 0x0E, 0x00, 0x00}},
+ {LCM_SEND(4), {0xE8, 0x0F, 0x00, 0xDB}},
+ {LCM_SEND(4), {0xE9, 0x00, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x01, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x02, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x03, 0x00, 0x3F}},
+ {LCM_SEND(4), {0xE9, 0x04, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x05, 0x00, 0x70}},
+ {LCM_SEND(4), {0xE9, 0x06, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x07, 0x00, 0xB4}},
+ {LCM_SEND(4), {0xE9, 0x08, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x09, 0x00, 0xEC}},
+ {LCM_SEND(4), {0xE9, 0x0A, 0x00, 0x01}},
+ {LCM_SEND(4), {0xE9, 0x0B, 0x00, 0xED}},
+ {LCM_SEND(4), {0xE9, 0x0C, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE9, 0x0D, 0x00, 0x1E}},
+ {LCM_SEND(4), {0xE9, 0x0E, 0x00, 0x02}},
+ {LCM_SEND(4), {0xE9, 0x0F, 0x00, 0x51}},
+ {LCM_SEND(4), {0xEA, 0x00, 0x00, 0x02}},
+ {LCM_SEND(4), {0xEA, 0x01, 0x00, 0x6C}},
+ {LCM_SEND(4), {0xEA, 0x02, 0x00, 0x02}},
+ {LCM_SEND(4), {0xEA, 0x03, 0x00, 0x8D}},
+ {LCM_SEND(4), {0xEA, 0x04, 0x00, 0x02}},
+ {LCM_SEND(4), {0xEA, 0x05, 0x00, 0xA5}},
+ {LCM_SEND(4), {0xEA, 0x06, 0x00, 0x02}},
+ {LCM_SEND(4), {0xEA, 0x07, 0x00, 0xC9}},
+ {LCM_SEND(4), {0xEA, 0x08, 0x00, 0x02}},
+ {LCM_SEND(4), {0xEA, 0x09, 0x00, 0xEA}},
+ {LCM_SEND(4), {0xEA, 0x0A, 0x00, 0x03}},
+ {LCM_SEND(4), {0xEA, 0x0B, 0x00, 0x19}},
+ {LCM_SEND(4), {0xEA, 0x0C, 0x00, 0x03}},
+ {LCM_SEND(4), {0xEA, 0x0D, 0x00, 0x45}},
+ {LCM_SEND(4), {0xEA, 0x0E, 0x00, 0x03}},
+ {LCM_SEND(4), {0xEA, 0x0F, 0x00, 0x7A}},
+ {LCM_SEND(4), {0xEB, 0x00, 0x00, 0x03}},
+ {LCM_SEND(4), {0xEB, 0x01, 0x00, 0xA0}},
+ {LCM_SEND(4), {0xEB, 0x02, 0x00, 0x03}},
+ {LCM_SEND(4), {0xEB, 0x03, 0x00, 0xF4}},
+ {LCM_SEND(4), {0x3A, 0x00, 0x00, 0x07}},
+ {LCM_SEND(4), {0x35, 0x00, 0x00, 0x00}},
+
+ {LCM_SEND(2), {0x11, 0x00}},
+};
+
+static LCM_Init_Code disp_on = {LCM_SEND(2), {0x29, 0x00}};
+
+#if 0
+LCD_ERR_E Set_NT35516_I2C_Read(uint16 addr, uint32 addr_len, uint16* data, uint32 data_len)
+{
+ uint32 rtn=LCD_ERR_NONE;
+ uint8 cmd[2]={0x00};
+ uint8 value[4]={0x00};
+ //uint8 value=0;
+
+ cmd[0]=(uint8)((addr>>0x08)&0xff);
+ cmd[1]=(uint8)(addr&0xff);
+
+ rtn=I2C_WriteCmdArr(NT35516_I2C_ADDR, cmd, addr_len, NT35516_I2C_ACK);
+ rtn=I2C_ReadCmdArr(NT35516_I2C_ADDR, value, data_len,NT35516_I2C_ACK );
+
+ *data=(value[0]<<0x08)|value[1];
+ // *data = value;
+ return rtn;
+}
+#endif
+
+static int32_t nt35516_rgb_i2c_init(struct panel_spec *self)
+{
+ unsigned int i = 0;
+ unsigned int tag;
+ uint16_t data=0x00;
+ uint16_t data1=0x00;
+ uint16_t data2=0x00;
+ LCM_Init_Code *init = init_data;
+
+ i2c_write_8bits_t i2c_write_8bits = self->info.rgb->bus_info.i2c->ops->i2c_write_8bits;
+ i2c_read_8bits_t i2c_read_8bits = self->info.rgb->bus_info.i2c->ops->i2c_read_8bits;
+ i2c_write_16bits_t i2c_write_16bits = self->info.rgb->bus_info.i2c->ops->i2c_write_16bits;
+ i2c_read_16bits_t i2c_read_16bits = self->info.rgb->bus_info.i2c->ops->i2c_read_16bits;
+ i2c_write_burst_t i2c_write_burst = self->info.rgb->bus_info.i2c->ops->i2c_write_burst;
+
+ printk(KERN_DEBUG "nt35516_rgb_i2c_init\n");
+
+
+ // Set_NT35516_I2C_Read(LCDI2C_ID_ADDR, 2, &data, 2);
+ i2c_read_16bits(0xda00, false, &data, false);
+ i2c_read_16bits(0xdb00, false, &data1, false);
+ i2c_read_16bits(0xdc00, false, &data2, false);
+
+ for (i = 0 ; i < ARRAY_SIZE(init_data); i++ ) {
+ tag = (init->tag >> 24);
+ if (tag & LCM_TAG_SEND) {
+ Set_NT35516_I2C_Send((init->tag & LCM_TAG_MASK) , init->data);
+ printk(KERN_DEBUG "send one i2c data!\n");
+ } else if (tag & LCM_TAG_SLEEP) {
+ udelay((init->tag & LCM_TAG_MASK)*1000);
+ printk(KERN_DEBUG "delay!\n");
+ }
+ init++;
+ }
+ udelay(200);
+ // while(1)
+ // {
+ printk(KERN_DEBUG "send disp_on!\n");
+ Set_NT35516_I2C_Send((disp_on.tag & LCM_TAG_MASK) , disp_on.data);
+ // }
+
+ //I2C_ReadCmd(0xDB00,pCmd,NT35516_I2C_ACK);
+ //Set_NT35516_I2C_Read(0xdb00, 2, &data, 2);
+ printk(KERN_DEBUG "nt35516_rgb_i2c_init finish\n");
+
+ return 0;
+}
+
+static uint32_t nt35516_rgb_i2c_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ return 0x16;
+}
+
+#if 0
+void NT35516_RGB_I2C_set_display_window(
+ uint16 left, // start Horizon address
+ uint16 right, // end Horizon address
+ uint16 top, // start Vertical address
+ uint16 bottom // end Vertical address
+ )
+{
+ unsigned char data[4];
+ data[0] = 0x2A;
+ data[1] = 0x00; data[2] = (left>>8);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x01; data[2] = (left&0xff);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x02; data[2] = (right>>8);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x03; data[2] = (right&0xff);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[0] = 0x2B;
+
+ data[1] = 0x00; data[2] = (top>>8);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x01; data[2] = (top&0xff);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x02; data[2] = (bottom>>8);
+ Set_NT35516_I2C_Send(3, data);
+
+ data[1] = 0x03; data[2] = (bottom&0xff);
+ Set_NT35516_I2C_Send(3, data);
+
+}
+
+LCD_ERR_E NT35516_RGB_I2C_EnterSleep(BOOLEAN is_sleep)
+{
+ unsigned char data[4];
+ if(is_sleep==1)
+ {
+ data[0] = 0x28;data[1] = 0x00;
+ Set_NT35516_I2C_Send(2, data);
+ LCD_Delay(200);
+
+ data[0] = 0x10;data[1] = 0x00;
+ Set_NT35516_I2C_Send(2, data);
+ LCD_Delay(200);
+ //Lcd_EnvidOnOff(0);//RGB TIMENG OFF
+ //LCD_Delay(200);
+ }
+ else
+ {
+ //Lcd_EnvidOnOff(1);//RGB TIMENG ON
+ //LCD_Delay(200);
+ //LCDinit_TFT();
+ //LCD_Delay(200);
+
+ }
+
+ return 0;
+}
+
+LCD_ERR_E NT35516_RGB_I2C_SetDisplayWindow(
+ uint16 left, //left of the window
+ uint16 top, //top of the window
+ uint16 right, //right of the window
+ uint16 bottom //bottom of the window
+ )
+{
+ unsigned char data[4];
+ //NT35516_RGB_I2C_set_display_window(left, right, top, bottom);
+ data[0] = 0x2C; data[1] = 0x00;
+ Set_NT35516_I2C_Send(2, data);
+ return TRUE;
+}
+#endif
+
+
+
+static struct panel_operations lcd_nt35516_rgb_i2c_operations = {
+ .panel_init = nt35516_rgb_i2c_init,
+ .panel_readid = nt35516_rgb_i2c_readid,
+};
+
+static struct timing_rgb lcd_nt35516_rgb_timing = {
+ .hfp = 16, /* unit: pixel */
+ .hbp = 16,
+ .hsync = 1,
+ .vfp = 16, /*unit: line*/
+ .vbp = 16,
+ .vsync = 1,
+};
+
+static struct i2c_info lcd_nt35516_rgb_i2c_info = {
+ .i2c_addr = NT35516_I2C_ADDR,
+ .ops = NULL,
+};
+
+static struct info_rgb lcd_nt35516_rgb_info = {
+ .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_I2C,
+ .video_bus_width = 24, /*18,16*/
+ .h_sync_pol = SPRDFB_POLARITY_NEG, //SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_NEG, //SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .timing = &lcd_nt35516_rgb_timing,
+ .bus_info = {
+ .i2c = &lcd_nt35516_rgb_i2c_info,
+ }
+};
+
+struct panel_spec lcd_nt35516_rgb_i2c_spec = {
+ .width = 540,
+ .height = 960,
+ .type = LCD_MODE_RGB,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .rgb = &lcd_nt35516_rgb_info
+ },
+ .ops = &lcd_nt35516_rgb_i2c_operations,
+};
+
+struct panel_cfg lcd_nt35516_rgb_i2c = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x16,
+ .lcd_name = "lcd_nt35516_rgb_i2c",
+ .panel = &lcd_nt35516_rgb_i2c_spec,
+};
+
+static int __init lcd_nt35516_rgb_i2c_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35516_rgb_i2c);
+}
+
+subsys_initcall(lcd_nt35516_rgb_i2c_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_spi.c b/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_spi.c new file mode 100755 index 00000000..0ca42500 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35516_rgb_spi.c @@ -0,0 +1,624 @@ +/* drivers/video/sc8825/lcd_nt35516_spi.c
+ *
+ * Support for nt35516 spi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+#define NT35516_SpiWriteCmd(cmd) \
+{ \
+ spi_send_cmd((cmd & 0xFF));\
+}
+
+#define NT35516_SpiWriteData(data)\
+{ \
+ spi_send_data((data & 0xFF));\
+}
+
+static int32_t nt35516_rgb_spi_init(struct panel_spec *self)
+{
+ uint32_t data = 0;
+ spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd;
+ spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data;
+ spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read;
+
+ // NT35516 + AUO 4.29'
+ // VCC=IOVCC=3.3V RGB_24Bit
+
+ //NT35516_SpiWriteCmd(0xDB00);
+ //spi_read(&data);
+
+ //TEST Commands
+
+ NT35516_SpiWriteCmd(0xFF);
+ NT35516_SpiWriteData(0xAA);//AA
+ NT35516_SpiWriteData(0x55);//55
+ NT35516_SpiWriteData(0x25);//08
+ NT35516_SpiWriteData(0x01);//01
+
+ //NT35516_SpiWriteCmd(0xFA0F); NT35516_SpiWriteData(0x20);
+
+ //NT35516_SpiWriteCmd(0xF300); NT35516_SpiWriteData(0x02);
+ //NT35516_SpiWriteCmd(0xF303); NT35516_SpiWriteData(0x15);
+
+ //ENABLE PAGE 0
+ NT35516_SpiWriteCmd(0xF0);
+ NT35516_SpiWriteData(0x55); //Manufacture Command Set Control
+ NT35516_SpiWriteData(0xAA);
+ NT35516_SpiWriteData(0x52);
+ NT35516_SpiWriteData(0x08);
+ NT35516_SpiWriteData(0x00);
+
+ NT35516_SpiWriteCmd(0xB8);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x02);
+
+ //NT35516_SpiWriteCmd(0xBC00); NT35516_SpiWriteData(0x05); //Zig-Zag Inversion
+ //NT35516_SpiWriteCmd(0xBC01); NT35516_SpiWriteData(0x05);
+ //NT35516_SpiWriteCmd(0xBC02); NT35516_SpiWriteData(0x05);
+
+ //NT35516_SpiWriteCmd(0x4C00); NT35516_SpiWriteData(0x11); //DB4=1,Enable Vivid Color,DB4=0 Disable Vivid Color
+
+ // ENABLE PAGE 1
+ NT35516_SpiWriteCmd(0xF0);
+ NT35516_SpiWriteData(0x55); //Manufacture Command Set Control
+ NT35516_SpiWriteData(0xAA);
+ NT35516_SpiWriteData(0x52);
+ NT35516_SpiWriteData(0x08);
+ NT35516_SpiWriteData(0x01);//Page1
+
+ NT35516_SpiWriteCmd(0xB0);
+ NT35516_SpiWriteData(0x05); // Setting AVDD Voltage 6V
+ NT35516_SpiWriteData(0x05);
+ NT35516_SpiWriteData(0x05);
+
+ NT35516_SpiWriteCmd(0xB6);
+ NT35516_SpiWriteData(0x44); // Setting AVEE boosting time 2.5*vpnl
+ NT35516_SpiWriteData(0x44);
+ NT35516_SpiWriteData(0x44);
+
+ NT35516_SpiWriteCmd(0xB1);
+ NT35516_SpiWriteData(0x05); // Setting AVEE Voltage -6V
+ NT35516_SpiWriteData(0x05);
+ NT35516_SpiWriteData(0x05);
+
+ //Setting AVEE boosting time -2.5xVPNL
+ NT35516_SpiWriteCmd(0xB7);
+ NT35516_SpiWriteData(0x34);
+ NT35516_SpiWriteData(0x34);
+ NT35516_SpiWriteData(0x34);
+
+ //Setting VGLX boosting time AVEE-AVDD
+ NT35516_SpiWriteCmd(0xBA);
+ NT35516_SpiWriteData(0x14); //0x24 --> 0x14
+ NT35516_SpiWriteData(0x14);
+ NT35516_SpiWriteData(0x14);
+
+ //Gamma Voltage
+ NT35516_SpiWriteCmd(0xBC);
+ NT35516_SpiWriteData(0x00);
+NT35516_SpiWriteData(0xA0);//VGMP 0x88=4.7V 0x78=4.5V 0xA0=5.0V
+NT35516_SpiWriteData(0x00);//VGSP
+
+ //Gamma Voltage
+ NT35516_SpiWriteCmd(0xBD);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xA0);//VGMN 0x88=-4.7V 0x78=-4.5V 0xA0=-5.0V
+ NT35516_SpiWriteData(0x00);//VGSN
+
+ NT35516_SpiWriteCmd(0xBE);
+ NT35516_SpiWriteData(0x57); // Setting VCOM Offset Voltage 0x4E¸ÄΪ0x57 20111019 LIYAN
+
+ //GAMMA RED Positive
+ NT35516_SpiWriteCmd(0xD1);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x32);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xD2);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xD3);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xD4);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ //Positive Gamma for GREEN
+ NT35516_SpiWriteCmd(0xD5);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x37);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xD6);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xD7);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xD8);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xA0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ //Positive Gamma for BLUE
+ NT35516_SpiWriteCmd(0xD9);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x32);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xDD);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xDE);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xDF);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xA0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ //Negative Gamma for RED
+ NT35516_SpiWriteCmd(0xE0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x32);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xE1);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xE2);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xE3);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xA0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ //Negative Gamma for GERREN
+ NT35516_SpiWriteCmd(0xE4);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x32);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xE5);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xE6);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xE7);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xA0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ //Negative Gamma for BLUE
+ NT35516_SpiWriteCmd(0xE8);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x32);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x41);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x54);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x67);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x7A);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0x98);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xB0);
+ NT35516_SpiWriteData(0x00);
+ NT35516_SpiWriteData(0xDB);
+
+ NT35516_SpiWriteCmd(0xE9);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x3F);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0x70);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xB4);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xEC);
+ NT35516_SpiWriteData(0x01);
+ NT35516_SpiWriteData(0xED);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x1E);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x51);
+
+ NT35516_SpiWriteCmd(0xEA);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x6C);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0x8D);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xA5);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xC9);
+ NT35516_SpiWriteData(0x02);
+ NT35516_SpiWriteData(0xEA);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x19);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x45);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0x7A);
+
+ NT35516_SpiWriteCmd(0xEB);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xA0);
+ NT35516_SpiWriteData(0x03);
+ NT35516_SpiWriteData(0xF4);
+
+ NT35516_SpiWriteCmd(0x3A); NT35516_SpiWriteData(0x77);
+
+ NT35516_SpiWriteCmd(0x35); NT35516_SpiWriteData(0x00);
+
+ NT35516_SpiWriteCmd(0x11); // Sleep out
+ mdelay(140);
+
+ NT35516_SpiWriteCmd(0x29); // Display On
+ mdelay(10);
+}
+
+static uint32_t nt35516_rgb_spi_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ return 0x16;
+}
+
+#if 0
+void NT35516_RGB_SPI_set_display_window(
+ uint16 left, // start Horizon address
+ uint16 right, // end Horizon address
+ uint16 top, // start Vertical address
+ uint16 bottom // end Vertical address
+ )
+{
+ NT35516_SpiWriteCmd(0x2A00); NT35516_SpiWriteData((left>>8));// set left address
+ NT35516_SpiWriteCmd(0x2A01); NT35516_SpiWriteData((left&0xff));
+ NT35516_SpiWriteCmd(0x2A02); NT35516_SpiWriteData((right>>8));// set right address
+ NT35516_SpiWriteCmd(0x2A03); NT35516_SpiWriteData((right&0xff));
+
+ NT35516_SpiWriteCmd(0x2B00); NT35516_SpiWriteData((top>>8));// set left address
+ NT35516_SpiWriteCmd(0x2B01); NT35516_SpiWriteData((top&0xff));
+ NT35516_SpiWriteCmd(0x2B02); NT35516_SpiWriteData((bottom>>8));// set bottom address
+ NT35516_SpiWriteCmd(0x2B03); NT35516_SpiWriteData((bottom&0xff));
+}
+
+LCD_ERR_E NT35516_RGB_SPI_EnterSleep(BOOLEAN is_sleep)
+{
+ if(is_sleep==1)
+ {
+ NT35516_SpiWriteCmd(0x28);
+ LCD_Delay(200);
+ NT35516_SpiWriteCmd(0x10);
+ LCD_Delay(200);
+ //Lcd_EnvidOnOff(0);//RGB TIMENG OFF
+ //LCD_Delay(200);
+
+ }
+ else
+ {
+ //Lcd_EnvidOnOff(1);//RGB TIMENG ON
+ //LCD_Delay(200);
+ //LCDinit_TFT();
+ //LCD_Delay(200);
+
+ }
+
+ return 0;
+}
+
+LCD_ERR_E NT35516_RGB_SPI_SetDisplayWindow(
+ uint16 left, //left of the window
+ uint16 top, //top of the window
+ uint16 right, //right of the window
+ uint16 bottom //bottom of the window
+ )
+{
+ //NT35516_RGB_SPI_set_display_window(left, right, top, bottom);
+
+ NT35516_SpiWriteCmd(0x2C);
+ return TRUE;
+}
+#endif
+
+
+static struct panel_operations lcd_nt35516_rgb_spi_operations = {
+ .panel_init = nt35516_rgb_spi_init,
+ .panel_readid = nt35516_rgb_spi_readid,
+};
+
+static struct timing_rgb lcd_nt35516_rgb_timing = {
+ .hfp = 30, /* unit: pixel */
+ .hbp = 16,
+ .hsync = 1,
+ .vfp = 16, /*unit: line*/
+ .vbp = 16,
+ .vsync = 1,
+};
+
+static struct spi_info lcd_nt35516_rgb_spi_info = {
+ .ops = NULL,
+};
+
+static struct info_rgb lcd_nt35516_rgb_info = {
+ .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_SPI,
+ .video_bus_width = 24, /*18,16*/
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .timing = &lcd_nt35516_rgb_timing,
+ .bus_info = {
+ .spi = &lcd_nt35516_rgb_spi_info,
+ }
+};
+
+struct panel_spec lcd_nt35516_rgb_spi_spec = {
+ .width = 540,
+ .height = 960,
+ .type = LCD_MODE_RGB,
+ .direction = LCD_DIRECT_NORMAL,
+#ifdef CONFIG_FB_SCX15
+ .fps = 56,
+#endif
+ .info = {
+ .rgb = &lcd_nt35516_rgb_info
+ },
+ .ops = &lcd_nt35516_rgb_spi_operations,
+};
+
+struct panel_cfg lcd_nt35516_rgb_spi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x16,
+ .lcd_name = "lcd_nt35516_rgb_spi",
+ .panel = &lcd_nt35516_rgb_spi_spec,
+};
+static int __init lcd_nt35516_rgb_spi_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35516_rgb_spi);
+}
+
+subsys_initcall(lcd_nt35516_rgb_spi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt35596h_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt35596h_mipi.c new file mode 100644 index 00000000..ea7da76f --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt35596h_mipi.c @@ -0,0 +1,841 @@ +/* drivers/video/sprdfb/lcd_nt35516_mipi.c
+ *
+ * Support for nt35516 mipi LCD device
+ *
+ * Copyright (C) 2015 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+
+#define MAX_DATA 10
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+
+{LCM_SEND(2), {0xFF,0x05}},
+{LCM_SEND(2), {0xFB,0x01}},
+{LCM_SEND(2), {0xc5,0x01}}, //Turn On NT50198
+
+{LCM_SLEEP(25)},
+{LCM_SEND(2), {0xFF,0xEE}},
+{LCM_SEND(2), {0xFB,0x01}},
+{LCM_SEND(2), {0x1F,0x45}},
+{LCM_SEND(2), {0x24,0x4F}},
+{LCM_SEND(2), {0x38,0xC8}},
+{LCM_SEND(2), {0x39,0x2C}},
+{LCM_SEND(2), {0x1E,0xBB}},
+{LCM_SEND(2), {0x1D,0x0F}},
+{LCM_SEND(2), {0x7E,0xB1}},
+{LCM_SEND(2), {0xFF,0x00}},
+{LCM_SEND(2), {0xFB,0x01}},
+{LCM_SEND(2), {0x35,0x01}},
+{LCM_SEND(2), {0xFF,0x01}},
+{LCM_SEND(2), {0xFB,0x01}},
+{LCM_SEND(2), {0x00,0x01}},
+{LCM_SEND(2), {0x01,0x55}},
+{LCM_SEND(2), {0x02,0x40}},
+{LCM_SEND(2), {0x05,0x40}},
+{LCM_SEND(2), {0x06,0x4A}},
+{LCM_SEND(2), {0x07,0x24}},
+{LCM_SEND(2), {0x08,0x0C}},
+{LCM_SEND(2), {0x0B,0x87}},
+{LCM_SEND(2), {0x0C,0x87}},
+{LCM_SEND(2), {0x0E,0xB0}},
+{LCM_SEND(2), {0x0F,0xB3}},
+{LCM_SEND(2), {0x11,0x10}},
+{LCM_SEND(2), {0x12,0x10}},
+{LCM_SEND(2), {0x13,0x05}},
+{LCM_SEND(2), {0x14,0x4A}},
+{LCM_SEND(2), {0x15,0x18}},
+{LCM_SEND(2), {0x16,0x18}},
+{LCM_SEND(2), {0x18,0x00}},
+{LCM_SEND(2), {0x19,0x77}},
+{LCM_SEND(2), {0x1A,0x55}},
+{LCM_SEND(2), {0x1B,0x13}},
+{LCM_SEND(2), {0x1C,0x00}},
+{LCM_SEND(2), {0x1D,0x00}},
+{LCM_SEND(2), {0x1E,0x13}},
+{LCM_SEND(2), {0x1F,0x00}},
+{LCM_SEND(2), {0x23,0x00}},
+{LCM_SEND(2), {0x24,0x00}},
+{LCM_SEND(2), {0x25,0x00}},
+{LCM_SEND(2), {0x26,0x00}},
+{LCM_SEND(2), {0x27,0x00}},
+{LCM_SEND(2), {0x28,0x00}},
+{LCM_SEND(2), {0x35,0x00}},
+{LCM_SEND(2), {0x66,0x00}},
+{LCM_SEND(2), {0x58,0x82}},
+{LCM_SEND(2), {0x59,0x02}},
+{LCM_SEND(2), {0x5a,0x02}},
+{LCM_SEND(2), {0x5B,0x02}},
+{LCM_SEND(2), {0x5C,0x82}},
+{LCM_SEND(2), {0x5D,0x82}},
+{LCM_SEND(2), {0x5E,0x02}},
+{LCM_SEND(2), {0x5F,0x02}},
+{LCM_SEND(2), {0x72,0x31}},
+{LCM_SEND(2), {0xFF,0x05}},
+{LCM_SEND(2), {0xFB,0x01}},
+{LCM_SEND(2), {0x00,0x01}},
+{LCM_SEND(2), {0x01,0x0B}},
+{LCM_SEND(2), {0x02,0x0C}},
+{LCM_SEND(2), {0x03,0x09}},
+{LCM_SEND(2), {0x04,0x0a}},
+{LCM_SEND(2), {0x05,0x00}},
+{LCM_SEND(2), {0x06,0x0F}},
+{LCM_SEND(2), {0x07,0x10}},
+{LCM_SEND(2), {0x08,0x00}},
+{LCM_SEND(2), {0x09,0x00}},
+{LCM_SEND(2), {0x0A,0x00}},
+{LCM_SEND(2), {0x0B,0x00}},
+{LCM_SEND(2), {0x0C,0x00}},
+{LCM_SEND(2), {0x0d,0x13}},
+{LCM_SEND(2), {0x0e,0x15}},
+{LCM_SEND(2), {0x0f,0x17}},
+{LCM_SEND(2), {0x10,0x01}},
+{LCM_SEND(2), {0x11,0x0b}},
+{LCM_SEND(2), {0x12,0x0c}},
+{LCM_SEND(2), {0x13,0x09}},
+{LCM_SEND(2), {0x14,0x0a}},
+{LCM_SEND(2), {0x15,0x00}},
+{LCM_SEND(2), {0x16,0x0f}},
+{LCM_SEND(2), {0x17,0x10}},
+{LCM_SEND(2), {0x18,0x00}},
+{LCM_SEND(2), {0x19,0x00}},
+{LCM_SEND(2), {0x1a,0x00}},
+{LCM_SEND(2), {0x1b,0x00}},
+{LCM_SEND(2), {0x1c,0x00}},
+{LCM_SEND(2), {0x1d,0x13}},
+{LCM_SEND(2), {0x1e,0x15}},
+{LCM_SEND(2), {0x1f,0x17}},
+{LCM_SEND(2), {0x20,0x00}},
+{LCM_SEND(2), {0x21,0x03}},
+{LCM_SEND(2), {0x22,0x01}},
+{LCM_SEND(2), {0x23,0x40}},
+{LCM_SEND(2), {0x24,0x40}},
+{LCM_SEND(2), {0x25,0xed}},
+{LCM_SEND(2), {0x29,0x58}},
+{LCM_SEND(2), {0x2a,0x12}},
+{LCM_SEND(2), {0x2b,0x01}},
+{LCM_SEND(2), {0x4b,0x06}},
+{LCM_SEND(2), {0x4c,0x11}},
+{LCM_SEND(2), {0x4d,0x20}},
+{LCM_SEND(2), {0x4e,0x02}},
+{LCM_SEND(2), {0x4f,0x02}},
+{LCM_SEND(2), {0x50,0x20}},
+{LCM_SEND(2), {0x51,0x61}},
+{LCM_SEND(2), {0x52,0x01}},
+{LCM_SEND(2), {0x53,0x63}},
+{LCM_SEND(2), {0x54,0x77}},
+{LCM_SEND(2), {0x55,0xed}},
+{LCM_SEND(2), {0x5b,0x00}},
+{LCM_SEND(2), {0x5c,0x00}},
+{LCM_SEND(2), {0x5d,0x00}},
+{LCM_SEND(2), {0x5e,0x00}},
+{LCM_SEND(2), {0x5f,0x15}},
+{LCM_SEND(2), {0x60,0x75}},
+{LCM_SEND(2), {0x61,0x00}},
+{LCM_SEND(2), {0x62,0x00}},
+{LCM_SEND(2), {0x63,0x00}},
+{LCM_SEND(2), {0x64,0x00}},
+{LCM_SEND(2), {0x65,0x00}},
+{LCM_SEND(2), {0x66,0x00}},
+{LCM_SEND(2), {0x67,0x00}},
+{LCM_SEND(2), {0x68,0x04}},
+{LCM_SEND(2), {0x69,0x00}},
+{LCM_SEND(2), {0x6a,0x00}},
+{LCM_SEND(2), {0x6c,0x40}},
+{LCM_SEND(2), {0x75,0x01}},
+{LCM_SEND(2), {0x76,0x01}},
+{LCM_SEND(2), {0x7a,0x80}},
+{LCM_SEND(2), {0x7b,0xc5}},
+{LCM_SEND(2), {0x7c,0xd8}},
+{LCM_SEND(2), {0x7d,0x60}},
+{LCM_SEND(2), {0x7f,0x15}},
+{LCM_SEND(2), {0x80,0x81}},
+{LCM_SEND(2), {0x83,0x05}},
+{LCM_SEND(2), {0x93,0x08}},
+{LCM_SEND(2), {0x94,0x10}},
+{LCM_SEND(2), {0x8a,0x00}},
+{LCM_SEND(2), {0x9b,0x0f}},
+{LCM_SEND(2), {0xea,0xff}},
+{LCM_SEND(2), {0xec,0x00}},
+
+{LCM_SEND(2), {0xff,0x01}}, //GAMMA
+{LCM_SEND(2), {0xfb,0x01}},
+{LCM_SEND(2), {0x75,0x00}},
+{LCM_SEND(2), {0x76,0x18}},
+{LCM_SEND(2), {0x77,0x00}},
+{LCM_SEND(2), {0x78,0x38}},
+{LCM_SEND(2), {0x79,0x00}},
+{LCM_SEND(2), {0x7a,0x65}},
+{LCM_SEND(2), {0x7b,0x00}},
+{LCM_SEND(2), {0x7c,0x84}},
+{LCM_SEND(2), {0x7d,0x00}},
+{LCM_SEND(2), {0x7e,0x9b}},
+{LCM_SEND(2), {0x7f,0x00}},
+{LCM_SEND(2), {0x80,0xaf}},
+{LCM_SEND(2), {0x81,0x00}},
+{LCM_SEND(2), {0x82,0xc1}},
+{LCM_SEND(2), {0x83,0x00}},
+{LCM_SEND(2), {0x84,0xd2}},
+{LCM_SEND(2), {0x85,0x00}},
+{LCM_SEND(2), {0x86,0xdf}},
+{LCM_SEND(2), {0x87,0x01}},
+{LCM_SEND(2), {0x88,0x11}},
+{LCM_SEND(2), {0x89,0x01}},
+{LCM_SEND(2), {0x8a,0x38}},
+{LCM_SEND(2), {0x8b,0x01}},
+{LCM_SEND(2), {0x8c,0x76}},
+{LCM_SEND(2), {0x8d,0x01}},
+{LCM_SEND(2), {0x8e,0xa7}},
+{LCM_SEND(2), {0x8f,0x01}},
+{LCM_SEND(2), {0x90,0xf3}},
+{LCM_SEND(2), {0x91,0x02}},
+{LCM_SEND(2), {0x92,0x2f}},
+{LCM_SEND(2), {0x93,0x02}},
+{LCM_SEND(2), {0x94,0x30}},
+{LCM_SEND(2), {0x95,0x02}},
+{LCM_SEND(2), {0x96,0x66}},
+{LCM_SEND(2), {0x97,0x02}},
+{LCM_SEND(2), {0x98,0xa0}},
+{LCM_SEND(2), {0x99,0x02}},
+{LCM_SEND(2), {0x9a,0xc5}},
+{LCM_SEND(2), {0x9b,0x02}},
+{LCM_SEND(2), {0x9c,0xf8}},
+{LCM_SEND(2), {0x9d,0x03}},
+{LCM_SEND(2), {0x9e,0x1b}},
+{LCM_SEND(2), {0x9f,0x03}},
+{LCM_SEND(2), {0xa0,0x46}},
+{LCM_SEND(2), {0xa2,0x03}},
+{LCM_SEND(2), {0xa3,0x52}},
+{LCM_SEND(2), {0xa4,0x03}},
+{LCM_SEND(2), {0xa5,0x62}},
+{LCM_SEND(2), {0xa6,0x03}},
+{LCM_SEND(2), {0xa7,0x71}},
+{LCM_SEND(2), {0xa9,0x03}},
+{LCM_SEND(2), {0xaa,0x83}},
+{LCM_SEND(2), {0xab,0x03}},
+{LCM_SEND(2), {0xac,0x94}},
+{LCM_SEND(2), {0xad,0x03}},
+{LCM_SEND(2), {0xae,0xa3}},
+{LCM_SEND(2), {0xaf,0x03}},
+{LCM_SEND(2), {0xb0,0xad}},
+{LCM_SEND(2), {0xb1,0x03}},
+{LCM_SEND(2), {0xb2,0xcc}},
+{LCM_SEND(2), {0xb3,0x00}},
+{LCM_SEND(2), {0xb4,0x18}},
+{LCM_SEND(2), {0xb5,0x00}},
+{LCM_SEND(2), {0xb6,0x38}},
+{LCM_SEND(2), {0xb7,0x00}},
+{LCM_SEND(2), {0xb8,0x65}},
+{LCM_SEND(2), {0xb9,0x00}},
+{LCM_SEND(2), {0xba,0x84}},
+{LCM_SEND(2), {0xbb,0x00}},
+{LCM_SEND(2), {0xbc,0x9b}},
+{LCM_SEND(2), {0xbd,0x00}},
+{LCM_SEND(2), {0xbe,0xaf}},
+{LCM_SEND(2), {0xbf,0x00}},
+{LCM_SEND(2), {0xc0,0xc1}},
+{LCM_SEND(2), {0xc1,0x00}},
+{LCM_SEND(2), {0xc2,0xd2}},
+{LCM_SEND(2), {0xc3,0x00}},
+{LCM_SEND(2), {0xc4,0xdf}},
+{LCM_SEND(2), {0xc5,0x01}},
+{LCM_SEND(2), {0xc6,0x11}},
+{LCM_SEND(2), {0xc7,0x01}},
+{LCM_SEND(2), {0xc8,0x38}},
+{LCM_SEND(2), {0xc9,0x01}},
+{LCM_SEND(2), {0xca,0x76}},
+{LCM_SEND(2), {0xcb,0x01}},
+{LCM_SEND(2), {0xcc,0xa7}},
+{LCM_SEND(2), {0xcd,0x01}},
+{LCM_SEND(2), {0xce,0xf3}},
+{LCM_SEND(2), {0xcf,0x02}},
+{LCM_SEND(2), {0xd0,0x2f}},
+{LCM_SEND(2), {0xd1,0x02}},
+{LCM_SEND(2), {0xd2,0x30}},
+{LCM_SEND(2), {0xd3,0x02}},
+{LCM_SEND(2), {0xd4,0x66}},
+{LCM_SEND(2), {0xd5,0x02}},
+{LCM_SEND(2), {0xd6,0xa0}},
+{LCM_SEND(2), {0xd7,0x02}},
+{LCM_SEND(2), {0xd8,0xc5}},
+{LCM_SEND(2), {0xd9,0x02}},
+{LCM_SEND(2), {0xda,0xf8}},
+{LCM_SEND(2), {0xdb,0x03}},
+{LCM_SEND(2), {0xdc,0x1b}},
+{LCM_SEND(2), {0xdd,0x03}},
+{LCM_SEND(2), {0xde,0x46}},
+{LCM_SEND(2), {0xdf,0x03}},
+{LCM_SEND(2), {0xe0,0x52}},
+{LCM_SEND(2), {0xe1,0x03}},
+{LCM_SEND(2), {0xe2,0x62}},
+{LCM_SEND(2), {0xe3,0x03}},
+{LCM_SEND(2), {0xe4,0x71}},
+{LCM_SEND(2), {0xe5,0x03}},
+{LCM_SEND(2), {0xe6,0x83}},
+{LCM_SEND(2), {0xe7,0x03}},
+{LCM_SEND(2), {0xe8,0x94}},
+{LCM_SEND(2), {0xe9,0x03}},
+{LCM_SEND(2), {0xea,0xa3}},
+{LCM_SEND(2), {0xeb,0x03}},
+{LCM_SEND(2), {0xec,0xad}},
+{LCM_SEND(2), {0xed,0x03}},
+{LCM_SEND(2), {0xee,0xcc}},
+{LCM_SEND(2), {0xef,0x00}},
+{LCM_SEND(2), {0xf0,0x18}},
+{LCM_SEND(2), {0xf1,0x00}},
+{LCM_SEND(2), {0xf2,0x38}},
+{LCM_SEND(2), {0xf3,0x00}},
+{LCM_SEND(2), {0xf4,0x65}},
+{LCM_SEND(2), {0xf5,0x00}},
+{LCM_SEND(2), {0xf6,0x84}},
+{LCM_SEND(2), {0xf7,0x00}},
+{LCM_SEND(2), {0xf8,0x9b}},
+{LCM_SEND(2), {0xf9,0x00}},
+{LCM_SEND(2), {0xfa,0xaf}},
+{LCM_SEND(2), {0xff,0x02}},
+{LCM_SEND(2), {0xfb,0x01}},
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(2), {0x01,0xc1}},
+{LCM_SEND(2), {0x02,0x00}},
+{LCM_SEND(2), {0x03,0xd2}},
+{LCM_SEND(2), {0x04,0x00}},
+{LCM_SEND(2), {0x05,0xdf}},
+{LCM_SEND(2), {0x06,0x01}},
+{LCM_SEND(2), {0x07,0x11}},
+{LCM_SEND(2), {0x08,0x01}},
+{LCM_SEND(2), {0x09,0x38}},
+{LCM_SEND(2), {0x0a,0x01}},
+{LCM_SEND(2), {0x0b,0x76}},
+{LCM_SEND(2), {0x0c,0x01}},
+{LCM_SEND(2), {0x0d,0xa7}},
+{LCM_SEND(2), {0x0e,0x01}},
+{LCM_SEND(2), {0x0f,0xf3}},
+{LCM_SEND(2), {0x10,0x02}},
+{LCM_SEND(2), {0x11,0x2f}},
+{LCM_SEND(2), {0x12,0x02}},
+{LCM_SEND(2), {0x13,0x30}},
+{LCM_SEND(2), {0x14,0x02}},
+{LCM_SEND(2), {0x15,0x66}},
+{LCM_SEND(2), {0x16,0x02}},
+{LCM_SEND(2), {0x17,0xa0}},
+{LCM_SEND(2), {0x18,0x02}},
+{LCM_SEND(2), {0x19,0xc5}},
+{LCM_SEND(2), {0x1a,0x02}},
+{LCM_SEND(2), {0x1b,0xf8}},
+{LCM_SEND(2), {0x1c,0x03}},
+{LCM_SEND(2), {0x1d,0x1b}},
+{LCM_SEND(2), {0x1e,0x03}},
+{LCM_SEND(2), {0x1f,0x46}},
+{LCM_SEND(2), {0x20,0x03}},
+{LCM_SEND(2), {0x21,0x52}},
+{LCM_SEND(2), {0x22,0x03}},
+{LCM_SEND(2), {0x23,0x62}},
+{LCM_SEND(2), {0x24,0x03}},
+{LCM_SEND(2), {0x25,0x71}},
+{LCM_SEND(2), {0x26,0x03}},
+{LCM_SEND(2), {0x27,0x83}},
+{LCM_SEND(2), {0x28,0x03}},
+{LCM_SEND(2), {0x29,0x94}},
+{LCM_SEND(2), {0x2a,0x03}},
+{LCM_SEND(2), {0x2b,0xa3}},
+{LCM_SEND(2), {0x2d,0x03}},
+{LCM_SEND(2), {0x2f,0xad}},
+{LCM_SEND(2), {0x30,0x03}},
+{LCM_SEND(2), {0x31,0xcc}},
+{LCM_SEND(2), {0x32,0x00}},
+{LCM_SEND(2), {0x33,0x18}},
+{LCM_SEND(2), {0x34,0x00}},
+{LCM_SEND(2), {0x35,0x38}},
+{LCM_SEND(2), {0x36,0x00}},
+{LCM_SEND(2), {0x37,0x65}},
+{LCM_SEND(2), {0x38,0x00}},
+{LCM_SEND(2), {0x39,0x84}},
+{LCM_SEND(2), {0x3a,0x00}},
+{LCM_SEND(2), {0x3b,0x9b}},
+{LCM_SEND(2), {0x3d,0x00}},
+{LCM_SEND(2), {0x3f,0xaf}},
+{LCM_SEND(2), {0x40,0x00}},
+{LCM_SEND(2), {0x41,0xc1}},
+{LCM_SEND(2), {0x42,0x00}},
+{LCM_SEND(2), {0x43,0xd2}},
+{LCM_SEND(2), {0x44,0x00}},
+{LCM_SEND(2), {0x45,0xdf}},
+{LCM_SEND(2), {0x46,0x01}},
+{LCM_SEND(2), {0x47,0x11}},
+{LCM_SEND(2), {0x48,0x01}},
+{LCM_SEND(2), {0x49,0x38}},
+{LCM_SEND(2), {0x4a,0x01}},
+{LCM_SEND(2), {0x4b,0x76}},
+{LCM_SEND(2), {0x4c,0x01}},
+{LCM_SEND(2), {0x4d,0xa7}},
+{LCM_SEND(2), {0x4e,0x01}},
+{LCM_SEND(2), {0x4f,0xf3}},
+{LCM_SEND(2), {0x50,0x02}},
+{LCM_SEND(2), {0x51,0x2f}},
+{LCM_SEND(2), {0x52,0x02}},
+{LCM_SEND(2), {0x53,0x30}},
+{LCM_SEND(2), {0x54,0x02}},
+{LCM_SEND(2), {0x55,0x66}},
+{LCM_SEND(2), {0x56,0x02}},
+{LCM_SEND(2), {0x58,0xa0}},
+{LCM_SEND(2), {0x59,0x02}},
+{LCM_SEND(2), {0x5a,0xc5}},
+{LCM_SEND(2), {0x5b,0x02}},
+{LCM_SEND(2), {0x5c,0xf8}},
+{LCM_SEND(2), {0x5d,0x03}},
+{LCM_SEND(2), {0x5e,0x1b}},
+{LCM_SEND(2), {0x5f,0x03}},
+{LCM_SEND(2), {0x60,0x46}},
+{LCM_SEND(2), {0x61,0x03}},
+{LCM_SEND(2), {0x62,0x52}},
+{LCM_SEND(2), {0x63,0x03}},
+{LCM_SEND(2), {0x64,0x62}},
+{LCM_SEND(2), {0x65,0x03}},
+{LCM_SEND(2), {0x66,0x71}},
+{LCM_SEND(2), {0x67,0x03}},
+{LCM_SEND(2), {0x68,0x83}},
+{LCM_SEND(2), {0x69,0x03}},
+{LCM_SEND(2), {0x6a,0x94}},
+{LCM_SEND(2), {0x6b,0x03}},
+{LCM_SEND(2), {0x6c,0xa3}},
+{LCM_SEND(2), {0x6d,0x03}},
+{LCM_SEND(2), {0x6e,0xad}},
+{LCM_SEND(2), {0x6f,0x03}},
+{LCM_SEND(2), {0x70,0xcc}},
+{LCM_SEND(2), {0x71,0x00}},
+{LCM_SEND(2), {0x72,0x18}},
+{LCM_SEND(2), {0x73,0x00}},
+{LCM_SEND(2), {0x74,0x38}},
+{LCM_SEND(2), {0x75,0x00}},
+{LCM_SEND(2), {0x76,0x65}},
+{LCM_SEND(2), {0x77,0x00}},
+{LCM_SEND(2), {0x78,0x84}},
+{LCM_SEND(2), {0x79,0x00}},
+{LCM_SEND(2), {0x7a,0x9b}},
+{LCM_SEND(2), {0x7b,0x00}},
+{LCM_SEND(2), {0x7c,0xaf}},
+{LCM_SEND(2), {0x7d,0x00}},
+{LCM_SEND(2), {0x7e,0xc1}},
+{LCM_SEND(2), {0x7f,0x00}},
+{LCM_SEND(2), {0x80,0xd2}},
+{LCM_SEND(2), {0x81,0x00}},
+{LCM_SEND(2), {0x82,0xdf}},
+{LCM_SEND(2), {0x83,0x01}},
+{LCM_SEND(2), {0x84,0x11}},
+{LCM_SEND(2), {0x85,0x01}},
+{LCM_SEND(2), {0x86,0x38}},
+{LCM_SEND(2), {0x87,0x01}},
+{LCM_SEND(2), {0x88,0x76}},
+{LCM_SEND(2), {0x89,0x01}},
+{LCM_SEND(2), {0x8a,0xa7}},
+{LCM_SEND(2), {0x8b,0x01}},
+{LCM_SEND(2), {0x8c,0xf3}},
+{LCM_SEND(2), {0x8d,0x02}},
+{LCM_SEND(2), {0x8e,0x2f}},
+{LCM_SEND(2), {0x8f,0x02}},
+{LCM_SEND(2), {0x90,0x30}},
+{LCM_SEND(2), {0x91,0x02}},
+{LCM_SEND(2), {0x92,0x66}},
+{LCM_SEND(2), {0x93,0x02}},
+{LCM_SEND(2), {0x94,0xa0}},
+{LCM_SEND(2), {0x95,0x02}},
+{LCM_SEND(2), {0x96,0xc5}},
+{LCM_SEND(2), {0x97,0x02}},
+{LCM_SEND(2), {0x98,0xf8}},
+{LCM_SEND(2), {0x99,0x03}},
+{LCM_SEND(2), {0x9a,0x1b}},
+{LCM_SEND(2), {0x9b,0x03}},
+{LCM_SEND(2), {0x9c,0x46}},
+{LCM_SEND(2), {0x9d,0x03}},
+{LCM_SEND(2), {0x9e,0x52}},
+{LCM_SEND(2), {0x9f,0x03}},
+{LCM_SEND(2), {0xa0,0x62}},
+{LCM_SEND(2), {0xa2,0x03}},
+{LCM_SEND(2), {0xa3,0x71}},
+{LCM_SEND(2), {0xa4,0x03}},
+{LCM_SEND(2), {0xa5,0x83}},
+{LCM_SEND(2), {0xa6,0x03}},
+{LCM_SEND(2), {0xa7,0x94}},
+{LCM_SEND(2), {0xa9,0x03}},
+{LCM_SEND(2), {0xaa,0xa3}},
+{LCM_SEND(2), {0xab,0x03}},
+{LCM_SEND(2), {0xac,0xad}},
+{LCM_SEND(2), {0xad,0x03}},
+{LCM_SEND(2), {0xae,0xcc}},
+{LCM_SEND(2), {0xaf,0x00}},
+{LCM_SEND(2), {0xb0,0x18}},
+{LCM_SEND(2), {0xb1,0x00}},
+{LCM_SEND(2), {0xb2,0x38}},
+{LCM_SEND(2), {0xb3,0x00}},
+{LCM_SEND(2), {0xb4,0x65}},
+{LCM_SEND(2), {0xb5,0x00}},
+{LCM_SEND(2), {0xb6,0x84}},
+{LCM_SEND(2), {0xb7,0x00}},
+{LCM_SEND(2), {0xb8,0x9b}},
+{LCM_SEND(2), {0xb9,0x00}},
+{LCM_SEND(2), {0xba,0xaf}},
+{LCM_SEND(2), {0xbb,0x00}},
+{LCM_SEND(2), {0xbc,0xc1}},
+{LCM_SEND(2), {0xbd,0x00}},
+{LCM_SEND(2), {0xbe,0xd2}},
+{LCM_SEND(2), {0xbf,0x00}},
+{LCM_SEND(2), {0xc0,0xdf}},
+{LCM_SEND(2), {0xc1,0x01}},
+{LCM_SEND(2), {0xc2,0x11}},
+{LCM_SEND(2), {0xc3,0x01}},
+{LCM_SEND(2), {0xc4,0x38}},
+{LCM_SEND(2), {0xc5,0x01}},
+{LCM_SEND(2), {0xc6,0x76}},
+{LCM_SEND(2), {0xc7,0x01}},
+{LCM_SEND(2), {0xc8,0xa7}},
+{LCM_SEND(2), {0xc9,0x01}},
+{LCM_SEND(2), {0xca,0xf3}},
+{LCM_SEND(2), {0xcb,0x02}},
+{LCM_SEND(2), {0xcc,0x2f}},
+{LCM_SEND(2), {0xcd,0x02}},
+{LCM_SEND(2), {0xce,0x30}},
+{LCM_SEND(2), {0xcf,0x02}},
+{LCM_SEND(2), {0xd0,0x66}},
+{LCM_SEND(2), {0xd1,0x02}},
+{LCM_SEND(2), {0xd2,0xa0}},
+{LCM_SEND(2), {0xd3,0x02}},
+{LCM_SEND(2), {0xd4,0xc5}},
+{LCM_SEND(2), {0xd6,0xf8}},
+{LCM_SEND(2), {0xd7,0x03}},
+{LCM_SEND(2), {0xd8,0x1b}},
+{LCM_SEND(2), {0xd9,0x03}},
+{LCM_SEND(2), {0xda,0x46}},
+{LCM_SEND(2), {0xdb,0x03}},
+{LCM_SEND(2), {0xdc,0x52}},
+{LCM_SEND(2), {0xdd,0x03}},
+{LCM_SEND(2), {0xde,0x62}},
+{LCM_SEND(2), {0xdf,0x03}},
+{LCM_SEND(2), {0xe0,0x71}},
+{LCM_SEND(2), {0xe1,0x03}},
+{LCM_SEND(2), {0xe2,0x83}},
+{LCM_SEND(2), {0xe3,0x03}},
+{LCM_SEND(2), {0xe4,0x94}},
+{LCM_SEND(2), {0xe5,0x03}},
+{LCM_SEND(2), {0xe6,0xa3}},
+{LCM_SEND(2), {0xe7,0x03}},
+{LCM_SEND(2), {0xe8,0xad}},
+{LCM_SEND(2), {0xe9,0x03}},
+{LCM_SEND(2), {0xea,0xcc}}, //GAMMA END
+
+{LCM_SEND(2), {0xff,0x01}},
+{LCM_SEND(2), {0xfb,0x01}},
+{LCM_SEND(2), {0xff,0x02}},
+{LCM_SEND(2), {0xfb,0x01}},
+{LCM_SEND(2), {0xff,0x04}},
+{LCM_SEND(2), {0xfb,0x01}},
+{LCM_SEND(2), {0xff,0x00}},
+{LCM_SEND(2), {0xD3,0x05}}, //VBP VFP VSPW
+{LCM_SEND(2), {0xD4,0x04}},
+
+{LCM_SEND(1), {0x11}}, //sleep out
+{LCM_SLEEP(150)},
+
+{LCM_SEND(2), {0xff,0x00}}, //Tearing Effect Line ON
+{LCM_SEND(2), {0x35,0x00}},
+
+{LCM_SEND(1), {0x29}}, //display on
+{LCM_SLEEP(100)},
+
+{LCM_SEND(2), {0x51,0x00}}, //CABC setting
+{LCM_SEND(2), {0x5e,0x00}},
+{LCM_SEND(2), {0x53,0x2c}},
+{LCM_SEND(2), {0x55,0x00}},
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+//{LCM_SEND(2), {0x4f, 0x01}}, /* this code may cause not resume bug*/
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+// {0x39, {LCM_SEND(8), {0x6, 0, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t nt35596h_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ pr_debug(KERN_DEBUG "sprdfb:nt35596h_mipi_init\n");
+
+ mipi_set_cmd_mode();
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ return 0;
+}
+
+static uint32_t nt35596h_readid(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("sprdfb:lcd_nt35596h_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0xF4, 1,(uint8_t *)read_data);
+ printk("lcd_nt35596h_mipi read id 0xF4 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if(0x96 == read_data[0]){
+ printk("lcd_nt35596h_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x96;
+ }
+ }
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t nt35596h_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ printk(KERN_DEBUG "nt35596h_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t nt35596h_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_nt35596h_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_nt35516 mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if(0x08 == read_data[0]){
+ pr_debug("lcd_nt35596h_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ printk("lcd_nt35596h mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t nt35596h_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+#ifndef FB_CHECK_ESD_IN_VFP
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+#endif
+
+ pr_debug("nt35596h_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+#endif
+ power_mode = nt35596h_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+#endif
+ if(power_mode == 0x9c){
+ pr_debug("nt35596h_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("nt35596h_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_nt35596h_mipi_operations = {
+ .panel_init = nt35596h_mipi_init,
+ .panel_readid = nt35596h_readid,
+ .panel_enter_sleep = nt35596h_enter_sleep,
+ .panel_esd_check = nt35596h_check_esd,
+};
+
+static struct timing_rgb lcd_nt35596h_mipi_timing = {
+ .hfp = 20, /* unit: pixel */
+ .hbp = 20,
+ .hsync = 20,//4,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_nt35596h_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 4,
+ .phy_feq = 1000*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt35596h_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt35596h_mipi_spec = {
+ .width = 1080,
+ .height = 1920,
+ .fps = 40,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .info = {
+ .mipi = &lcd_nt35596h_mipi_info
+ },
+ .ops = &lcd_nt35596h_mipi_operations,
+};
+
+struct panel_cfg lcd_nt35596h_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x96,
+ .lcd_name = "lcd_nt35596h_mipi",
+ .panel = &lcd_nt35596h_mipi_spec,
+};
+
+static int __init lcd_nt35596h_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_nt35596h_mipi);
+}
+
+subsys_initcall(lcd_nt35596h_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt51017_goyal_mipi.c b/drivers/video/sprdfb/lcd/lcd_nt51017_goyal_mipi.c new file mode 100755 index 00000000..1f081bee --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt51017_goyal_mipi.c @@ -0,0 +1,296 @@ +/* drivers/video/sprdfb/lcd_nt51017_mipi.c
+ *
+ * Support for nt51017 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+#include <mach/gpio.h>
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 150
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+
+
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(2), {0x83, 0x96} },
+ {LCM_SEND(2), {0x84, 0x69} },
+ {LCM_SEND(2), {0x92, 0x19} },
+ {LCM_SEND(2), {0x83, 0x00} },
+ {LCM_SEND(2), {0x84, 0x00} },
+ {LCM_SEND(2), {0x96, 0x00} },
+
+};
+
+
+static LCM_Init_Code sleep_in[] = {
+
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(170)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(170)},
+
+};
+
+
+static int32_t nt51017_mipi_init(struct panel_spec *self)
+{
+
+ if (gpio_request(232, "LED_EN0")) {
+ printk("Failed ro request LCD_BL GPIO_%d \n",232);
+ return -ENODEV;
+ }
+ gpio_direction_output(232, 1);
+ gpio_set_value(232, 1);
+
+ if (gpio_request(233, "LED_EN1")) {
+ printk("Failed ro request LCD_BL GPIO_%d \n",233);
+ return -ENODEV;
+ }
+ gpio_direction_output(233, 1);
+ gpio_set_value(233, 1);
+
+ mdelay(200);
+
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_nt51017_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ mdelay(init->tag & LCM_TAG_MASK);//udelay((init->tag & LCM_TAG_MASK) * 1000);
+ }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t nt51017_readid(struct panel_spec *self)
+{
+#if 0
+ uint32 j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_nt51017_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x01;
+ param[1] = 0x00;
+ mipi_force_write(0x37, param, 2);
+ read_rtn = mipi_force_read(0xda,1,&read_data[0]);
+ printk("lcd_nt51017_mipi read id 0xda value is 0x%x!\n",read_data[0]);
+
+ read_rtn = mipi_force_read(0xdb,1,&read_data[1]);
+ printk("lcd_nt51017_mipi read id 0xdb value is 0x%x!\n",read_data[1]);
+
+ read_rtn = mipi_force_read(0xdc,1,&read_data[2]);
+ printk("lcd_nt51017_mipi read id 0xdc value is 0x%x!\n",read_data[2]);
+
+ if((0x55 == read_data[0])&&(0xbf == read_data[1] || 0xc0 == read_data[1] || 0xbe == read_data[1])&&(0x90 == read_data[2])){
+ printk("lcd_nt51017_mipi read id success!\n");
+ return 0x8369;
+ }
+ }
+
+ mipi_eotp_set(0,0);
+
+ printk("lcd_s6d77a1_mipi read id failed!\n");
+ return 0;
+#endif
+ return 0x51017;
+}
+
+static int32_t nt51017_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel nt51017_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(sleep_in_out->tag & LCM_TAG_MASK);
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static int32_t nt51017_before_resume(struct panel_spec *self, uint8_t is_sleep)
+{
+ gpio_set_value(152, 1);
+ gpio_set_value(155, 1);
+ gpio_set_value(232, 1);
+ gpio_set_value(233, 1);
+}
+
+static int32_t nt51017_after_suspend(struct panel_spec *self, uint8_t is_sleep)
+{
+ gpio_set_value(152, 0);
+ gpio_set_value(155, 0);
+ gpio_set_value(232, 0);
+ gpio_set_value(233, 0);
+}
+
+static struct panel_operations lcd_nt51017_mipi_operations = {
+ .panel_init = nt51017_mipi_init,
+ .panel_readid = nt51017_readid,
+ .panel_enter_sleep = nt51017_enter_sleep,
+ .panel_before_resume = nt51017_before_resume,
+ .panel_after_suspend = nt51017_after_suspend,
+};
+
+static struct timing_rgb lcd_nt51017_mipi_timing = {
+
+ .hfp = 80, /* unit: pixel */
+ .hbp = 80,
+ .hsync = 1,
+ .vfp = 18, /*unit: line*/
+ .vbp = 23,
+ .vsync = 1,
+
+};
+
+
+static struct info_mipi lcd_nt51017_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 4,
+ .phy_feq =481*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_nt51017_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_nt51017_mipi_spec = {
+ .width = 800,
+ .height =1280,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .suspend_mode = SEND_SLEEP_CMD,
+ .info = {
+ .mipi = &lcd_nt51017_mipi_info
+ },
+ .ops = &lcd_nt51017_mipi_operations,
+};
+struct panel_cfg lcd_nt51017_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x51017,
+ .lcd_name = "lcd_nt51017_mipi",
+ .panel = &lcd_nt51017_mipi_spec,
+};
+
+
+static int __init lcd_nt51017_mipi_init(void)
+{
+ if (gpio_request(152, "LCD_3V3")) {
+ printk("Failed ro request LCD_3V3 GPIO_%d \n",152);
+ return -ENODEV;
+ }
+ if (gpio_request(155, "BL_EN")) {
+ printk("Failed ro request BL_EN GPIO_%d \n",155);
+ return -ENODEV;
+ }
+ if (gpio_request(232, "CABC_EN0")) {
+ printk("Failed ro request CABC_EN0 GPIO_%d \n",232);
+ return -ENODEV;
+ }
+ if (gpio_request(233, "CABC_EN1")) {
+ printk("Failed ro request CABC_EN1 GPIO_%d \n",233);
+ return -ENODEV;
+ }
+ gpio_direction_output(152, 1);
+ gpio_direction_output(155, 1);
+ gpio_direction_output(232, 1);
+ gpio_direction_output(233, 1);
+
+ return sprdfb_panel_register(&lcd_nt51017_mipi);
+}
+
+subsys_initcall(lcd_nt51017_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_nt51017_mipi_lvds.c b/drivers/video/sprdfb/lcd/lcd_nt51017_mipi_lvds.c new file mode 100644 index 00000000..e5689072 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_nt51017_mipi_lvds.c @@ -0,0 +1,589 @@ +/* drivers/video/sprdfb/lcd_nt51017_mipi_lvds.c + * + * Support for nt51017 lvds LCD device + * + * Copyright (C) 2013 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +//#include <asm/arch/sprd_lcd.h> +//#include <asm/arch/sprd_i2c.h> +#include <linux/kernel.h> +//#include <linux/bug.h> +#include <linux/delay.h> +//#include <linux/platform_device.h> +#include <linux/i2c.h> +//#include <include/asm/gpio.h> +//#include "sp8830_i2c.h" +#include "../sprdfb_panel.h" + +//#define printk printf + +//#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +/***************** Important Macro! *****************/ +/* For TI! ONLY ONE of the flowing marco can be defined! */ +//#define LINES_ALL_RIGHT_TI +#define LINES_ONLY_CLK_RIGHT_TI + +/* For CHIPONE! ONLY ONE of the flowing marco can be defined! */ +#if 1 +#define LINES_ALL_WRONG_C1 +#else // 5735A-2 v1.0.1 +#define LINES_ALL_RIGHT_C1 +#endif +/***************** Important Macro! *****************/ + +struct bridge_ops { + int32_t (*init)(struct panel_spec *self); + int32_t (*suspend)(struct panel_spec *self); +}; + +static struct bridge_ops b_ops = { + .init = NULL, + .suspend = NULL, +}; + + +#define I2CID_BRIDGE 2 +#define I2C_NT50366_ADDR_WRITE 0x9E /* NT50169 100_1111 0 */ +#define I2C_NT51017_ADDR_WRITE 0xD0 /* NT51017 110_1000 0 */ +#define I2C_BRIDGE_ADDR_WRITE0 0x2C /* 0 010_1100 ADDR=Low */ +#define I2C_BRIDGE_ADDR_WRITE1 0x2D /* 0 010_1101 ADDR=High */ +#define I2C_BRIDGE_ADDR I2C_BRIDGE_ADDR_WRITE0 + + +#define GPIOID_LCMRSTN 103 /* should modify pinmap */ +#define GPIOID_STBYB 230 /* should modify pinmap */ +#define GPIOID_BRIDGE_EN 231 +#define GPIOID_VDDPWR 232 +#define GPIOID_ADDR 234 /* should modify pinmap */ +#define GPIOID_LCDPWR 235 + +#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +extern int gpio_direction_output(unsigned gpio, int value); +extern int gpio_request(unsigned gpio, const char *label); +extern void gpio_free(unsigned gpio); + +const static __u8 i2c_msg_buf_ti[][2] = { + {0x09, 0x00}, + {0x0A, 0x03}, + {0x0B, 0x18}, + {0x0D, 0x00}, + {0x10, 0x26}, + {0x11, 0x00}, + {0x12, 0x31}, + {0x13, 0x00}, +#ifdef LINES_ALL_RIGHT_TI + {0x18, 0x18},/* all the line is right */ +#elif defined LINES_ONLY_CLK_RIGHT_TI + {0x18, 0xF8},/* only clock line is right */ +#endif + {0x19, 0x0C},/* 0x00 */ + {0x1A, 0x03}, + {0x1B, 0x00}, + {0x20, 0x00}, + {0x21, 0x03}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x20}, + {0x29, 0x00}, + {0x2A, 0x00}, + {0x2B, 0x00}, + {0x2C, 0x04},/*0x04*/ + {0x2D, 0x00}, + {0x2E, 0x00}, + {0x2F, 0x00}, + {0x30, 0x04},/*0x04*/ + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x4C}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3A, 0x00}, + {0x3B, 0x00}, + {0x3C, 0x00}, + {0x3D, 0x00}, + {0x3E, 0x00}, +}; +const static __u8 i2c_msg_buf_c1[][2] = { + /*{0x10, 0x4E},add*/ + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x43}, + {0x23, 0x28}, + {0x24, 0x04}, + {0x25, 0x4C}, + {0x26, 0x00}, + {0x27, 0x12}, + {0x28, 0x04},/*0x02*/ + {0x29, 0x13}, + {0x2A, 0x01}, + {0x34, 0xF0},/*add*/ + {0x36, 0x50},/*add*/ + {0x86, 0x2B}, + {0xB5, 0xA0}, + {0x51, 0x20}, + {0x56, 0x92}, + {0x69, 0x1C},/*0x1F*/ + {0x6B, 0x22}, + {0x5C, 0xFF}, + {0xB6, 0x20}, +#ifdef LINES_ALL_RIGHT_C1 + {0x13, 0x10}, +#elif defined LINES_ONLY_CLK_RIGHT_C1 + {0x13, 0x1F}, +#elif defined LINES_ALL_WRONG_C1 + {0x13, 0x5F}, +#endif + /*{0x10, 0x47},add*/ + /*{0x2A, 0x31},modify*/ + /*{0x2E, 0x40},add*/ + /*{0x2F, 0x40},add*/ + {0x09, 0x10}, + /*{0x7B, 0xF2},*/ + /*{0x7C, 0xF3},*/ +}; + +static struct i2c_msg msg_w = { + .addr = I2C_BRIDGE_ADDR, + .flags = 0, + .len = 2, + .buf = NULL, +}; + +static struct i2c_msg msg_r[] = { + [0] = { + .addr = I2C_BRIDGE_ADDR, + .flags = 0, + .len = 1, + .buf = NULL, + }, + [1] = { + .addr = I2C_BRIDGE_ADDR, + .flags = I2C_M_RD, + .len = 1, + .buf = NULL, + }, +}; + +static int32_t sn65dsi83_reg_read(struct panel_spec *self) +{ + __u8 reg[] = {0x09,0x0A,0x0B,0x0D,0x10,0x11,0x12,0x13,0x18,0x19,0x1A,0x1B,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E}; + __u8 val[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int32_t ret_i2c = 0; + int32_t i = 0; + struct i2c_adapter *adap = i2c_get_adapter(I2CID_BRIDGE); + + for (i=0; i<ARRAY_SIZE(reg); i++){ + msg_r[0].buf = ®[i]; + msg_r[1].buf = &val[i]; + ret_i2c = i2c_transfer(adap, &msg_r, 2); + LCD_PRINT("kernel Read All Regs! SendMsgNum=%d, Reg=0x%x, Src=0x%x,Read=0x%x,\n", ret_i2c,reg[i],i2c_msg_buf_ti[2*i+1],val[i]); + } + + LCD_PRINT("kernel sn65dsi83_reg_read! adap_addr=0x%x, name=%s, nr=%d\n", adap, adap->name, adap->nr); + + return 0; +} + +/* set pin, return 0:OK, other value:failed */ +static int32_t set_en_pin(struct panel_spec *self, uint8_t value, uint8_t delays)//value 0 : set low, value not 0 : set high +{ + static uint8_t gpio_is_requested = 0; + + /* request gpio */ + if (!gpio_is_requested){ + if (gpio_request(GPIOID_BRIDGE_EN, "BRIDGE_EN")){ + printk("kernel GPIO%d requeste failed!\n",GPIOID_BRIDGE_EN); + return 1; + } + gpio_is_requested = 1; + } + + if (value) {//set high + gpio_direction_output(GPIOID_BRIDGE_EN, 0); + msleep(delays); + gpio_direction_output(GPIOID_BRIDGE_EN, 1); + } else {//set low + gpio_direction_output(GPIOID_BRIDGE_EN, 0); + gpio_free(GPIOID_BRIDGE_EN); + gpio_is_requested = 0; + } + + return 0; +} + +/* Init SN65DSI83 */ +static int32_t sn65dsi83_init(struct panel_spec *self) +{ + int32_t i = 0; + int32_t ret_i2c = 0; + + __u8 i2c_msg_buf_pll_en[] = {0x0D, i2c_msg_buf_ti[3][1]|0x01};// PLL_EN (CSR 0x0D.0) + __u8 i2c_msg_buf_soft_reset[] = {0x09, i2c_msg_buf_ti[0][1]|0x01};// SOFT_RESET (CSR 0x09.0) + + struct i2c_adapter *adap = i2c_get_adapter(I2CID_BRIDGE); + + mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;/* u-boot\arch\arm\include\asm\arch\sprd_lcd.h */ + mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode; + mipi_set_video_mode_t mipi_set_video_mode = self->info.mipi->ops->mipi_set_video_mode; + + /* step 1 : All DSI into LP11*/ + mipi_set_lp_mode(); + + /* step 2 : Set EN*/ + if (set_en_pin(self, 1, 30)){ + printk("kernel Set EN failed!\n"); + return 0; + } + + /* step 3 : Delay*/ + udelay(2000); + + /* step 4 : init CSR reg*/ + for (i=0; i<ARRAY_SIZE(i2c_msg_buf_ti); i++) { + msg_w.buf = i2c_msg_buf_ti[i]; + ret_i2c = i2c_transfer(adap, &msg_w, 1); + } + + /* step 5 : Start the DSI video stream */ + mipi_set_hs_mode(); + mipi_set_video_mode(); + udelay(1000); + + /* step 6 : Set the PLL_EN bit(CSR 0x0D.0) */ + msg_w.buf = i2c_msg_buf_pll_en; + ret_i2c = i2c_transfer(adap, &msg_w, 1); + + /* step 7 : Wait for the PLL_LOCK bit to be set(CSR 0x0A.7) */ + udelay(1000); + + /* step 8 : Set the SOFT_RESET bit (CSR 0x09.0) */ + msg_w.buf = i2c_msg_buf_soft_reset; + ret_i2c = i2c_transfer(adap, &msg_w, 1); + + return 0; +} + +static int32_t chipone_init(struct panel_spec *self) +{ + int32_t ret_i2c = 0; + int32_t i = 0; + + struct i2c_adapter *adap = i2c_get_adapter(I2CID_BRIDGE); + + /* Set EN pin */ + if (set_en_pin(self, 1, 10)){ + printk("kernel Set EN failed!\n"); + return 0; + } + udelay(1000); + + /* init chipone */ + for (i=0; i<ARRAY_SIZE(i2c_msg_buf_c1); i++) { + msg_w.buf = i2c_msg_buf_c1[i]; + ret_i2c = i2c_transfer(adap, &msg_w, 1); + } + + return 0; +} + +/* reset sn65dsi83 */ +static int32_t sn65dsi83_suspend(struct panel_spec *self) +{ + __u8 i2c_msg_buf_pll_en[] = {0x0D, i2c_msg_buf_ti[3][1] & 0xFE};// PLL_EN (CSR 0x0D.0) + int32_t ret_i2c = 0; + + struct i2c_adapter *adap = i2c_get_adapter(I2CID_BRIDGE); + + LCD_PRINT("kernel sn65dsi83_suspend! adap_addr=0x%x, name=%s, nr=%d\n", adap, adap->name, adap->nr); + + /*1. Clear the PLL_EN bit to 0(CSR 0x0D.0*/ + msg_w.buf = i2c_msg_buf_pll_en; + ret_i2c = i2c_transfer(adap, &msg_w, 1); + + /* set EN to 0 */ + if (set_en_pin(self, 0, 1)){ + printk("kernel Set EN failed!\n"); + return 0; + } + + return 0; +} + +static int32_t chipone_suspend(struct panel_spec *self) +{ + /* set EN to 0 */ + if (set_en_pin(self, 0, 1)){ + printk("kernel Set EN failed!\n"); + return 0; + } + return 0; +} + +static int32_t nt51017_power(struct panel_spec *self, uint8_t power)//0:power down, 1:power up +{ + static uint8_t is_requested = 0; + + if(!is_requested){//should request gpio + if (gpio_request(GPIOID_VDDPWR, "VDDPWR")){ + printk("kernel GPIO%d requeste failed!\n", GPIOID_VDDPWR); + return 0; + } + + if (gpio_request(GPIOID_LCDPWR, "LCDPWR")){ + printk("kernel GPIO%d requeste failed!\n", GPIOID_LCDPWR); + return 0; + } + + is_requested = 1; + } + + if (is_requested){ + gpio_direction_output(GPIOID_VDDPWR, power); + gpio_direction_output(GPIOID_LCDPWR, power); + + if (!power){//power down, should free gpio + gpio_free(GPIOID_VDDPWR); + gpio_free(GPIOID_LCDPWR); + is_requested = 0; + } + } + + return 0; +} + +static int32_t get_bridge_info(struct panel_spec *self) +{ + __u8 reg = 0x00; + __u8 flag = 0xFF; + int32_t ret_i2c = 0; + + struct i2c_adapter *adap = i2c_get_adapter(I2CID_BRIDGE); + + if (set_en_pin(self, 1, 30)){ + printk("kernel Set EN failed!\n"); + return 1; + } + + if (gpio_request(GPIOID_ADDR, "ADDR")){ + printk("kernel GPIO%d requeste failed!\n", GPIOID_ADDR); + return 1; + } + gpio_direction_output(GPIOID_ADDR, 0);// drive ADDR to low + udelay(1000); + + msg_r[0].buf = ® + msg_r[1].buf = &flag; + ret_i2c = i2c_transfer(adap, &msg_r, 2); + if (0 == ret_i2c){ + printk("get_bridge_info, I2C Read Failed!\n"); + return 1; + } + + if (0x35 == flag){//TI + b_ops.init = sn65dsi83_init; + b_ops.suspend = sn65dsi83_suspend; + } else if (0xC1 == flag) {//ChipOne + b_ops.init = chipone_init; + b_ops.suspend = chipone_suspend; + } else { + printk("get_bridge_info, Unknown bridge! flag=0x%x\n", flag); + gpio_free(GPIOID_ADDR); + return 1; + } + + return 0; +} + +static int32_t nt51017_mipi_lvds_init(struct panel_spec *self) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_init\n"); + + /* init */ + if (b_ops.init) { + b_ops.init(self); + } else { + if (get_bridge_info(self)){//get bridge info fail + printk("Get bridge info fail!\n"); + return 0; + } else { + b_ops.init(self); + } + } + + /* power up */ + nt51017_power(self, 1); + + LCD_PRINT("kernel nt51017_mipi_lvds_init over!\n"); + + return 0; +} + +static int32_t nt51017_mipi_lvds_reset(struct panel_spec *self) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_reset\n"); + + return 0; +} + +static int32_t nt51017_mipi_lvds_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_enter_sleep! is_sleep=%d\n",is_sleep); + + if (is_sleep){//sleep in + nt51017_power(self, 0);// power down + if (b_ops.suspend) { + b_ops.suspend(self); + } else { + if (get_bridge_info(self)){ + printk("Get bridge info fail when suspend!\n"); + return 0; + } else { + b_ops.suspend(self); + } + } + } else {//sleep out + nt51017_power(self, 1);// power up + if (b_ops.init) { + b_ops.init(self); + } else { + if (get_bridge_info(self)){//get bridge info fail + printk("Get bridge info fail!\n"); + return 0; + } else { + b_ops.init(self); + } + } + } + + return 0; +} + +static uint32_t nt51017_mipi_lvds_after_suspend(struct panel_spec *self) +{ + nt51017_power(self, 0);// power down + + if (b_ops.suspend) { + b_ops.suspend(self); + }else { + if (get_bridge_info(self)){ + printk("Get bridge info fail when suspend!\n"); + return 0; + } else { + b_ops.suspend(self); + } + } + + LCD_PRINT("kernel nt51017_mipi_lvds_after_suspend\n"); + + return 0; +} + +static uint32_t nt51017_mipi_lvds_before_resume(struct panel_spec *self) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_before_resume\n"); + + return 0; +} + +static uint32_t nt51017_mipi_lvds_readid(struct panel_spec *self) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_readid\n"); + + return 0xC749;/*51017*/ +} + +static int32_t nt51017_mipi_lvds_check_esd(struct panel_spec *self) +{ + LCD_PRINT("kernel nt51017_mipi_lvds_check_esd\n"); + + return 1; +} + +static struct panel_operations lcd_nt51017_mipi_lvds_operations = { + .panel_init = nt51017_mipi_lvds_init, + .panel_reset = NULL,//nt51017_mipi_lvds_reset, + .panel_enter_sleep = nt51017_mipi_lvds_enter_sleep, + .panel_after_suspend = nt51017_mipi_lvds_after_suspend, + .panel_before_resume = NULL, + .panel_readid = nt51017_mipi_lvds_readid, + .panel_esd_check = NULL, +}; + +static struct timing_rgb lcd_nt51017_mipi_lvds_timing = { + .hfp = 110, /* unit: pixel */ + .hbp = 76, + .hsync = 4,//4 + .vfp = 18, /*unit: line*/ + .vbp = 19, + .vsync = 4, +}; + +static struct info_mipi lcd_nt51017_mipi_lvds_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 4, + .phy_feq = 512*1000,/*494*/ + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_nt51017_mipi_lvds_timing, + .ops = NULL, +}; + +struct panel_spec lcd_nt51017_mipi_lvds_spec = { + //.cap = PANEL_CAP_NOT_TEAR_SYNC, + .width = 768, + .height = 1024, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true,//bug 273509 + .info = { + .mipi = &lcd_nt51017_mipi_lvds_info + }, + .ops = &lcd_nt51017_mipi_lvds_operations, +}; + +struct panel_cfg lcd_nt51017_mipi_lvds = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0xC749, + .lcd_name = "lcd_nt51017_mipi_lvds", + .panel = &lcd_nt51017_mipi_lvds_spec, +}; + +static int __init lcd_nt51017_mipi_lvds_init(void) +{ + return sprdfb_panel_register(&lcd_nt51017_mipi_lvds); +} + +subsys_initcall(lcd_nt51017_mipi_lvds_init); + + diff --git a/drivers/video/sprdfb/lcd/lcd_otm1283a_mipi.c b/drivers/video/sprdfb/lcd/lcd_otm1283a_mipi.c new file mode 100644 index 00000000..06875681 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_otm1283a_mipi.c @@ -0,0 +1,560 @@ +/* drivers/video/sprdfb/lcd_otm1283a_mipi.c
+ *
+ * Support for otm1283a mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+//#define printk printf
+
+#define LCD_DEBUG
+//#define THREE_LANE_SUPPORT
+
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x37, {LCM_SEND(2), {0x5, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(6),{4,0,0xFF,0x12,0x83,0x01}},
+ {LCM_SEND(2),{0x00,0x80}},
+
+ {LCM_SEND(5),{3,0,0xFF,0x12,0x83}},
+
+#ifdef THREE_LANE_SUPPORT
+ {LCM_SEND(2),{0x00,0x92}},
+ {LCM_SEND(5),{3,0,0xFF,0x20,0x02}}, //0x20:3lane 0x30:4lanes
+#endif
+ //---------------PANEL setting -----------//
+ {LCM_SEND(2),{0x00,0x80}},
+ {LCM_SEND(10),{8,0,0xC0,0x00,0x64,0x00,0x10,0x10,0x00,0x64}},
+ {LCM_SEND(2),{0x00,0x87}},
+ {LCM_SEND(5),{3,0,0xC0,0x10,0x10}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(9),{7,0,0xC0,0x00,0x5C,0x00,0x01,0x00,0x04}},
+ {LCM_SEND(2),{0x00,0xA4}},
+ {LCM_SEND(2),{0xC0,0x22}},
+ {LCM_SEND(2),{0x00,0xB3}},
+ {LCM_SEND(5),{3,0,0xC0,0x00,0x50}},
+ {LCM_SEND(2),{0x00,0xB4}},
+ {LCM_SEND(2),{0xC0,0x55}},
+ {LCM_SEND(2),{0x00,0x81}},
+ //if(!TC358768_Gen_write_1A_1P(0xC1,0x55)) return -1;//xufei 2013-08-26 delete
+ //or
+ {LCM_SEND(2),{0xC1,0x66}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(2),{0xC4,0x49}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(2),{0x35,0x01}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(2),{0x36,0x00}},
+ //-----------------POWER SETTING-----------------
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(10),{8,0,0xC4,0x05,0x10,0x06,0x02,0x05,0x15,0x10}},
+ {LCM_SEND(2),{0x00,0xA7}},
+ {LCM_SEND(10),{8,0,0xC4,0x05,0x10,0x07,0x02,0x05,0x15,0x10}},
+ {LCM_SEND(2),{0x00,0xB0}},
+ {LCM_SEND(5),{3,0,0xC4,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x91}},
+ {LCM_SEND(5),{3,0,0xC5,0x46,0x40}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(5),{3,0,0xD8,0xC7,0xC7}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(2),{0xD9,0x6B}},
+ {LCM_SEND(2),{0x00,0x81}},
+ {LCM_SEND(2),{0xC4,0x82}},
+ {LCM_SEND(2),{0x00,0xB0}},
+
+ //if(!TC358768_Gen_write_1A_2P(0xC5,0x04,0xB8)) return -1;//xufei 2013-08-26 delete
+ //or
+ {LCM_SEND(5),{3,0,0xC5,0x04,0x58}},
+ {LCM_SEND(2),{0x00,0xBB}},
+ {LCM_SEND(2),{0xC5,0x80}},
+ {LCM_SEND(2),{0x00,0x82}},
+ {LCM_SEND(2),{0xC4,0x02}},
+ {LCM_SEND(2),{0x00,0xC6}},
+ {LCM_SEND(2),{0xB0,0x03}},
+ {LCM_SEND(2),{0x00,0xB1}},
+ {LCM_SEND(2),{0xC6,0x03}},
+ //-----------------CONTROL SETTING---------------
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(2),{0xD0,0x40}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(5),{3,0,0xD1,0x00,0x00}},
+ //-----------------PANEL TIMING STATE-------------------
+ {LCM_SEND(2),{0x00,0x80}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x87}},
+ {LCM_SEND(6),{4,0,0xCB,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x97}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x9E}},
+ {LCM_SEND(2),{0xCB,0x00}},
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xA7}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xAE}},
+ {LCM_SEND(2),{0xCB,0x00}},
+ {LCM_SEND(2),{0x00,0xB0}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB7}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xBE}},
+ {LCM_SEND(2),{0xCB,0x00}},
+ {LCM_SEND(2),{0x00,0xC0}},
+ {LCM_SEND(10),{8,0,0xCB,0x05,0x05,0x05,0x05,0x05,0x05,0x00}},
+ {LCM_SEND(2),{0x00,0xC7}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x05,0x05,0x00,0x05}},
+ {LCM_SEND(2),{0x00,0xCE}},
+ {LCM_SEND(2),{0xCB,0x05}},
+ {LCM_SEND(2),{0x00,0xD0}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xD7}},
+ {LCM_SEND(10),{8,0,0xCB,0x05,0x05,0x05,0x05,0x05,0x05,0x00}},
+ {LCM_SEND(2),{0x00,0xDE}},
+ {LCM_SEND(2),{0xCB,0x00}},
+ {LCM_SEND(2),{0x00,0xE0}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x05,0x05,0x00,0x05,0x05}},
+ {LCM_SEND(2),{0x00,0xE7}},
+ {LCM_SEND(10),{8,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xF0}},
+ {LCM_SEND(10),{8,0,0xCB,0xff,0xff,0xff,0xff,0xff,0xff,0xff}},
+ {LCM_SEND(2),{0x00,0xF7}},
+ {LCM_SEND(6),{4,0,0xCB,0xff,0xff,0xff,0xff}},
+ //--------------PANEL PAD MAPPING-------------
+ {LCM_SEND(2),{0x00,0x80}},
+ {LCM_SEND(10),{8,0,0xCC,0x0E,0x10,0x0A,0x0C,0x02,0x04,0x00}},
+ {LCM_SEND(2),{0x00,0x87}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x2E,0x2D,0x00,0x29}},
+ {LCM_SEND(2),{0x00,0x8E}},
+ {LCM_SEND(2),{0xCC,0x2A}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x97}},
+ {LCM_SEND(10),{8,0,0xCC,0x0D,0x0F,0x09,0x0B,0x01,0x03,0x00}},
+ {LCM_SEND(2),{0x00,0x9E}},
+ {LCM_SEND(2),{0xCC,0x00}},
+
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x2E,0x2D,0x00,0x29,0x2A}},
+ {LCM_SEND(2),{0x00,0xA7}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB0}},
+ {LCM_SEND(10),{8,0,0xCC,0x0B,0x09,0x0F,0x0D,0x03,0x01,0x00}},
+ {LCM_SEND(2),{0x00,0xB7}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x2D,0x2E,0x00,0x29}},
+ {LCM_SEND(2),{0x00,0xBE}},
+ {LCM_SEND(2),{0xCC,0x2A}},
+ {LCM_SEND(2),{0x00,0xC0}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xC7}},
+ {LCM_SEND(10),{8,0,0xCC,0x0C,0x0A,0x10,0x0E,0x04,0x02,0x00}},
+ {LCM_SEND(2),{0x00,0xCE}},
+ {LCM_SEND(2),{0xCC,0x00}},
+ {LCM_SEND(2),{0x00,0xD0}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x2D,0x2E,0x00,0x29,0x2A}},
+ {LCM_SEND(2),{0x00,0xD7}},
+ {LCM_SEND(10),{8,0,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ //-----------PANEL TIMING SETTING
+ {LCM_SEND(2),{0x00,0x80}},
+ {LCM_SEND(10),{8,0,0xCE,0x8B,0x03,0x18,0x8A,0x03,0x18,0x89}},
+ {LCM_SEND(2),{0x00,0x87}},
+ {LCM_SEND(8),{6,0,0xCE,0x03,0x18,0x88,0x03,0x18}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(10),{8,0,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x97}},
+ {LCM_SEND(10),{8,0,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x07,0x05,0x00,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xA7}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x06,0x05,0x01,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xB0}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x05,0x05,0x02,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xB7}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x04,0x05,0x03,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xC0}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x03,0x05,0x04,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xC7}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x02,0x05,0x05,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xD0}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x01,0x05,0x06,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0xD7}},
+ {LCM_SEND(10),{8,0,0xCE,0x38,0x00,0x05,0x07,0x00,0x48,0x00}},
+ {LCM_SEND(2),{0x00,0x80}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x87}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x97}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xA7}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB0}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB7}},
+ {LCM_SEND(10),{8,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xC0}},
+ {LCM_SEND(10),{8,0,0xCF,0x02,0x01,0x20,0x20,0x00,0x00,0x01}},
+ {LCM_SEND(2),{0x00,0xC7}},
+ {LCM_SEND(6),{4,0,0xCF,0x81,0x00,0x03,0x08}},
+ {LCM_SEND(2),{0x00,0xB5}},
+ {LCM_SEND(9),{7,0,0xC5,0x00,0x6F,0xFF,0x00,0x6F,0xFF}},
+ //-----------------FOR POWER IC--------------------------
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(6),{4,0,0xF5,0x02,0x11,0x02,0x11}},
+ {LCM_SEND(2),{0x00,0x90}},
+ {LCM_SEND(2),{0xC5,0x50}},
+ {LCM_SEND(2),{0x00,0x94}},
+ {LCM_SEND(2),{0xC5,0x66}},
+ //-----------------VGL01/02----------------------------------
+ {LCM_SEND(2),{0x00,0xB2}},
+ {LCM_SEND(5),{3,0,0xF5,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB4}},
+ {LCM_SEND(5),{3,0,0xF5,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB6}},
+ {LCM_SEND(5),{3,0,0xF5,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0xB8}},
+ {LCM_SEND(5),{3,0,0xF5,0x00,0x00}},
+ {LCM_SEND(2),{0x00,0x94}},
+ {LCM_SEND(2),{0xF5,0x02}},
+ {LCM_SEND(2),{0x00,0xBA}},
+ {LCM_SEND(2),{0xF5,0x03}},
+ {LCM_SEND(2),{0x00,0xB4}},
+ {LCM_SEND(2),{0xC5,0xC0}},
+ {LCM_SEND(2),{0x00,0xc6}},
+ {LCM_SEND(2),{0xB0,0x03}},
+ //spread frame range
+ {LCM_SEND(2),{0x00,0xA0}},
+ {LCM_SEND(2),{0xC1,0x02}},
+ {LCM_SEND(2),{0x00,0xA3}},
+ {LCM_SEND(2),{0xC1,0xF0}},
+ //-----------------GAMMA------------------------------
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(10),{8,0,0xE1,0x00,0x0d,0x14,0x0d,0x06,0x0e,0x0a}},
+ {LCM_SEND(10),{8,0,0xE1,0x09,0x05,0x08,0x0f,0x08,0x0f,0x10}},
+ {LCM_SEND(5),{3,0,0xE1,0x0a,0x05}},
+ {LCM_SEND(2),{0x00,0x00}},
+ {LCM_SEND(10),{8,0,0xE2,0x00,0x0d,0x14,0x0d,0x06,0x0e,0x0a}},
+ {LCM_SEND(10),{8,0,0xE2,0x09,0x05,0x08,0x0f,0x08,0x0f,0x10}},
+ {LCM_SEND(5),{3,0,0xE2,0x0a,0x05}},
+
+ {LCM_SEND(1), {0x11}}, // sleep out
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29}}, // display on
+ {LCM_SLEEP(50),}, //30, 100
+ {LCM_SEND(1), {0x2C}}, // normal on
+};
+
+static int32_t otm1283a_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("otm1283a_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ mdelay((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+ return 0;
+}
+
+static uint32_t otm1283a_readid(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[5] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("lcd_otm1283a_mipi read id!\n");
+ return 0x1283;
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ mdelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0xa1, 5,(uint8_t *)read_data);
+ LCD_PRINT("lcd_otm1283a_mipi read id 0xa1 value is 0x%x, 0x%x, 0x%x, 0x%x, 0x%x!\n",
+ read_data[0], read_data[1], read_data[2], read_data[3], read_data[4]);
+
+ mipi_eotp_set(1,1);
+
+ if((0x01 == read_data[0])&&(0x8b == read_data[1])&&(0x12 == read_data[2])&&(0x83 == read_data[3])&&(0xff == read_data[4])){
+ LCD_PRINT("lcd_otm1283a_mipi read id success!\n");
+ return 0x1283;
+ }
+ }
+
+ printk("lcd_otm1283a_mipi identify fail!\n");
+ return 0;
+}
+
+static uint32_t otm1283a_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_otm1283a_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+// printk("lcd_otm1283a_mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_otm1283a_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ printk("lcd_otm1283a_mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t otm1283a_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ pr_debug("otm1283a_check_esd!\n");
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = otm1283a_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0x9c){
+ pr_debug("otm1283a_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("otm1283a_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static int32_t otm1283a_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "otm1283a_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static struct panel_operations lcd_otm1283a_mipi_operations = {
+ .panel_init = otm1283a_mipi_init,
+ .panel_readid = otm1283a_readid,
+ .panel_esd_check = otm1283a_check_esd,
+ .panel_enter_sleep = otm1283a_enter_sleep,
+};
+
+static struct timing_rgb lcd_otm1283a_mipi_timing = {
+ .hfp =32,
+ .hbp = 4,
+ .hsync =8,
+ .vfp = 17,
+ .vbp = 18,
+ .vsync = 7,
+};
+
+static struct info_mipi lcd_otm1283a_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+#ifdef THREE_LANE_SUPPORT
+ .lan_number = 3,
+ .phy_feq = 550*1000,
+#else
+ .lan_number = 4,
+ .phy_feq = 500*1000,
+#endif
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_otm1283a_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_otm1283a_mipi_spec = {
+ .width = 720,
+ .height = 1280,
+ .fps = 60,
+ .reset_timing = {5,40,20},
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+// .suspend_mode = SEND_SLEEP_CMD,
+ .info = {
+ .mipi = &lcd_otm1283a_mipi_info
+ },
+ .ops = &lcd_otm1283a_mipi_operations,
+};
+
+struct panel_cfg lcd_otm1283a_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x1283,
+ .lcd_name = "lcd_otm1283a_mipi",
+ .panel = &lcd_otm1283a_mipi_spec,
+};
+
+static int __init lcd_otm1283_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_otm1283a_mipi);
+}
+
+subsys_initcall(lcd_otm1283_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_otm8019a_mipi.c b/drivers/video/sprdfb/lcd/lcd_otm8019a_mipi.c new file mode 100644 index 00000000..a9ac2829 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_otm8019a_mipi.c @@ -0,0 +1,516 @@ +/* drivers/video/sprdfb/lcd_otm8019a_mipi.c
+ *
+ * Support for otm8019a mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+//#define printk printf
+
+#define LCD_DEBUG
+//#define THREE_LANE_SUPPORT
+
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x37, {LCM_SEND(2), {0x5, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(6), {4, 0, 0xFF, 0x80, 0x19, 0x01} },
+
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(5), {3, 0, 0xFF, 0x80, 0x19} },
+
+ {LCM_SEND(2), {0x00, 0x03} },
+ {LCM_SEND(2), {0xFF, 0x01} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(5), {3, 0, 0xD8, 0x7F, 0X7F} },/*6f*/
+
+ {LCM_SEND(2), {0x00, 0x082} },
+ {LCM_SEND(2), {0xC5, 0xB0} },
+
+ {LCM_SEND(2), {0x00, 0xA1} },
+ {LCM_SEND(2), {0xC1, 0x08} },
+
+ {LCM_SEND(2), {0x00, 0xA3} },
+ {LCM_SEND(2), {0xC0, 0x1B} },
+
+ {LCM_SEND(2), {0x00, 0xB4} },
+ {LCM_SEND(2), {0xC0, 0x77} },
+
+ {LCM_SEND(2), {0x00, 0x81} },
+ {LCM_SEND(2), {0xC4, 0x83} },
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(6), {4, 0, 0xC5, 0x4E, 0xA7, 0x01} },
+
+ {LCM_SEND(2), {0x00, 0xB1} },
+ {LCM_SEND(2), {0xC5, 0xA9} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(2), {0xD9, 0x17} },
+
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(2), {0xD8, 0x58} },
+
+/***************Gamma 2.2********************/
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(23), {21, 0, 0xE1, 0x00, 0x06, 0x14, 0x25, 0x3d, 0x4e, 0x5a,
+ 0x8d, 0x7c, 0x91, 0x75, 0x64, 0x7d, 0x69, 0x6e, 0x67, 0x5f, 0x55,
+ 0x5c, 0x02} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(23), {21, 0, 0xE2, 0x00, 0x06, 0x14, 0x25, 0x3d, 0x4e, 0x5a,
+ 0x8d, 0x7b, 0x91, 0x75, 0x64, 0x7d, 0x69, 0x6e, 0x67, 0x5f, 0x55,
+ 0x5c, 0x02} },
+/********************************************/
+/***************Gamma 2.5********************/
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(23), {21, 0, 0xE1, 0x00, 0x02, 0x07, 0x12, 0x22, 0x37, 0x41,
+ 0x78, 0x6b, 0x85, 0x7f, 0x6b, 0x82, 0x6b, 0x71, 0x69, 0x61, 0x58,
+ 0x4c, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(23), {21, 0, 0xE2, 0x00, 0x02, 0x07, 0x12, 0x22, 0x37, 0x41,
+ 0x78, 0x6b, 0x85, 0x7f, 0x6b, 0x82, 0x6b, 0x71, 0x69, 0x61, 0x58,
+ 0x4c, 0x00} },
+/********************************************/
+
+ {LCM_SEND(2), {0x00, 0xA7} },
+ {LCM_SEND(2), {0xB3, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0x92} },
+ {LCM_SEND(2), {0xB3, 0x45} },
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(2), {0xB3, 0x02} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(2), {0x36, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(9), {7, 0, 0xC0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03} },
+
+ {LCM_SEND(2), {0x00, 0xA0} },
+ {LCM_SEND(2), {0xC1, 0xE8} },
+
+ {LCM_SEND(2), {0x00, 0xA6} },
+ {LCM_SEND(6), {4, 0, 0xC1, 0x01, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(9), {7, 0, 0xCE, 0x87, 0x03, 0x00, 0x86, 0x03, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(9), {7, 0, 0xCE, 0x33, 0x54, 0x00, 0x33, 0x55, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0xA0} },
+ {LCM_SEND(17), {15, 0, 0xCE, 0x38, 0x03, 0x03, 0x58, 0x00, 0x00, 0x00,
+ 0x38, 0x02, 0x03, 0x59, 0x00, 0x00, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0xB0} },
+ {LCM_SEND(17), {15, 0, 0xCE, 0x38, 0x01, 0x03, 0x5A, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x03, 0x5B, 0x00, 0x00, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0xC0} },
+ {LCM_SEND(17), {15, 0, 0xCE, 0x30, 0x00, 0x03, 0x5C, 0x00, 0x00, 0x00,
+ 0x30, 0x01, 0x03, 0x5D, 0x00, 0x00, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0xD0} },
+ {LCM_SEND(17), {15, 0, 0xCE, 0x38, 0x05, 0x03, 0x5E, 0x00, 0x00, 0x00,
+ 0x38, 0x04, 0x03, 0x5F, 0x00, 0x00, 0x00} },
+ {LCM_SLEEP(2)},
+
+ {LCM_SEND(2), {0x00, 0xC0} },
+ {LCM_SEND(13), {11, 0, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x80, 0x00, 0x09} },
+
+ {LCM_SEND(2), {0x00, 0xC0} },
+ {LCM_SEND(18), {16, 0, 0xCB, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0xD0} },
+ {LCM_SEND(18), {16, 0, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0xE0} },
+ {LCM_SEND(13), {11, 0, 0xCB, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(13), {11, 0, 0xCC, 0x00, 0x26, 0x25, 0x02, 0x06, 0x00, 0x00,
+ 0x0A, 0x0E, 0x0C} },
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(18), {16, 0, 0xCC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0xA0} },
+ {LCM_SEND(18), {16, 0, 0xCC, 0x0f, 0x0b, 0x0d, 0x09, 0x00, 0x00, 0x05,
+ 0x01, 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0xB0} },
+ {LCM_SEND(13), {11, 0, 0xCC, 0x00, 0x25, 0x26, 0x05, 0x01, 0x00, 0x00,
+ 0x0D, 0x09, 0x0B} },
+
+ {LCM_SEND(2), {0x00, 0xC0} },
+ {LCM_SEND(18), {16, 0, 0xCC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+
+ {LCM_SEND(2), {0x00, 0xD0} },
+ {LCM_SEND(18), {16, 0, 0xCC, 0x10, 0x0c, 0x0a, 0x0e, 0x00, 0x00, 0x02,
+ 0x06, 0x26, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00} },
+
+/*-----------------AUTO SHIFT-------------------*/
+ {LCM_SEND(2), {0x00, 0x98} },
+ {LCM_SEND(2), {0xC0, 0x00} },
+ {LCM_SEND(2), {0x00, 0xA9} },
+ {LCM_SEND(2), {0xC0, 0x06} },
+ {LCM_SEND(2), {0x00, 0xB0} },
+ {LCM_SEND(6), {4, 0, 0xC1, 0x20, 0x00, 0x00} },
+ {LCM_SEND(2), {0x00, 0xE1} },
+ {LCM_SEND(5), {3, 0, 0xC0, 0x40, 0x18} },
+/*----------------------------------------------*/
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(2), {0xC4, 0x30} }, /*source blanking area=GND*/
+
+ {LCM_SEND(2), {0x00, 0x80} },
+ {LCM_SEND(5), {3, 0, 0xC1, 0x03, 0x33} },
+
+ {LCM_SEND(2), {0x00, 0x90} },
+ {LCM_SEND(2), {0xB6, 0xB4} },/*command fia*/
+ {LCM_SLEEP(10)},
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(2), {0xfb, 0x01} },
+
+ {LCM_SEND(2), {0x00, 0x00} },
+ {LCM_SEND(2), {4, 0, 0xFF, 0xFF, 0xFF, 0xFF} },
+
+ {LCM_SEND(1), {0x11} }, /*sleep out*/
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29} }, /*display on*/
+ {LCM_SLEEP(5)}, /*30, 100 ,50*/
+ {LCM_SEND(1), {0x2C} } /*normal on*/
+};
+
+static int32_t otm8019a_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode =
+ self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("otm8019a_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for (i = 0; i < ARRAY_SIZE(init_data); i++) {
+ tag = (init->tag >> 24);
+ if (tag & LCM_TAG_SEND) {
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ } else if (tag & LCM_TAG_SLEEP) {
+ mdelay((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+ return 0;
+}
+
+static uint32_t otm8019a_readid(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[5] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode =
+ self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("lcd_otm8019a_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1, 0);
+
+ for (j = 0; j < 4; j++) {
+ rd_prepare = rd_prep_code;
+ for (i = 0; i < ARRAY_SIZE(rd_prep_code); i++) {
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if (tag & LCM_TAG_SEND)
+ mipi_force_write(rd_prepare->datatype,
+ rd_prepare->real_cmd_code.data,
+ (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ else if (tag & LCM_TAG_SLEEP)
+ mdelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0xa1, 5, (uint8_t *)read_data);
+ LCD_PRINT("lcd_otm8019a_mipi read id 0xa1 value is 0x%x, 0x%x, 0x%x, 0x%x, 0x%x!\n",
+ read_data[0], read_data[1], read_data[2], read_data[3],
+ read_data[4]);
+
+ mipi_eotp_set(1, 1);
+
+ if ((0x01 == read_data[0]) && (0x8b == read_data[1]) &&
+ (0x80 == read_data[2]) && (0x19 == read_data[3]) &&
+ (0xff == read_data[4])) {
+ LCD_PRINT("lcd_otm8019a_mipi read id success!\n");
+ return 0x8019;
+ }
+ }
+
+ printk(KERN_ERR "lcd_otm8019a_mipi identify fail!\n");
+ return 0;
+}
+
+static uint32_t otm8019a_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_otm8019a_mipi read power mode!\n");
+ mipi_eotp_set(0, 1);
+ for (j = 0; j < 4; j++) {
+ rd_prepare = rd_prep_code_1;
+ for (i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++) {
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if (tag & LCM_TAG_SEND)
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data,
+ (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ else if (tag & LCM_TAG_SLEEP)
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1, (uint8_t *)read_data);
+ /*printk("lcd_otm80193a_mipi read power mode 0x0A value is 0x%x!,
+ read result(%d)\n", read_data[0], read_rtn);*/
+ if ((0x9c == read_data[0]) && (0 == read_rtn)) {
+ pr_debug("lcd_otm8019a_mipi read power mode success!\n");
+ mipi_eotp_set(1, 1);
+ return 0x9c;
+ }
+ }
+
+ printk(KERN_ERR "lcd_otm8019a_mipi read power mode fail!0x0A value is 0x%x!, read result(%d)\n",
+ read_data[0], read_rtn);
+ mipi_eotp_set(1, 1);
+ return 0x0;
+}
+
+static int32_t otm8019a_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+#ifndef FB_CHECK_ESD_IN_VFP
+ mipi_set_lp_mode_t mipi_set_data_lp_mode =
+ self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode =
+ self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+#endif
+
+ pr_debug("otm8019a_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if (SPRDFB_MIPI_MODE_CMD == work_mode)
+ mipi_set_lp_mode();
+ else
+ mipi_set_data_lp_mode();
+#endif
+ power_mode = otm8019a_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if (SPRDFB_MIPI_MODE_CMD == work_mode)
+ mipi_set_hs_mode();
+ else
+ mipi_set_data_hs_mode();
+#endif
+ if (power_mode == 0x9c) {
+ pr_debug("otm8019a_check_esd OK!\n");
+ return 1;
+ } else {
+ printk(KERN_ERR "otm8019a_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static int32_t otm8019a_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "otm8019a_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if (is_sleep) {
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ } else {
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1, 0);
+
+ for (i = 0; i < size; i++) {
+ tag = (sleep_in_out->tag >> 24);
+ if (tag & LCM_TAG_SEND)
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ else if (tag & LCM_TAG_SLEEP)
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ sleep_in_out++;
+ }
+ mipi_eotp_set(1, 1);
+
+ return 0;
+}
+
+static struct panel_operations lcd_otm8019a_mipi_operations = {
+ .panel_init = otm8019a_mipi_init,
+ .panel_readid = otm8019a_readid,
+ .panel_esd_check = otm8019a_check_esd,
+ .panel_enter_sleep = otm8019a_enter_sleep,
+};
+
+static struct timing_rgb lcd_otm8019a_mipi_timing = {
+ .hfp = 48, /*46*/
+ .hbp = 48, /*44*/ + .hsync = 8, + .vfp = 16, /*14*/ + .vbp = 16, + .vsync = 8,/* 2*/
+};
+
+static struct info_mipi lcd_otm8019a_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_otm8019a_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_otm8019a_mipi_spec = {
+ .width = 480,
+ .height = 854,
+ .fps = 60,
+ .reset_timing = {5, 40, 20},
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ /*.suspend_mode = SEND_SLEEP_CMD,*/
+ .info = {
+ .mipi = &lcd_otm8019a_mipi_info
+ },
+ .ops = &lcd_otm8019a_mipi_operations,
+};
+
+struct panel_cfg lcd_otm8019a_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x8019,
+ .lcd_name = "lcd_otm8019a_mipi",
+ .panel = &lcd_otm8019a_mipi_spec,
+};
+
+static int __init lcd_otm8019a_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_otm8019a_mipi);
+}
+
+subsys_initcall(lcd_otm8019a_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_otm_8018b_mipi.c b/drivers/video/sprdfb/lcd/lcd_otm_8018b_mipi.c new file mode 100644 index 00000000..7651fd4e --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_otm_8018b_mipi.c @@ -0,0 +1,296 @@ +/* drivers/video/sc8825/lcd_otm8018b_mipi.c
+ *
+ * Support for otm8018b mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_Delay(ms) uDelay(ms*1000)
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+#if 1
+{LCM_SEND(6), {4, 0, 0xff,0x80,0x09,0x01}},
+
+{LCM_SEND(2), {0x00,0x80}},
+{LCM_SEND(5), {3, 0, 0xff,0x80,0x09}},
+
+{LCM_SEND(2), {0x00,0x03}},
+{LCM_SEND(2), {0xFF,0x01}},
+
+{LCM_SEND(2), {0x00,0xB4}},
+{LCM_SEND(2), {0xC0,0x10}},
+
+{LCM_SEND(2), {0x00,0x82}},
+{LCM_SEND(2), {0xC5,0xA3}},
+
+{LCM_SEND(2), {0x00,0x90}},
+{LCM_SEND(5), {3, 0, 0xC5,0xC6,0x76}},
+
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(5), {3, 0, 0xD8,0x75,0x73}},
+
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(2), {0xD9,0x4E}},
+
+/*-------------Gamma+ ------*/
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(19), {17, 0, 0xE1,0x0C,0x0D,0x11,0x10,0x0A,0x1B,0x0B,0x0B,0x00,0x03,0x03,0x05,0x0D,0x24,0x21,0x05}},
+
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(19), {17, 0, 0xE2,0x0C,0x0D,0x11,0x12,0x0E,0x1D,0x0B,0x0B,0x00,0x03,0x03,0x05,0x0D,0x25,0x21,0x05}},
+
+{LCM_SEND(2), {0x00,0x81}},
+{LCM_SEND(2), {0xC1,0x66}},
+{LCM_SEND(2), {0x00,0xA1}},
+{LCM_SEND(2), {0xC1,0x08}},
+
+{LCM_SEND(2), {0x00,0x89}},
+{LCM_SEND(2), {0xC4,0x08}},
+
+{LCM_SEND(2), {0x00,0xA2}},
+{LCM_SEND(6), {4, 0, 0xC0,0x1B,0x00,0x02}},
+
+{LCM_SEND(2), {0x00,0x81}},
+{LCM_SEND(2), {0xC4,0x83}},
+
+{LCM_SEND(2), {0x00,0x92}},
+{LCM_SEND(2), {0xC5,0x01}},
+
+{LCM_SEND(2), {0x00,0xB1}},
+{LCM_SEND(2), {0xC5,0xA9}},
+
+/*C09x : mck_shift1/mck_shift2/mck_shift3*/
+{LCM_SEND(2), {0x00,0x90}},
+{LCM_SEND(9), {7, 0, 0xC0,0x00,0x44,0x00,0x00,0x00,0x03}},
+
+/*C1Ax : hs_shift/vs_shift*/
+{LCM_SEND(2), {0x00,0xA6}},
+{LCM_SEND(6), {4, 0, 0xC1,0x00,0x00,0x00}},
+
+//CE8x : vst1, vst2, vst3, vst4
+{LCM_SEND(2), {0x00,0x80}},
+{LCM_SEND(15), {13, 0, 0xCE,0x87,0x03,0x00,0x85,0x03,0x00,0x86,0x03,0x00,0x84,0x03,0x00}},
+
+//CEAx : clka1, clka2
+{LCM_SEND(2), {0x00,0xA0}},
+{LCM_SEND(17), {15, 0, 0xCE,0x38,0x03,0x03,0x58,0x00,0x00,0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00}},
+
+//CEBx : clka3, clka4
+{LCM_SEND(2), {0x00,0xB0}},
+{LCM_SEND(17), {15, 0, 0xCE,0x38,0x01,0x03,0x5A,0x00,0x00,0x00,0x38,0x00,0x03,0x5B,0x00,0x00,0x00}},
+
+//CECx : clkb1, clkb2
+{LCM_SEND(2), {0x00,0xC0}},
+{LCM_SEND(17), {15, 0, 0xCE,0x30,0x00,0x03,0x5C,0x00,0x00,0x00,0x30,0x01,0x03,0x5D,0x00,0x00,0x00}},
+
+//CEDx : clkb3, clkb4
+{LCM_SEND(2), {0x00,0xD0}},
+{LCM_SEND(17), {15, 0, 0xCE,0x30,0x02,0x03,0x5E,0x00,0x00,0x00,0x30,0x03,0x03,0x5F,0x00,0x00,0x00}},
+
+{LCM_SEND(2), {0x00, 0xC7}},
+{LCM_SEND(2), {0xCF, 0x00}},
+
+{LCM_SEND(2), {0x00, 0xC9}},
+{LCM_SEND(2), {0xCF, 0x00}},
+
+{LCM_SEND(2), {0x00, 0xC4}},
+{LCM_SEND(9), {7, 0, 0xCB,0x04,0x04,0x04,0x04,0x04,0x04}},
+
+{LCM_SEND(2), {0x00, 0xD9}},
+{LCM_SEND(9), {7, 0, 0xCB,0x04,0x04,0x04,0x04,0x04,0x04}},
+
+{LCM_SEND(2), {0x00, 0x84}},
+{LCM_SEND(9), {7, 0, 0xCC,0x0C,0x0A,0x10,0x0E,0x03,0x04}},
+
+{LCM_SEND(2), {0x00,0x9E}},
+{LCM_SEND(2), {0xCC,0x0B}},
+
+{LCM_SEND(2), {0x00,0xA0}},
+{LCM_SEND(8), {6, 0, 0xCC,0x09,0x0F,0x0D,0x01,0x02}},
+
+{LCM_SEND(2), {0x00,0xB4}},
+{LCM_SEND(9), {7, 0, 0xCC,0x0D,0x0F,0x09,0x0B,0x02,0x01}},
+
+{LCM_SEND(2), {0x00,0xCE}},
+{LCM_SEND(2), {0xCC,0x0E}},
+
+{LCM_SEND(2), {0x00,0xD0}},
+{LCM_SEND(8), {6, 0, 0xCC,0x10,0x0A,0x0C,0x04,0x03}},
+
+{LCM_SEND(2), {0x00,0x00}},
+{LCM_SEND(2), {0x3A,0x77}},
+
+{LCM_SEND(2), {0x11, 0x00}}, // sleep out
+{LCM_SLEEP(200),},
+{LCM_SEND(2), {0x29, 0x00}}, // display on
+
+{LCM_SEND(1), {0x2C}}, // normal on
+
+#endif
+
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static int32_t otm8018b_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ pr_debug(KERN_DEBUG "otm8018b_mipi_init\n");
+
+ mipi_set_cmd_mode();
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ return 0;
+}
+
+static uint32_t otm8018b_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ return 0x18;
+}
+
+static int32_t otm8018b_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+
+ printk(KERN_DEBUG "otm8018b_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static struct panel_operations lcd_otm8018b_mipi_operations = {
+ .panel_init = otm8018b_mipi_init,
+ .panel_readid = otm8018b_readid,
+ .panel_enter_sleep = otm8018b_enter_sleep,
+};
+
+static struct timing_rgb lcd_otm8018b_mipi_timing = {
+ .hfp = 80, /* unit: pixel */
+ .hbp = 80,
+ .hsync = 6,
+ .vfp = 10, /*unit: line*/
+ .vbp = 10,
+ .vsync = 6,
+};
+
+static struct info_mipi lcd_otm8018b_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_POS,
+ .shut_down_pol = SPRDFB_POLARITY_POS,
+ .timing = &lcd_otm8018b_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_otm8018b_mipi_spec = {
+ .width = 480,
+ .height = 800,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_otm8018b_mipi_info
+ },
+ .ops = &lcd_otm8018b_mipi_operations,
+};
+
+struct panel_cfg lcd_otm8018b_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x18,
+ .lcd_name = "lcd_otm8018b_mipi",
+ .panel = &lcd_otm8018b_mipi_spec,
+};
+
+static int __init lcd_otm8018b_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_otm8018b_mipi);
+}
+
+subsys_initcall(lcd_otm8018b_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_rm68180_mipi.c b/drivers/video/sprdfb/lcd/lcd_rm68180_mipi.c new file mode 100644 index 00000000..e100f38d --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_rm68180_mipi.c @@ -0,0 +1,383 @@ +/* drivers/video/srpdfb/lcd_rm68180_mipi.c + * + * Support for rm68180 mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +//#define LCD_Delay(ms) uDelay(ms*1000) + +#define MAX_DATA 58 + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Force_Cmd_Code rd_prep_code_1[]={ + {0x37, {LCM_SEND(2), {0x1, 0}}}, +}; + +static LCM_Init_Code init_data[] = { +#if 1 //l901 shengjing rm68180 + {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x01}}, + {LCM_SEND(6),{4,0,0xB0,0x0D,0x0D,0x0D}}, + {LCM_SEND(6),{4,0,0xB1,0x05,0x05,0x05}}, + {LCM_SEND(6),{4,0,0xB6,0x34,0x34,0x34}}, + {LCM_SEND(6),{4,0,0xB7,0x34,0x34,0x34}}, + {LCM_SEND(6),{4,0,0xB8,0x24,0x24,0x24}}, + {LCM_SEND(6),{4,0,0xB9,0x34,0x34,0x34}}, + {LCM_SEND(6),{4,0,0xBA,0x04,0x04,0x04}}, + {LCM_SEND(6),{4,0,0xBC,0x00,0x90,0x00}}, + {LCM_SEND(6),{4,0,0xBD,0x00,0x90,0x00}}, + {LCM_SEND(5),{3,0,0xBE,0x00,0x75}}, + {LCM_SEND(2),{0xCC,0x05}}, + {LCM_SEND(55),{53,0,0xD1,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(55),{53,0,0xD2,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(55),{53,0,0xD3,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(55),{53,0,0xD4,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(55),{53,0,0xD5,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(55),{53,0,0xD6,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x3B,0x00,0x60,0x00,0x9E,0x00,0xCF,0x01,0x17,0x01,0x4B,0x01,0x93,0x01,0xC6,0x02,0x10,0x02,0x48,0x02,0x49,0x02,0x79,0x02,0xAA,0x02,0xC4,0x02,0xE4,0x02,0xF8,0x03,0x10,0x03,0x20,0x03,0x36,0x03,0x46,0x03,0x5C,0x03,0x8B,0x03,0xFF}}, + {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x00}}, + {LCM_SEND(2),{0xB1,0xFC}}, + {LCM_SEND(2),{0xB4,0x10}}, + {LCM_SEND(2),{0xB6,0x01}}, + {LCM_SEND(7),{5,0,0xB8,0x01,0x04,0x04,0x04}}, + {LCM_SEND(2),{0xBA,0x01}}, + {LCM_SEND(6),{4,0,0xBC,0x02,0x02,0x02}}, + {LCM_SEND(2),{0x3A,0x77}}, //0x55 + {LCM_SEND(5),{3,0,0xC9,0xC0,0x01}}, + {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x02}}, + {LCM_SEND(2),{0xF6,0x60}}, + {LCM_SEND(2),{0x35,0x00}}, + {LCM_SEND(2),{0x36,0x00}}, + {LCM_SEND(5),{3,0,0x44,0x00,0x50}}, + {LCM_SEND(8),{6,0,0xF0,0x55,0xAA,0x52,0x08,0x01}}, + {LCM_SEND(7),{5,0,0x2A,0x00,0x00,0x01,0xDF}}, + {LCM_SEND(7),{5,0,0x2B,0x00,0x00,0x03,0x1F}}, //0x355 + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(100)}, +#endif +}; + +static LCM_Force_Cmd_Code rd_prep_code[]={ + {0x39, {LCM_SEND(8), {0x6, 0, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01}}}, + {0x37, {LCM_SEND(2), {0x3, 0}}}, +}; + +static LCM_Init_Code sleep_in[] = { +{LCM_SEND(1), {0x28}}, +{LCM_SLEEP(120)}, +{LCM_SEND(1), {0x10}}, +{LCM_SLEEP(100)}, +{LCM_SEND(2), {0x4F,0x01}}, +//{LCM_SEND(2), {0x4f, 0x01}}, +}; + +static LCM_Init_Code sleep_out[] = { +{LCM_SEND(1), {0x11}}, +{LCM_SLEEP(120)}, +{LCM_SEND(1), {0x29}}, +{LCM_SLEEP(100)}, +}; + +static int32_t rm68180_mipi_init(struct panel_spec *self) +{ + int32_t i; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + pr_debug(KERN_DEBUG "rm68180_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(1,0); + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep((init->tag & LCM_TAG_MASK)); + } + init++; + } + mipi_eotp_set(1,1); + return 0; +} + +static uint32_t rm68180_readid(struct panel_spec *self) +{ +//{LCM_SEND(8), {6,0,0xF0,0x55,0xAA,0x52,0x08,0x01}}, + /*Jessica TODO: need read id*/ + int32_t i = 0; + uint32_t j =0; + LCM_Force_Cmd_Code * rd_prepare = rd_prep_code; + + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + unsigned int tag = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("lcd_rm68180_mipi read id!\n"); + mipi_set_cmd_mode(); + mipi_eotp_set(1,0); + //mipi_force_read(0x0, 3,(uint8_t *)read_data); + + for(j = 0; j < 4; j++){ + for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){ + tag = (rd_prepare->real_cmd_code.tag >> 24); + if(tag & LCM_TAG_SEND){ + mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + udelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK) * 1000); + } + rd_prepare++; + } + read_rtn = mipi_force_read(0x04, 3,(uint8_t *)read_data); + printk("lcd_rm68180_mipi read id value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]); + //0x00 0x80 0x00 + //return 0x80; + if((0x80 == read_data[1])){ + self->info.mipi->ops->mipi_set_hs_mode(); + printk("lcd_rm68180_mipi read id success!\n"); + mipi_eotp_set(1,1); + return 0x80; + } + else + printk("lcd_rm68180_mipi read id failed!\n"); + + } + mipi_eotp_set(1,1); + return 0x00; +} + +static uint32_t rm68180_readpowermode(struct panel_spec *self) +{ + int32_t i = 0; + uint32_t j =0; + LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1; + uint8_t read_data[1] = {0}; + int32_t read_rtn = 0; + unsigned int tag = 0; + + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + pr_debug("lcd_rm68180_mipi read power mode!\n"); + mipi_eotp_set(0,1); + for(j = 0; j < 4; j++){ + rd_prepare = rd_prep_code_1; + for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){ + tag = (rd_prepare->real_cmd_code.tag >> 24); + if(tag & LCM_TAG_SEND){ + mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK)); + } + rd_prepare++; + } + read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data); + //printk("lcd_rm68180_mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn); + if((0x9c == read_data[0]) && (0 == read_rtn)){ + pr_debug("lcd_rm68180_mipi read power mode success!\n"); + mipi_eotp_set(1,1); + return 0x9c; + } + } + + printk("lcd_rm68180_mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn); + mipi_eotp_set(1,1); + return 0x0; +} + +static int32_t rm68180_check_esd(struct panel_spec *self) +{ + uint32_t power_mode; + + mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode; + mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode; + mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode; + mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode; + uint16_t work_mode = self->info.mipi->work_mode; + + pr_debug("rm68180_check_esd!\n"); + if(SPRDFB_MIPI_MODE_CMD==work_mode){ + mipi_set_lp_mode(); + }else{ + mipi_set_data_lp_mode(); + } + power_mode = rm68180_readpowermode(self); + //power_mode = 0x0; + if(SPRDFB_MIPI_MODE_CMD==work_mode){ + mipi_set_hs_mode(); + }else{ + mipi_set_data_hs_mode(); + } + if(power_mode == 0x9c){ + pr_debug("rm68180_check_esd OK!\n"); + return 1; + }else{ + printk("rm68180_check_esd fail!(0x%x)\n", power_mode); + return 0; + } +} + +static int32_t rm68180_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write; + + printk(KERN_DEBUG "rm68180_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep((sleep_in_out->tag & LCM_TAG_MASK)); + } + sleep_in_out++; + } +// printk(KERN_DEBUG "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy = %d\n", is_sleep); + //if (!is_sleep) +// { +// printk(KERN_DEBUG "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = %d\n", is_sleep); +// mdelay(6000); +// } + return 0; +} + +static int32_t rm68180_mipi_after_suspend(struct panel_spec *self) +{ + return 0; +} + + +static struct panel_operations lcd_rm68180_mipi_operations = { + .panel_init = rm68180_mipi_init, + .panel_readid = rm68180_readid, + .panel_enter_sleep = rm68180_enter_sleep, + .panel_after_suspend = rm68180_mipi_after_suspend, + .panel_esd_check = rm68180_check_esd, +}; + +static struct timing_rgb lcd_rm68180_mipi_timing = { +#if 1 + .hfp = 20, /* unit: pixel */ + .hbp = 20, + .hsync = 6,//4, + .vfp = 20, /*unit: line*/ + .vbp = 20, + .vsync = 6,//6 +#else +/* + .hfp = 120, + .hbp = 120, + .hsync = 60, + .vfp = 6, + .vbp = 6, + .vsync = 4, +*/ + .hfp =70, + .hbp = 40, + .hsync = 10, + .vfp = 10, + .vbp = 10, + .vsync = 12, +#endif +}; + +static struct info_mipi lcd_rm68180_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq = 360*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_rm68180_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_rm68180_mipi_spec = { + .width = 480, + .height = 800, //854, + .fps = 60, + .reset_timing = {20,20,120}, + //.suspend_mode = SEND_SLEEP_CMD, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .mipi = &lcd_rm68180_mipi_info + }, + .ops = &lcd_rm68180_mipi_operations, +}; + +struct panel_cfg lcd_rm68180_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x80, + .lcd_name = "lcd_rm68180_mipi", + .panel = &lcd_rm68180_mipi_spec, +}; + +static int __init lcd_rm68180_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_rm68180_mipi); +} + +subsys_initcall(lcd_rm68180_mipi_init); diff --git a/drivers/video/sprdfb/lcd/lcd_s6d0139.c b/drivers/video/sprdfb/lcd/lcd_s6d0139.c new file mode 100644 index 00000000..9ed5f1e0 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_s6d0139.c @@ -0,0 +1,244 @@ +/* drivers/video/sc8800g/sc8800g_lcd_s6d0139.c + * + * Support for s6d0139 LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +static int32_t s6d0139_init(struct panel_spec *self) +{ + send_cmd_data_t send_cmd_data = self->info.mcu->ops->send_cmd_data; + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + pr_debug(KERN_DEBUG "s6d0139_init\n"); + + /* reset the lcd */ + self->ops->panel_reset(self); + mdelay(100); + /* start init sequence */ + send_cmd_data(0x0000, 0x0001); + mdelay(10); + + send_cmd_data(0x0007, 0x0000); + send_cmd_data(0x0013, 0x0000); + send_cmd_data(0x0011, 0x2604); + send_cmd_data(0x0014, 0x1212); + send_cmd_data(0x0010, 0x3C00); + send_cmd_data(0x0013, 0x0040); + mdelay(10); + send_cmd_data(0x0013, 0x0060); + mdelay(50); + send_cmd_data(0x0013, 0x0070); + mdelay(40); + send_cmd_data(0x0001, 0x0127); + send_cmd_data(0x0002, 0x0700); + send_cmd_data(0x0003, 0x1030); + send_cmd_data(0x0007, 0x0000); + send_cmd_data(0x0008, 0x0404); + send_cmd_data(0x000B, 0x0200); + send_cmd_data(0x000C, 0x0000); + send_cmd_data(0x0015, 0x0000); + + //gamma setting + send_cmd_data(0x0030, 0x0000); + send_cmd_data(0x0031, 0x0606); + send_cmd_data(0x0032, 0x0006); + send_cmd_data(0x0033, 0x0403); + send_cmd_data(0x0034, 0x0107); + send_cmd_data(0x0035, 0x0101); + send_cmd_data(0x0036, 0x0707); + send_cmd_data(0x0037, 0x0304); + send_cmd_data(0x0038, 0x0A00); + send_cmd_data(0x0039, 0x0706); + send_cmd_data(0x0040, 0x0000); + send_cmd_data(0x0041, 0x0000); + send_cmd_data(0x0042, 0x013F); + send_cmd_data(0x0043, 0x0000); + send_cmd_data(0x0044, 0x0000); + send_cmd_data(0x0045, 0x0000); + send_cmd_data(0x0046, 0xEF00); + send_cmd_data(0x0047, 0x013F); + send_cmd_data(0x0048, 0x0000); + send_cmd_data(0x0007, 0x0011); + mdelay(40); + send_cmd_data(0x0007, 0x0017); + send_cmd_data(0x0020, 0x0000); + send_cmd_data(0x0021, 0x0000); + mdelay(40); + + send_cmd(0x0022); + + + if(1){ + int i = 0; + for (i=0; i<320*240/3; i++) + send_data(0xf800); + for (i=0; i< 320*240/3; i++) + send_data(0x07e0); + for (i=0; i< 320*240/3; i++) + send_data(0x001f); + } + + return 0; +} + +static int32_t s6d0139_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_cmd_data_t send_cmd_data = self->info.mcu->ops->send_cmd_data; + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + pr_debug(KERN_DEBUG "s6d0139_set_window\n"); + + send_cmd_data(0x46, ((right << 8) & 0xff00)|(left&0xff)); + send_cmd_data(0x47, bottom); + send_cmd_data(0x48, top); + + switch (self->direction) { + case LCD_DIRECT_NORMAL: + case LCD_DIRECT_ROT_270: + send_cmd_data(0x0020, left); + send_cmd_data(0x0021, top); + break; + case LCD_DIRECT_ROT_90: + case LCD_DIRECT_MIR_H: + send_cmd_data(0x0020, right); + send_cmd_data(0x0021, top); + break; + case LCD_DIRECT_ROT_180: + case LCD_DIRECT_MIR_HV: + send_cmd_data(0x0020, right); + send_cmd_data(0x0021, bottom); + break; + case LCD_DIRECT_MIR_V: + send_cmd_data(0x0020, left); + send_cmd_data(0x0021, bottom); + break; + default: + pr_debug(KERN_ERR "unknown lcd direction!\n"); + break; + } + + send_cmd(0x0022); + + return 0; +} + +static int32_t s6d0139_invalidate(struct panel_spec *self) +{ + pr_debug(KERN_DEBUG "s6d0139_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width-1, self->height-1); + +} + +static int32_t s6d0139_set_direction(struct panel_spec *self, uint16_t direction) +{ + send_cmd_data_t send_cmd_data = self->info.mcu->ops->send_cmd_data; + pr_debug(KERN_DEBUG "s6d0139_set_direction\n"); + + switch (direction) { + case LCD_DIRECT_NORMAL: + send_cmd_data(0x0003, 0x1030); + break; + case LCD_DIRECT_ROT_90: + send_cmd_data(0x0003, 0x1028); + break; + case LCD_DIRECT_ROT_180: + case LCD_DIRECT_MIR_HV: + send_cmd_data(0x0003, 0x1000); + break; + case LCD_DIRECT_ROT_270: + send_cmd_data(0x0003, 0x1018); + break; + case LCD_DIRECT_MIR_H: + send_cmd_data(0x0003, 0x1020); + break; + case LCD_DIRECT_MIR_V: + send_cmd_data(0x0003, 0x1010); + break; + default: + pr_debug(KERN_ERR "unknown lcd direction!\n"); + send_cmd_data(0x0003, 0x1030); + direction = LCD_DIRECT_NORMAL; + break; + } + + self->direction = direction; + + return 0; +} + +static struct panel_operations lcd_s6d0139_operations = { + .panel_init = s6d0139_init, + .panel_set_window = s6d0139_set_window, + .panel_invalidate = s6d0139_invalidate, + .panel_set_direction = s6d0139_set_direction, +}; + + +static struct timing_mcu lcd_s6d0139_timing[] = { +[MCU_LCD_REGISTER_TIMING] = { /* read/write register timing (ns) */ + .rcss = 15, + .rlpw = 250, + .rhpw = 250, + .wcss = 10, + .wlpw = 28, + .whpw = 28, + }, +[MCU_LCD_GRAM_TIMING] = { /* read/write gram timing (ns) */ + .rcss = 25, /* 25 ns */ + .rlpw = 70, + .rhpw = 70, + .wcss = 10, + .wlpw = 50, + .whpw = 50, + } +}; + +static struct info_mcu lcd_s6d0139_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 16, + .bpp = 16, /*RGB565*/ + .timing = lcd_s6d0139_timing, + .ops = NULL, +}; + +struct panel_spec lcd_s6d0139_spec = { + .width = 240, + .height = 320, + .type = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_s6d0139_info + }, + .ops = &lcd_s6d0139_operations, +}; + +struct panel_cfg lcd_s6d0139 = { + /* this panel may on both CS0/1 */ + .dev_id = SPRDFB_UNDEFINELCD_ID, + .lcd_id = 0x139, + .lcd_name = "lcd_s6d0139", + .panel = &lcd_s6d0139_spec, +}; + +static int __init lcd_s6d0139_init(void) +{ + return sprdfb_panel_register(&lcd_s6d0139); +} + +subsys_initcall(lcd_s6d0139_init); diff --git a/drivers/video/sprdfb/lcd/lcd_s6d77a1_pikeA_mipi.c b/drivers/video/sprdfb/lcd/lcd_s6d77a1_pikeA_mipi.c new file mode 100644 index 00000000..9b186b7a --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_s6d77a1_pikeA_mipi.c @@ -0,0 +1,330 @@ +/* drivers/video/sprdfb/lcd_s6d77a1_pikeA_mipi.c + * + * Support for s6d77a1 mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + +#define PIKEA_J1_NBW_PANEL + + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + +#ifndef PIKEA_J1_NBW_PANEL + {LCM_SEND(1),{0x11}}, + {LCM_SEND(5),{3,0,0xF0,0x5A,0x5A}}, + {LCM_SEND(5),{3,0,0xFC,0xA5,0xA5}}, + {LCM_SEND(5),{3,0,0xF1,0x5A,0xA5}}, + + {LCM_SEND(2),{0xB3, 0x01}}, + {LCM_SEND(2),{0xB5, 0x10}}, + {LCM_SEND(6),{4,0,0xBC,0x01,0x29,0x51}}, /* 141006 Battery detect function disabled */ + + /* MIPI SETTING */ + {LCM_SEND(5),{3,0,0xE3,0x24,0x2C}}, + + /* Display Inversion Off */ + {LCM_SEND(1),{0x21}}, + + /* Display Control */ + {LCM_SEND(10), {8,0,0xF2,0x11,0x04,0x08,0x10,0x10,0x82,0x54}}, + + /* power control 1 */ + {LCM_SEND(8),{6,0,0xF3,0x91,0x00,0x00,0x00,0x10}}, + + /* power control 2 */ + {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}}, + + /* power control 3 */ + {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}}, + + /* 9.4 */ + {LCM_SEND(20),{18,0,0xFE,0x00,0x02,0x01,0x39,0x60,0x40,0x21,0x00,0x4B,0x00,0x80,0x00,0xF0,0x00,0x00,0x00,0x02}}, + + /* ASG EQ Control */ + {LCM_SEND(13),{11,0,0xEE,0x00,0xA8,0x00,0xA8,0x00,0x00,0x00,0x00,0x00,0x00}}, + + {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}}, + + /* Panel Gate Control */ + {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}}, + + /* Source Control */ + {LCM_SEND(9),{7,0,0xF6,0x63,0x25,0x15,0x00,0x00,0x2A}}, + + /* Memory Data Access Control */ + {LCM_SEND(2),{0x36,0x10}}, + + /* Positive Gamma Control */ + {LCM_SEND(20),{18,0,0xFA,0x0C,0x36,0x11,0x17,0x0E,0x14,0x19,0x18,0x1A,0x21,0x23,0x22,0x22,0x21,0x22,0x22,0x29}}, + + /* Negative Gamma Control */ + {LCM_SEND(20),{18,0,0xFB,0x0C,0x36,0x12,0x17,0x0F,0x14,0x19,0x18,0x1A,0x21,0x24,0x22,0x23,0x21,0x22,0x22,0x29}}, + + /* display on */ + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(120)}, +#else + + {LCM_SEND(5), {3, 0x00, 0xF0, 0x5A, 0x5A} }, + {LCM_SEND(5), {3, 0x00, 0xFC, 0xA5, 0xA5} }, + {LCM_SEND(2), {0xB3, 0x01} }, + {LCM_SEND(2), {0xB5, 0x10} }, + {LCM_SEND(6), {4, 0x00, 0xBC, 0x00, 0x29, 0x51} }, + {LCM_SEND(5), {3, 0x00, 0xE3, 0x24, 0x2C} }, + {LCM_SEND(1), {0x21} }, + {LCM_SEND(10), {8, 0x00, 0xF2, 0x11, 0x04, 0x08, 0x10, 0x10, 0x82, 0x54} }, + {LCM_SEND(8), {6, 0x00, 0xF3, 0x91, 0x00, 0x00, 0x00, 0x10} }, + {LCM_SEND(46), {44, 0x00, 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} }, + {LCM_SEND(31), {29, 0x00, 0xF5, 0x5A, 0x62, 0xB9, 0x21, 0x35, 0x55, 0x06, 0x08, 0x00, 0x39, 0x00, 0x00, 0x0B, + 0x4B, 0xC4, 0xCB, 0x4B, 0x12, 0x12, 0x1A, 0x00, 0x10, 0xE0, 0xE2, 0x0E, 0x34, 0x34, 0x03} }, + {LCM_SEND(20), {18, 0x00, 0xFE, 0x00, 0x02, 0x01, 0x39, 0x60, 0x40, 0x21, 0x00, 0x4B, 0x00, 0x80, 0x00, 0xF0, + 0x00, 0x00, 0x00, 0x02} }, + {LCM_SEND(13), {11, 0x00, 0xEE, 0x86, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, + {LCM_SEND(24), {22, 0x00, 0xEF, 0x34, 0x12, 0x00, 0x00, 0x0A, 0x29, 0x08, 0x27, 0x21, 0x40, 0x10, 0x28, 0x02, + 0x21, 0x21, 0x03, 0x03, 0x40, 0x00, 0x00, 0x00} }, + {LCM_SEND(33), {31, 0x00, 0xF7, 0x02, 0x1B, 0x1A, 0x00, 0x01, 0x0D, 0x0D, 0x09, 0x09, 0x0C, 0x0C, 0x08, 0x08, + 0x04, 0x06, 0x02, 0x1B, 0x1A, 0x00, 0x01, 0x0F, 0x0F, 0x0B, 0x0B, 0x0E, 0x0E, 0x0A, 0x0A, 0x05, 0x07} }, + {LCM_SEND(9), {7, 0x00, 0xF6, 0x63, 0x25, 0x15, 0x00, 0x00, 0x2E} }, + {LCM_SEND(2), {0x36, 0x10} }, + {LCM_SEND(20), {18, 0x00, 0xFA, 0x00, 0x3F, 0x09, 0x10, 0x08, 0x0D, 0x12, 0x12, 0x12, 0x18, 0x1B, 0x1B, 0x1D, 0x1E, 0x21, 0x25, 0x2D} }, + {LCM_SEND(20), {18, 0x00, 0xFB, 0x00, 0x3F, 0x09, 0x11, 0x08, 0x0E, 0x13, 0x12, 0x13, 0x19, 0x1B, 0x1C, 0x1D, 0x1E, 0x21, 0x25, 0x2D} }, + {LCM_SEND(10), {8, 0x00, 0xFD, 0x00, 0x10, 0x11, 0x20, 0x21, 0x1F, 0xCC} }, + {LCM_SEND(5), {3, 0x00, 0xFC, 0x5A, 0x5A} }, +/* display on */ + {LCM_SEND(1),{0x11}}, + {LCM_SLEEP(120)}, + {LCM_SEND(1),{0x29}}, + {LCM_SLEEP(120)}, +#endif + +}; + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t s6d77a1_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel s6d77a1_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t s6d77a1_readid(struct panel_spec *self) + { + uint8_t j =0; + uint8_t read_data[4] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("lcd_s6d77a1_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x03; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0x04, 3, read_data); + LCD_PRINT("lcd_s6d77a1_mipi read id 0xda, 0xdb,0xdc is 0x%x,0x%x,0x%x!\n", + read_data[0], read_data[1], read_data[2]); + if ((0x55 == read_data[0]) && (0xB8 == read_data[1]) + && (0x10 == read_data[2])) { + LCD_PRINT("lcd_s6d77a1_mipi read id success!\n"); + return 0x55b810; + } + } + + mipi_eotp_set(0,0); + + LCD_PRINT("lcd_s6d77a1_mipi read id failed!\n"); + return 0; + +} + + +static int32_t s6d77a1_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel s6d77a1_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_s6d77a1_mipi_operations = { + .panel_init = s6d77a1_mipi_init, + .panel_readid = s6d77a1_readid, + .panel_enter_sleep = s6d77a1_enter_sleep, +}; + +static struct timing_rgb lcd_s6d77a1_mipi_timing = { + .hfp = 84, /* unit: pixel */ + .hbp = 90, + .hsync = 40, + .vfp = 16, /* unit: line */ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_s6d77a1_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_s6d77a1_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_s6d77a1_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .mipi = &lcd_s6d77a1_mipi_info + }, + .ops = &lcd_s6d77a1_mipi_operations, +}; +struct panel_cfg lcd_s6d77a1_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x55b810, + .lcd_name = "lcd_s6d77a1_mipi", + .panel = &lcd_s6d77a1_mipi_spec, +}; + + +static int __init lcd_s6d77a1_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_s6d77a1_mipi); +} + +subsys_initcall(lcd_s6d77a1_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_s6d7aa0x62_t8_mipi.c b/drivers/video/sprdfb/lcd/lcd_s6d7aa0x62_t8_mipi.c new file mode 100644 index 00000000..67f8df1b --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_s6d7aa0x62_t8_mipi.c @@ -0,0 +1,350 @@ +/* drivers/video/sprdfb/lcd_hx8389b_mipi.c
+ *
+ * Support for hx8389b mipi LCD device
+ *
+ * Copyright (C) 2015 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+#include <linux/gpio.h>
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 150
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+
+ //Initializing Sequence(1)
+ {LCM_SEND(5), {3, 0, 0xF0, 0x5A, 0x5A} },
+ {LCM_SEND(5), {3, 0, 0xF1, 0x5A, 0x5A} },
+ {LCM_SEND(5), {3, 0, 0xFC, 0xA5, 0xA5} },
+ {LCM_SEND(5), {3, 0, 0xD0, 0x00, 0x10} },
+
+ //Initializing Sequence(2)
+ {LCM_SEND(2), {0xB1, 0x12} },
+ {LCM_SEND(7), {5, 0, 0xB2,0x14, 0x22, 0x2F, 0x18} },
+ {LCM_SEND(2), {0xB3, 0x11} },
+ {LCM_SEND(12), {10, 0, 0xBA,0x03,0x19,0x19,0x11,0x03,0x05,0x18,0x18,0x77} },
+ {LCM_SEND(6), {4, 0, 0xBC,0x00, 0x4E, 0x0B} },
+ {LCM_SEND(6), {4, 0, 0xC0,0x80, 0x80, 0x30} },
+ {LCM_SEND(2), {0xC1, 0x03} },
+ {LCM_SEND(2), {0xC2, 0x00} },
+ {LCM_SEND(6), {4, 0, 0xC3, 0x40,0x00, 0x28} },
+ {LCM_SEND(8), {6, 0, 0xE1, 0x03,0x10, 0x1C, 0xA0, 0x10} },
+ {LCM_SEND(11), {9, 0, 0xEE, 0xA5,0x00,0x98,0x00,0xA5,0x00,0x98,0x00} },
+ {LCM_SEND(8), {6, 0, 0xF2, 0x02,0x10, 0x10, 0x44, 0x10} },
+ {LCM_SEND(13), {11, 0, 0xF3, 0x01,0x93,0x20,0x22,0x80,0x05,0x25,0x3C,0x26,0x00} },
+ {LCM_SEND(48), {46, 0, 0xF4, 0x02,0x02,0x10,0x26,0x10,0x02,0x03,0x03,0x03,0x10,0x16,0x03, \
+ 0x00,0x0C,0x0C,0x03,0x04,0x05,0x13,0x1E,0x09,0x0A,0x05,0x05,0x01,0x04,0x02, \
+ 0x61,0x74,0x75,0x72,0x83,0x80,0x80,0x00,0x00,0x01,0x01,0x28,0x04,0x03,0x28, \
+ 0x01,0xD1,0x32} },
+ {LCM_SEND(35), {33, 0, 0xF7,0x01,0x1B,0x08,0x0C,0x09,0x0D,0x01,0x01,0x01,0x04,0x06,0x01,0x01, \
+ 0x00,0x00,0x1A,0x01,0x1B,0x0A,0x0E,0x0B,0x0F,0x01,0x01,0x01,0x05,0x07,0x01,0x01,
+ 0x00,0x00,0x1A} },
+ {LCM_SEND(9), {7, 0, 0xF6, 0x60,0x25, 0x05, 0x00, 0x00, 0x00} },
+ {LCM_SEND(8), {6, 0, 0xFD, 0x16,0x10, 0x11, 0x23, 0x09} },
+ {LCM_SEND(9), {7, 0, 0xFE, 0x00,0x02, 0x03, 0x21, 0x80, 0x78} },
+ {LCM_SEND(20), {18, 0, 0xEF,0x34,0x12,0x98,0xBA,0x10,0x80,0x24,0x80,0x80,0x80,0x00,0x00,0x00, \
+ 0x44,0xA0,0x82,0x00} },
+ {LCM_SEND(16), {14, 0, 0xCD,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E} },
+ {LCM_SEND(16), {14, 0, 0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+ {LCM_SEND(2), {0x51, 0xFF} },
+ {LCM_SEND(2), {0x53, 0x2C} },
+ {LCM_SEND(2), {0x55, 0x01} },
+
+ // Initializing Sequence(3)
+ {LCM_SEND(20), {18, 0, 0xFA,0x08,0x3F,0x0D,0x12,0x07,0x0C,0x11,0x0F,0x11,0x18,0x1D,0x1E,0x21,\
+ 0x23,0x24,0x27,0x30,} },
+ {LCM_SEND(20), {18, 0, 0xF8,0x08,0x3F,0x0C,0x12,0x07,0x0C,0x10,0x0F,0x11,0x18,0x1D,0x1E,0x21,\
+ 0x23,0x23,0x26,0x2F} },
+
+ // Initializing Sequence(1-1)
+ {LCM_SEND(5), {3, 0, 0xF0, 0xA5, 0xA5} },
+ {LCM_SEND(5), {3, 0, 0xF1, 0xA5, 0xA5} },
+ {LCM_SEND(5), {3, 0, 0xFC, 0x5A, 0x5A} },
+
+ // power on
+ {LCM_SEND(1), {0x11} },
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1), {0x29} },
+ {LCM_SLEEP(20)},
+
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(1), {0x28}},
+ {LCM_SLEEP(150)}, //>150ms
+ {LCM_SEND(1), {0x10}},
+ {LCM_SLEEP(150)}, //>150ms
+};
+
+static LCM_Init_Code sleep_out[] = {
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},//>120ms
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(20)}, //>20ms
+};
+
+static int32_t s6d7aa0x62_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("kernel s6d7aa0x62_mipi_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(0,0);
+
+ return 0;
+}
+
+static uint32_t s6d7aa0x62_readid(struct panel_spec *self)
+{
+#if 0
+ uint32_t j =0;
+ uint8_t read_data[4] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ LCD_PRINT("lcd_s6d7aa0x62_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(0,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x03;
+ param[1] = 0x00;
+ mipi_force_write(0x37, param, 2);
+ read_rtn = mipi_force_read(0x04,3, &read_data[0]);
+ LCD_PRINT("lcd_s6d7aa0x62_mipi read id 0x04 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if(0x83 == read_data[0] && 0x94 == read_data[1] && 0x1A == read_data[2]){
+ LCD_PRINT("s6d7aa0x62 success!\n");
+ return 0xaa62;
+ }
+ }
+
+ mipi_eotp_set(0,0);
+
+ return 0;
+#endif
+ return 0x6262;
+}
+
+static uint32_t s6d7aa0x62_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_s6d7aa0x62_mipi read power mode!\n");
+ mipi_eotp_set(0,0);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ pr_debug("lcd_hx8389b mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ if((0x1c == read_data[0])){
+ //printk("lcd_hx8389b_mipi read power mode success!\n");
+ mipi_eotp_set(0,0);
+ return 0x1c;
+ }
+ }
+
+ printk("lcd_s6d7aa0x62 mipi read power mode fail!0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+ mipi_eotp_set(0,0);
+ return 0x0;
+}
+
+static int32_t s6d7aa0x62_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ pr_debug("s6d7aa0x62_check_esd!\n");
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+#endif
+ power_mode = s6d7aa0x62_readpowermode(self);
+ //power_mode = 0x0;
+#ifndef FB_CHECK_ESD_IN_VFP
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+#endif
+ if(power_mode == 0x1c){
+ pr_debug("s6d7aa0x62_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("s6d7aa0x62_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_s6d7aa0x62_mipi_operations = {
+ .panel_init = s6d7aa0x62_mipi_init,
+ .panel_readid = s6d7aa0x62_readid,
+ .panel_esd_check = s6d7aa0x62_check_esd,
+};
+
+static struct timing_rgb lcd_s6d7aa0x62_mipi_timing = {
+ .hfp = 104, /* unit: pixel */
+ .hbp = 154,
+ .hsync = 1,
+ .vfp = 16, /*unit: line*/
+ .vbp = 12,
+ .vsync = 1,
+};
+
+
+static struct info_mipi lcd_s6d7aa0x62_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 4,
+ .phy_feq = 481*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_s6d7aa0x62_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_s6d7aa0x62_mipi_spec = {
+ .width = 720,
+ .height = 1280,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_s6d7aa0x62_mipi_info
+ },
+ .ops = &lcd_s6d7aa0x62_mipi_operations,
+};
+
+struct panel_cfg lcd_s6d7aa0x62_mipi = {
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x6262,
+ .lcd_name = "lcd_s6d7aa0x62_mipi",
+ .panel = &lcd_s6d7aa0x62_mipi_spec,
+};
+
+static int __init lcd_s6d7aa0x62_mipi_init(void)
+{
+#if 0
+ if (gpio_request(152, "LCD_3V3")) {
+ printk("Failed ro request LCD_3V3 GPIO_%d \n",152);
+ return -ENODEV;
+ }
+ if (gpio_request(155, "BL_EN")) {
+ printk("Failed ro request BL_EN GPIO_%d \n",155);
+ return -ENODEV;
+ }
+ if (gpio_request(232, "CABC_EN0")) {
+ printk("Failed ro request CABC_EN0 GPIO_%d \n",232);
+ return -ENODEV;
+ }
+ if (gpio_request(233, "CABC_EN1")) {
+ printk("Failed ro request CABC_EN1 GPIO_%d \n",233);
+ return -ENODEV;
+ }
+ gpio_direction_output(152, 1);
+ gpio_direction_output(155, 1);
+ gpio_direction_output(232, 1);
+ gpio_direction_output(233, 1);
+#endif
+ return sprdfb_panel_register(&lcd_s6d7aa0x62_mipi);
+}
+
+subsys_initcall(lcd_s6d7aa0x62_mipi_init);
+
+
diff --git a/drivers/video/sprdfb/lcd/lcd_sc7798_rgb_spi.c b/drivers/video/sprdfb/lcd/lcd_sc7798_rgb_spi.c new file mode 100755 index 00000000..0b9d7a73 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_sc7798_rgb_spi.c @@ -0,0 +1,561 @@ +/* drivers/video/sc8810/lcd_hx8363_rgb_spi.c + * + * + * + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + + + + +#define sc7798_SpiWriteCmd(cmd) \ +{ \ + spi_send_cmd((cmd & 0xFF));\ +} + +#define sc7798_SpiWriteData(data)\ +{ \ + spi_send_data((data & 0xFF));\ +} +static int32_t sc7798_init(struct panel_spec *self) +{ + uint32_t test_data[8] = {0}; + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 480; + uint32_t bottom = 800; + uint32_t data = 0; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; + + + printk("sc7798_init\n"); + + sc7798_SpiWriteCmd(0xB9); + sc7798_SpiWriteData(0xF1); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x00); + + sc7798_SpiWriteCmd(0xBC); + sc7798_SpiWriteData(0x67); + + sc7798_SpiWriteCmd(0x3A); + sc7798_SpiWriteData(0x70); + + sc7798_SpiWriteCmd(0xB2); + sc7798_SpiWriteData(0x23); + + sc7798_SpiWriteCmd(0xB4); + sc7798_SpiWriteData(0x00); + + sc7798_SpiWriteCmd(0xB1); + sc7798_SpiWriteData(0x22); + sc7798_SpiWriteData(0x1B); + sc7798_SpiWriteData(0x1B); + sc7798_SpiWriteData(0xB7); + sc7798_SpiWriteData(0x22); + sc7798_SpiWriteData(0x02); + sc7798_SpiWriteData(0xA8); + + sc7798_SpiWriteCmd(0xC6); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0xFF); + + sc7798_SpiWriteCmd(0xCC); + sc7798_SpiWriteData(0x0C); + + sc7798_SpiWriteCmd(0xE3); + sc7798_SpiWriteData(0x02); + sc7798_SpiWriteData(0x02); + sc7798_SpiWriteData(0x02); + sc7798_SpiWriteData(0x02); + + + sc7798_SpiWriteCmd(0xB8); + sc7798_SpiWriteData(0x07); + sc7798_SpiWriteData(0x22); + + sc7798_SpiWriteCmd(0xB5); + sc7798_SpiWriteData(0x09); + sc7798_SpiWriteData(0x09); + + sc7798_SpiWriteCmd(0xC0); + sc7798_SpiWriteData(0x73); + sc7798_SpiWriteData(0x50); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x70); + + sc7798_SpiWriteCmd(0xB3); + sc7798_SpiWriteData(0x01); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x06); + sc7798_SpiWriteData(0x06); + sc7798_SpiWriteData(0x10); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x45); + sc7798_SpiWriteData(0x40); + + sc7798_SpiWriteCmd(0xB9); + sc7798_SpiWriteData(0xF1); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x00); + + sc7798_SpiWriteCmd(0xE9); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x03); + sc7798_SpiWriteData(0x2F); + sc7798_SpiWriteData(0x89); + sc7798_SpiWriteData(0x6A); + sc7798_SpiWriteData(0x12); + sc7798_SpiWriteData(0x31); + sc7798_SpiWriteData(0x23); + sc7798_SpiWriteData(0x48); + sc7798_SpiWriteData(0x0C); + sc7798_SpiWriteData(0x89); + sc7798_SpiWriteData(0x6A); + sc7798_SpiWriteData(0x47); + sc7798_SpiWriteData(0x02); + sc7798_SpiWriteData(0x04); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x20); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x40); + sc7798_SpiWriteData(0x28); + sc7798_SpiWriteData(0x69); + sc7798_SpiWriteData(0x48); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x80); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x51); + sc7798_SpiWriteData(0x38); + sc7798_SpiWriteData(0x79); + sc7798_SpiWriteData(0x58); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x81); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + + sc7798_SpiWriteCmd(0xEA); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x37); + sc7798_SpiWriteData(0x59); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x85); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x26); + sc7798_SpiWriteData(0x49); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x08); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x84); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0xFF); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x50); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + + sc7798_SpiWriteCmd(0xE0); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x04); + sc7798_SpiWriteData(0x04); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x2B); + sc7798_SpiWriteData(0x05); + sc7798_SpiWriteData(0x0C); + sc7798_SpiWriteData(0x11); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x15); + sc7798_SpiWriteData(0x19); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x04); + sc7798_SpiWriteData(0x04); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x2C); + sc7798_SpiWriteData(0x05); + sc7798_SpiWriteData(0x0C); + sc7798_SpiWriteData(0x12); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x18); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x17); + sc7798_SpiWriteData(0x16); + sc7798_SpiWriteData(0x19); + +#if 0 + sc7798_SpiWriteCmd(0xC1); + sc7798_SpiWriteData(0x01); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x03); + sc7798_SpiWriteData(0x0B); + sc7798_SpiWriteData(0x17); + sc7798_SpiWriteData(0x20); + sc7798_SpiWriteData(0x26); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0x36); + sc7798_SpiWriteData(0x3F); + sc7798_SpiWriteData(0x48); + sc7798_SpiWriteData(0x50); + sc7798_SpiWriteData(0x58); + sc7798_SpiWriteData(0x5F); + sc7798_SpiWriteData(0x68); + sc7798_SpiWriteData(0x71); + sc7798_SpiWriteData(0x79); + sc7798_SpiWriteData(0x82); + sc7798_SpiWriteData(0x89); + sc7798_SpiWriteData(0x91); + sc7798_SpiWriteData(0x99); + sc7798_SpiWriteData(0xA1); + sc7798_SpiWriteData(0xA9); + sc7798_SpiWriteData(0xB0); + sc7798_SpiWriteData(0xB8); + sc7798_SpiWriteData(0xC0); + sc7798_SpiWriteData(0xC8); + sc7798_SpiWriteData(0xD0); + sc7798_SpiWriteData(0xD6); + sc7798_SpiWriteData(0xDC); + sc7798_SpiWriteData(0xE4); + sc7798_SpiWriteData(0xED); + sc7798_SpiWriteData(0xF7); + sc7798_SpiWriteData(0xFF); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0xC0); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x80); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0xE8); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x03); + sc7798_SpiWriteData(0x0B); + sc7798_SpiWriteData(0x17); + sc7798_SpiWriteData(0x20); + sc7798_SpiWriteData(0x27); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0x37); + sc7798_SpiWriteData(0x40); + sc7798_SpiWriteData(0x48); + sc7798_SpiWriteData(0x50); + sc7798_SpiWriteData(0x58); + sc7798_SpiWriteData(0x5F); + sc7798_SpiWriteData(0x67); + sc7798_SpiWriteData(0x70); + sc7798_SpiWriteData(0x78); + sc7798_SpiWriteData(0x80); + sc7798_SpiWriteData(0x88); + sc7798_SpiWriteData(0x90); + sc7798_SpiWriteData(0x98); + sc7798_SpiWriteData(0xA0); + sc7798_SpiWriteData(0xA8); + sc7798_SpiWriteData(0xAF); + sc7798_SpiWriteData(0xB7); + sc7798_SpiWriteData(0xBF); + sc7798_SpiWriteData(0xC7); + sc7798_SpiWriteData(0xCF); + sc7798_SpiWriteData(0xD5); + sc7798_SpiWriteData(0xDC); + sc7798_SpiWriteData(0xE4); + sc7798_SpiWriteData(0xED); + sc7798_SpiWriteData(0xF7); + sc7798_SpiWriteData(0xFF); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0xC0); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x80); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0xE8); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x03); + sc7798_SpiWriteData(0x0D); + sc7798_SpiWriteData(0x19); + sc7798_SpiWriteData(0x23); + sc7798_SpiWriteData(0x29); + sc7798_SpiWriteData(0x31); + sc7798_SpiWriteData(0x38); + sc7798_SpiWriteData(0x41); + sc7798_SpiWriteData(0x48); + sc7798_SpiWriteData(0x4F); + sc7798_SpiWriteData(0x57); + sc7798_SpiWriteData(0x5D); + sc7798_SpiWriteData(0x65); + sc7798_SpiWriteData(0x6C); + sc7798_SpiWriteData(0x74); + sc7798_SpiWriteData(0x7B); + sc7798_SpiWriteData(0x84); + sc7798_SpiWriteData(0x8B); + sc7798_SpiWriteData(0x94); + sc7798_SpiWriteData(0x9B); + sc7798_SpiWriteData(0xA4); + sc7798_SpiWriteData(0xAA); + sc7798_SpiWriteData(0xB4); + sc7798_SpiWriteData(0xB9); + sc7798_SpiWriteData(0xC3); + sc7798_SpiWriteData(0xCC); + sc7798_SpiWriteData(0xD6); + sc7798_SpiWriteData(0xDC); + sc7798_SpiWriteData(0xE4); + sc7798_SpiWriteData(0xED); + sc7798_SpiWriteData(0xF7); + sc7798_SpiWriteData(0xFF); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0x00); + sc7798_SpiWriteData(0xC0); + sc7798_SpiWriteData(0x0A); + sc7798_SpiWriteData(0x80); + sc7798_SpiWriteData(0x30); + sc7798_SpiWriteData(0xE8); + sc7798_SpiWriteData(0x00); +#endif + + sc7798_SpiWriteCmd(0x11); + mdelay(120); + sc7798_SpiWriteCmd(0x29); +} + + +#if 1 +static int32_t sc7798_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + + if(is_sleep==1){ + //Sleep In + sc7798_SpiWriteCmd(0x28); + mdelay(120); + sc7798_SpiWriteCmd(0x10); + mdelay(10); + }else{ + //Sleep Out + sc7798_SpiWriteCmd(0x11); + mdelay(120); + sc7798_SpiWriteCmd(0x29); + mdelay(10); + } + + return 0; +} + + + + +static int32_t sc7798_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + uint32_t *test_data[4] = {0}; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; +#if 0 + + printk("zxdbg add -hx8363_set_window: %d, %d, %d, %d\n",left, top, right, bottom); + + sc7798_SpiWriteCmd(0x2A00); + sc7798_SpiWriteData((left>>8));// set left address + sc7798_SpiWriteData((left&0xff)); + sc7798_SpiWriteData((right>>8));// set right address + sc7798_SpiWriteData((right&0xff)); + + sc7798_SpiWriteCmd(0x2B00); + sc7798_SpiWriteData((top>>8));// set left address + sc7798_SpiWriteData((top&0xff)); + sc7798_SpiWriteData((bottom>>8));// set bottom address + sc7798_SpiWriteData((bottom&0xff)); + +// HX8363_SpiWriteCmd(0x2C00); + + sc7798_SpiWriteCmd(0x2A00); + spi_read(test_data); + spi_read(test_data+1); + sc7798_SpiWriteCmd(0x2B00); + spi_read(test_data+2); + spi_read(test_data+3); +#endif +// printk("zxdbg add -hx8363_read read: %x, %x, %x, %x\n",test_data[0], test_data[1], test_data[2], test_data[3]); + + return 0; +} + +static int32_t sc7798_invalidate(struct panel_spec *self) +{ +// printk("hx8363_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width - 1, self->height - 1); +} + + + +static int32_t sc7798_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ +// printk("hx8363_invalidate_rect \n"); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + + +#endif + + +static int32_t sc7798_read_id(struct panel_spec *self) +{ +#if 0 + int32_t id = 0x62; + spi_send_cmd_t spi_send_cmd = self->info.rgb->bus_info.spi->ops->spi_send_cmd; + spi_send_data_t spi_send_data = self->info.rgb->bus_info.spi->ops->spi_send_data; + spi_read_t spi_read = self->info.rgb->bus_info.spi->ops->spi_read; +/* + printk("sprdfb hx8363_read_id \n"); + HX8363_SpiWriteCmd(0xB9); // SET password + HX8363_SpiWriteData(0xFF); // + HX8363_SpiWriteData(0x83); // + HX8363_SpiWriteData(0x63); // + + HX8363_SpiWriteCmd(0xFE); // SET SPI READ INDEX + HX8363_SpiWriteData(0xF4); // GETHXID + HX8363_SpiWriteCmd(0xFF); // GET SPI READ + + spi_read(&id); +*/ + id &= 0xff; + printk(" hx8363_read_id kernel id = %x\n",id); +// return id; +#endif + return 0x7798; +} + +static struct panel_operations lcd_sc7798_rgb_spi_operations = { + .panel_init = sc7798_init, + .panel_set_window = sc7798_set_window, + .panel_invalidate_rect= sc7798_invalidate_rect, + .panel_invalidate = sc7798_invalidate, + .panel_enter_sleep = sc7798_enter_sleep, + .panel_readid = sc7798_read_id +}; + +static struct timing_rgb lcd_sc7798_rgb_timing = { + .hfp = 90, + .hbp = 70, + .hsync = 60, + .vfp = 8, + .vbp = 12, + .vsync = 4, + +}; + +static struct spi_info lcd_sc7798_rgb_spi_info = { + .ops = NULL, +}; + +static struct info_rgb lcd_sc7798_rgb_info = { + .cmd_bus_mode = SPRDFB_RGB_BUS_TYPE_SPI, + .video_bus_width = 24, /*18,16*/ + .h_sync_pol = SPRDFB_POLARITY_NEG, + .v_sync_pol = SPRDFB_POLARITY_NEG, + .de_pol = SPRDFB_POLARITY_POS, + .timing = &lcd_sc7798_rgb_timing, + .bus_info = { + .spi = &lcd_sc7798_rgb_spi_info, + } +}; + +struct panel_spec lcd_panel_sc7798_rgb_spi_spec = { + + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_RGB, + .direction = LCD_DIRECT_NORMAL, + .is_clean_lcd = true, + .info = { + .rgb = &lcd_sc7798_rgb_info + }, + .ops = &lcd_sc7798_rgb_spi_operations, +}; + +struct panel_cfg lcd_sc7798_rgb_spi_spec = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x7798, + .lcd_name = "lcd_sc7798_rgb_spi", + .panel = &lcd_panel_sc7798_rgb_spi_spec, +}; + +static int __init lcd_sc7798_rgb_spi_init(void) +{ + return sprdfb_panel_register(&lcd_sc7798_rgb_spi_spec); + +} + +subsys_initcall(lcd_sc7798_rgb_spi_init); diff --git a/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi.c b/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi.c new file mode 100755 index 00000000..e377c3c5 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi.c @@ -0,0 +1,261 @@ +/* drivers/video/sprdfb/lcd_sc7798d_mipi.c + * + * Support for sc7798d mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + {LCM_SEND(6), {4, 0, 0xB9, 0xF1, 0x08, 0x00} }, + /*{LCM_SLEEP(10)},*/ + {LCM_SEND(10), {8, 0, 0xB1, 0x31, 0x0C, 0x0C, 0xA7, 0x33, 0x01, 0xB7} }, + {LCM_SEND(6), {4, 0, 0xC6, 0x00, 0x00, 0xFD} }, + {LCM_SEND(7), {5, 0, 0xE3, 0x03, 0x03, 0x03, 0x03} }, + {LCM_SEND(5), {3, 0, 0xB8, 0x06, 0x22} }, + {LCM_SLEEP(10)}, + {LCM_SEND(21), {19, 0, 0xBA, 0x31, 0x00, 0x44, 0x25, 0x91, 0x0A, 0x00, 0x00, 0xC2, 0x34, 0x00, 0x00, 0x04, 0x02, 0x1D, + 0xB9, 0xEE, 0x40} }, + {LCM_SEND(11), {9, 0, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0A, 0x25, 0x20} }, + {LCM_SEND(2), {0xB4, 0x00} }, + {LCM_SEND(2), {0xCC, 0x0E} }, + {LCM_SEND(2), {0xBC, 0x67} }, + {LCM_SEND(2), {0xB2, 0x03} }, + {LCM_SEND(8), {6, 0, 0xC0, 0x73, 0x50, 0x00, 0x08, 0x70} }, + {LCM_SEND(54), {52, 0, 0xE9, 0x00, 0x00, 0x06, 0x00, 0x00, 0x6E, 0x29, 0x12, 0x30, 0x00, 0x48, 0x08, 0x6E, 0x29, 0x47, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x89, 0x98, 0x33, 0x11, 0x77, 0x55, + 0x13, 0x00, 0x00, 0x89, 0x98, 0x22, 0x00, 0x66, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} }, + {LCM_SEND(39), {37, 0, 0xEA, 0x00, 0x00, 0x98, 0x98, 0x44, 0x66, 0x00, 0x22, 0x20, 0x00, 0x00, 0x98, 0x98, 0x55, 0x77, + 0x11, 0x33, 0x31, 0x30, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} }, + {LCM_SEND(37), {35, 0, 0xE0, 0x01, 0x09, 0x0D, 0x2E, 0x36, 0x3F, 0x10, 0x31, 0x07, 0x0D, 0x11, 0x15, 0x13, 0x16, 0x15, + 0x32, 0x38, 0x01, 0x05, 0x05, 0x30, 0x35, 0x3F, 0x0E, 0x30, 0x04, 0x09, 0x0A, 0x0D, 0x12, + 0x0D, 0x0F, 0x2C, 0x35} }, + {LCM_SEND(1), {0x11} }, + {LCM_SLEEP(120)}, + {LCM_SEND(1), {0x29} }, + {LCM_SLEEP(20)}, + +}; + + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t sc7798d_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel sc7798d_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t sc7798d_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_sc7798d_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0xF0 == read_data[2])) + { + printk("lcd_sc7798d_mipi read id success!\n"); + return 0x55b8f0; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_sc7798d_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t sc7798d_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel sc7798d_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_sc7798d_mipi_operations = { + .panel_init = sc7798d_mipi_init, + .panel_readid = sc7798d_readid, + .panel_enter_sleep = sc7798d_enter_sleep, +}; + +static struct timing_rgb lcd_sc7798d_mipi_timing = { + .hfp = 145, /* unit: pixel */ + .hbp = 90, + .hsync = 70, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_sc7798d_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_sc7798d_mipi_timing, + .ops = NULL, +}; +struct panel_spec lcd_sc7798d_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_sc7798d_mipi_info + }, + .ops = &lcd_sc7798d_mipi_operations, +}; +struct panel_cfg lcd_sc7798d_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x55b8f0, + .lcd_name = "lcd_sc7798d_mipi", + .panel = &lcd_sc7798d_mipi_spec, +}; + +//temp code +static int __init lcd_sc7798d_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_sc7798d_mipi); +} + +subsys_initcall(lcd_sc7798d_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi_sharkls_z3lte.c b/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi_sharkls_z3lte.c new file mode 100755 index 00000000..e377c3c5 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_sd7798d_mipi_sharkls_z3lte.c @@ -0,0 +1,261 @@ +/* drivers/video/sprdfb/lcd_sc7798d_mipi.c + * + * Support for sc7798d mipi LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> + +#define LCD_DEBUG +#ifdef LCD_DEBUG +#define LCD_PRINT printk +#else +#define LCD_PRINT(...) +#endif + +#define MAX_DATA 150 + + +typedef struct LCM_Init_Code_tag { + unsigned int tag; + unsigned char data[MAX_DATA]; +}LCM_Init_Code; + +typedef struct LCM_force_cmd_code_tag{ + unsigned int datatype; + LCM_Init_Code real_cmd_code; +}LCM_Force_Cmd_Code; + +#define LCM_TAG_SHIFT 24 +#define LCM_TAG_MASK ((1 << 24) -1) +#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len) +#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms) +//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0])) + +#define LCM_TAG_SEND (1<< 0) +#define LCM_TAG_SLEEP (1 << 1) + +static LCM_Init_Code init_data[] = { + {LCM_SEND(6), {4, 0, 0xB9, 0xF1, 0x08, 0x00} }, + /*{LCM_SLEEP(10)},*/ + {LCM_SEND(10), {8, 0, 0xB1, 0x31, 0x0C, 0x0C, 0xA7, 0x33, 0x01, 0xB7} }, + {LCM_SEND(6), {4, 0, 0xC6, 0x00, 0x00, 0xFD} }, + {LCM_SEND(7), {5, 0, 0xE3, 0x03, 0x03, 0x03, 0x03} }, + {LCM_SEND(5), {3, 0, 0xB8, 0x06, 0x22} }, + {LCM_SLEEP(10)}, + {LCM_SEND(21), {19, 0, 0xBA, 0x31, 0x00, 0x44, 0x25, 0x91, 0x0A, 0x00, 0x00, 0xC2, 0x34, 0x00, 0x00, 0x04, 0x02, 0x1D, + 0xB9, 0xEE, 0x40} }, + {LCM_SEND(11), {9, 0, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0A, 0x25, 0x20} }, + {LCM_SEND(2), {0xB4, 0x00} }, + {LCM_SEND(2), {0xCC, 0x0E} }, + {LCM_SEND(2), {0xBC, 0x67} }, + {LCM_SEND(2), {0xB2, 0x03} }, + {LCM_SEND(8), {6, 0, 0xC0, 0x73, 0x50, 0x00, 0x08, 0x70} }, + {LCM_SEND(54), {52, 0, 0xE9, 0x00, 0x00, 0x06, 0x00, 0x00, 0x6E, 0x29, 0x12, 0x30, 0x00, 0x48, 0x08, 0x6E, 0x29, 0x47, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x89, 0x98, 0x33, 0x11, 0x77, 0x55, + 0x13, 0x00, 0x00, 0x89, 0x98, 0x22, 0x00, 0x66, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} }, + {LCM_SEND(39), {37, 0, 0xEA, 0x00, 0x00, 0x98, 0x98, 0x44, 0x66, 0x00, 0x22, 0x20, 0x00, 0x00, 0x98, 0x98, 0x55, 0x77, + 0x11, 0x33, 0x31, 0x30, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} }, + {LCM_SEND(37), {35, 0, 0xE0, 0x01, 0x09, 0x0D, 0x2E, 0x36, 0x3F, 0x10, 0x31, 0x07, 0x0D, 0x11, 0x15, 0x13, 0x16, 0x15, + 0x32, 0x38, 0x01, 0x05, 0x05, 0x30, 0x35, 0x3F, 0x0E, 0x30, 0x04, 0x09, 0x0A, 0x0D, 0x12, + 0x0D, 0x0F, 0x2C, 0x35} }, + {LCM_SEND(1), {0x11} }, + {LCM_SLEEP(120)}, + {LCM_SEND(1), {0x29} }, + {LCM_SLEEP(20)}, + +}; + + +static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}}; + +static LCM_Init_Code sleep_in[] = { + {LCM_SEND(1), {0x28}}, + {LCM_SLEEP(150)}, //>150ms + {LCM_SEND(1), {0x10}}, + {LCM_SLEEP(150)}, //>150ms +}; + +static LCM_Init_Code sleep_out[] = { + {LCM_SEND(1), {0x11}}, + {LCM_SLEEP(120)},//>120ms + {LCM_SEND(1), {0x29}}, + {LCM_SLEEP(20)}, //>20ms +}; +static int32_t sc7798d_mipi_init(struct panel_spec *self) +{ + int32_t i = 0; + LCM_Init_Code *init = init_data; + unsigned int tag; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel sc7798d_mipi_init\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i < ARRAY_SIZE(init_data); i++){ + tag = (init->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK)); + udelay(20); + }else if(tag & LCM_TAG_SLEEP){ + msleep(init->tag & LCM_TAG_MASK); + } + init++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static uint32_t sc7798d_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[3] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + LCD_PRINT("kernel lcd_sc7798d_mipi read id!\n"); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x37, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + + if((0x55 == read_data[0])&&(0xB8 == read_data[1])&&(0xF0 == read_data[2])) + { + printk("lcd_sc7798d_mipi read id success!\n"); + return 0x55b8f0; + } + } + mipi_eotp_set(0,0); + LCD_PRINT("lcd_sc7798d_mipi read id fail! 0xda,0xdb,0xdc is 0x%x,0x%x,0x%x!\n",read_data[0],read_data[1],read_data[2]); + return 0; +} + + +static int32_t sc7798d_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + int32_t i = 0; + LCM_Init_Code *sleep_in_out = NULL; + unsigned int tag; + int32_t size = 0; + + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + printk("kernel sc7798d_enter_sleep, is_sleep = %d\n", is_sleep); + + if(is_sleep){ + sleep_in_out = sleep_in; + size = ARRAY_SIZE(sleep_in); + }else{ + sleep_in_out = sleep_out; + size = ARRAY_SIZE(sleep_out); + } + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(i = 0; i <size ; i++){ + tag = (sleep_in_out->tag >>24); + if(tag & LCM_TAG_SEND){ + mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK)); + }else if(tag & LCM_TAG_SLEEP){ + msleep(sleep_in_out->tag & LCM_TAG_MASK); + } + sleep_in_out++; + } + mipi_eotp_set(0,0); + + return 0; +} + +static struct panel_operations lcd_sc7798d_mipi_operations = { + .panel_init = sc7798d_mipi_init, + .panel_readid = sc7798d_readid, + .panel_enter_sleep = sc7798d_enter_sleep, +}; + +static struct timing_rgb lcd_sc7798d_mipi_timing = { + .hfp = 145, /* unit: pixel */ + .hbp = 90, + .hsync = 70, + .vfp = 10, /*unit: line*/ + .vbp = 12, + .vsync = 4, +}; + + +static struct info_mipi lcd_sc7798d_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 2, + .phy_feq =481*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_sc7798d_mipi_timing, + .ops = NULL, +}; +struct panel_spec lcd_sc7798d_mipi_spec = { + .width = 480, + .height = 800, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mipi = &lcd_sc7798d_mipi_info + }, + .ops = &lcd_sc7798d_mipi_operations, +}; +struct panel_cfg lcd_sc7798d_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x55b8f0, + .lcd_name = "lcd_sc7798d_mipi", + .panel = &lcd_sc7798d_mipi_spec, +}; + +//temp code +static int __init lcd_sc7798d_mipi_init(void) +{ + return sprdfb_panel_register(&lcd_sc7798d_mipi); +} + +subsys_initcall(lcd_sc7798d_mipi_init); + diff --git a/drivers/video/sprdfb/lcd/lcd_ssd2075_mipi.c b/drivers/video/sprdfb/lcd/lcd_ssd2075_mipi.c new file mode 100644 index 00000000..b2281be3 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_ssd2075_mipi.c @@ -0,0 +1,375 @@ +/* drivers/video/sprdfb/lcd_ssd2075_mipi.c
+ *
+ * Support for ssd2075 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+//#define printk printf
+
+#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+ {LCM_SEND(2),{0xE1,0x93}},
+ {LCM_SEND(2),{0xB3,0x00}},
+ //5inchGIP
+ {LCM_SEND(7),{5,0,0xB6,0x16,0x0F,0x00,0x77}}, //0x00
+ {LCM_SEND(11),{9,0,0xB8,0x00,0x06,0x08,0x00,0x07,0x09,0x23,0x04}},
+ {LCM_SEND(9),{7,0,0xB9,0x04,0x08,0x22,0xFF,0xFF,0x0F}},
+ {LCM_SEND(11),{9,0,0xBA,0x0E,0x0E,0x10,0x10,0x0A,0x0A,0x0C,0x0C}},
+ {LCM_SEND(11),{9,0,0xBB,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1}},
+ {LCM_SEND(11),{9,0,0xBC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(11),{9,0,0xBD,0x0F,0x0F,0x11,0x11,0x0B,0x0B,0x0D,0x0D}},
+ {LCM_SEND(11),{9,0,0xBE,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1,0xA1}},
+ {LCM_SEND(11),{9,0,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {LCM_SEND(6),{4,0,0xB1,0x06,0x44,0x10}},
+ {LCM_SEND(8),{6,0,0xE0,0x11,0x02,0x04,0x00,0x01}},
+
+ //Gamma2.2
+ #if 1
+ {LCM_SEND(9),{7,0,0xD0,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xD1,0x1A,0x37,0x29,0x1B,0x08}},
+ {LCM_SEND(9),{7,0,0xD2,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xD3,0x1A,0x37,0x29,0x1B,0x08}},
+ {LCM_SEND(9),{7,0,0xD4,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xD5,0x1A,0x37,0x29,0x1B,0x08}},
+ {LCM_SEND(9),{7,0,0xD6,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xD7,0x1A,0x37,0x29,0x1B,0x08}},
+ {LCM_SEND(9),{7,0,0xD8,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xD9,0x1A,0x37,0x29,0x1B,0x08}},
+ {LCM_SEND(9),{7,0,0xDA,0x00,0x00,0x0E,0x0F,0x14,0x20}},
+ {LCM_SEND(8),{6,0,0xDB,0x1A,0x37,0x29,0x1B,0x08}},
+ #else
+ {LCM_SEND(9),{7,0,0xD0,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xD1,0x2D,0x27,0x1A,0x1B,0x0A}},
+ {LCM_SEND(9),{7,0,0xD2,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xD3,0x2D,0x27,0x1A,0x1B,0x0A}},
+ {LCM_SEND(9),{7,0,0xD4,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xD5,0x26,0x2B,0x23,0x1B,0x0A}},
+ {LCM_SEND(9),{7,0,0xD6,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xD7,0x2D,0x27,0x1A,0x1B,0x0A}},
+ {LCM_SEND(9),{7,0,0xD8,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xD9,0x2D,0x27,0x1A,0x1B,0x0A}},
+ {LCM_SEND(9),{7,0,0xDA,0x00,0x00,0x1E,0x27,0x2D,0x35}},
+ {LCM_SEND(8),{6,0,0xDB,0x2D,0x27,0x1A,0x1B,0x0A}},
+ #endif
+ {LCM_SEND(7),{5,0,0x70,0xD8,0x00,0xFF,0x80}},
+ {LCM_SEND(2),{0xFF,0x01}},
+
+ {LCM_SEND(5),{3,0,0xC6,0xCC,0x33}},//77->CC
+ {LCM_SEND(5),{3,0,0xDE,0x9D,0x30}},
+ {LCM_SEND(2),{0x14,0x00}},
+
+ {LCM_SEND(2),{0xE9,0x07}},
+ {LCM_SEND(5),{3,0,0xED,0x60,0x10}},
+ {LCM_SEND(2),{0xEC,0x12}},
+ {LCM_SEND(7),{5,0,0xCD,0x77,0x7B,0x34,0x08}},
+ {LCM_SEND(10),{8,0,0xC3,0x03,0x0D,0x34,0x05,0x01,0x44,0x54}},
+ {LCM_SEND(8),{6,0,0xC4,0x02,0x03,0x3D,0x3D,0x5A}}, // Vcom
+ {LCM_SEND(6),{4,0,0xCB,0xDF,0x80,0x00}},
+ {LCM_SEND(6),{4,0,0xEA,0x15,0x28,0x00}},
+ {LCM_SEND(7),{5,0,0xF0,0x38,0x00,0x00,0x00}},
+ {LCM_SEND(6),{4,0,0xC9,0x60,0x00,0x82}},
+ {LCM_SEND(11),{9,0,0xB5,0x00,0x05,0x05,0x1E,0x04,0x40,0x20,0xFC}},
+ {LCM_SEND(2),{0x36,0x0B}},//08->0B rotate 180
+ {LCM_SEND(2),{0x3A,0x70}},
+ {LCM_SEND(1),{0x11}},
+ {LCM_SLEEP(120)},
+ {LCM_SEND(1),{0x29}},
+};
+
+//static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+//static LCM_Init_Code sleep_in = {LCM_SEND(1), {0x10}};
+
+//static LCM_Init_Code sleep_out = {LCM_SEND(1), {0x11}};
+static LCM_Init_Code sleep_in[] = {
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(10)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(120)},
+{LCM_SEND(2), {0x4f, 0x01}},
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static int32_t ssd2075_mipi_init(struct panel_spec *self)
+{
+ int32_t i = 0;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_ssd2075_init\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((init->tag & LCM_TAG_MASK));
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t ssd2075_readid(struct panel_spec *self)
+{
+ int32_t j =0;
+ uint8_t read_data[10] = {0};
+ int32_t read_rtn = 0;
+ uint8_t param[2] = {0};
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_ssd2075_mipi read id!\n");
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ param[0] = 0x0a;
+ param[1] = 0x00;
+ mipi_force_write(0x37, param, 2);
+ read_rtn = mipi_force_read(0xA1,10,(uint8_t *)read_data);
+ printk("lcd_ssd2075_mipi read id 0xA1 value is 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x!\n", read_data[0], read_data[1], \
+ read_data[2], read_data[3],read_data[4], read_data[5],read_data[6], read_data[7],read_data[8], read_data[9]);
+
+ if((0x20 == read_data[0])&&(0x75 == read_data[1])){
+ printk("lcd_ssd2075_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x2075;
+ }
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static int32_t ssd2075_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i = 0;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "ssd2075_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t ssd2075_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+// pr_debug("lcd_ssd2075_mipi read power mode!\n");
+
+ mipi_eotp_set(0,1);
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ msleep((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0xF5, 3,(uint8_t *)read_data);
+// printk("lcd_ssd2075 mipi read power mode 0xF5 value r[0]=0x%x,r[1]=0x%x,r[2]=0x%x! , read result(%d)\n", read_data[0],read_data[1],read_data[2],read_rtn);
+ if((0x0 == read_data[0]) && (0x0 == read_data[1]) && (0x0 == read_data[2]) && (0 == read_rtn)){
+ mipi_eotp_set(1,1);
+// pr_debug("lcd_ssd2075_mipi read power mode success!\n");
+ return 0xF5;
+ }
+ }
+ mipi_eotp_set(1,1);
+ printk("lcd_ssd2075 ssd2075_readpowermode fail! 0xF5 value r[0]=0x%x,r[1]=0x%x,r[2]=0x%x! , read result(%d)\n", read_data[0],\
+ read_data[1],read_data[2],read_rtn);
+ return 0x0;
+}
+
+static int32_t ssd2075_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+// pr_debug("ssd2075_check_esd!\n");
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = ssd2075_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0xF5){
+// pr_debug("ssd2075_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("ssd2075_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+static struct panel_operations lcd_ssd2075_mipi_operations = {
+ .panel_init = ssd2075_mipi_init,
+ .panel_readid = ssd2075_readid,
+ .panel_enter_sleep = ssd2075_enter_sleep,
+ .panel_esd_check = ssd2075_check_esd,
+};
+
+static struct timing_rgb lcd_ssd2075_mipi_timing = {
+ .hfp =50,
+ .hbp = 36,
+ .hsync =16,
+ .vfp = 12,
+ .vbp = 14,
+ .vsync = 2,
+};
+
+
+static struct info_mipi lcd_ssd2075_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 4,
+ .phy_feq =500*1000,
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_ssd2075_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_ssd2075_mipi_spec = {
+ .width = 720,
+ .height = 1280,
+ .fps = 60,
+ .reset_timing = {20,20,120},
+ .suspend_mode = SEND_SLEEP_CMD,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mipi = &lcd_ssd2075_mipi_info
+ },
+ .ops = &lcd_ssd2075_mipi_operations,
+};
+struct panel_cfg lcd_ssd2075_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x2075,
+ .lcd_name = "lcd_ssd2075_mipi",
+ .panel = &lcd_ssd2075_mipi_spec,
+};
+
+static int __init lcd_ssd2075_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_ssd2075_mipi);
+}
+
+subsys_initcall(lcd_ssd2075_mipi_init);
+
diff --git a/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c b/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c new file mode 100644 index 00000000..f9538e90 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c @@ -0,0 +1,336 @@ +/* drivers/video/sprdfb/lcd_st7789v.c + * + * Support for st7789v LCD device + * + * Copyright (C) 2010 Spreadtrum + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" + +#define ST7789V_BUS_WIDTH_8BIT // bus_width = 8 + +static int32_t st7789v_init(struct panel_spec *self) + { + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("st7789v_init\n"); + //Power setting sequence + send_cmd(0x11); + mdelay(120); + +#if defined(ST7789V_BUS_WIDTH_8BIT) + send_cmd(0xDF); + send_data(0x5A69); + send_data(0x0201); + + send_cmd(0x36); + send_data(0x0000); + + send_cmd(0x3a); + send_data(0x0500); + + send_cmd(0x35); + send_data(0x0000); + + send_cmd(0xd2); + send_data(0x4c00); + + send_cmd(0xb2); + send_data(0x0404); + send_data(0x0033); + send_data(0x3300); + + send_cmd(0xC6); + send_data(0x0A00); + + send_cmd(0xb8); + send_data(0x2A2B); + send_data(0x0575); + + send_cmd(0xb7); + send_data(0x7500); + + send_cmd(0xbb); + send_data(0x1B00); + + send_cmd(0xC2); + send_data(0x0100); + + send_cmd(0xC3); + send_data(0x0b00); + + send_cmd(0xC4); + send_data(0x2000); + + send_cmd(0xd0); + send_data(0xa4a1); + + send_cmd(0xE8); + send_data(0x8300); + + send_cmd(0xE9); + send_data(0x0909); + send_data(0x0500); + + send_cmd(0xC0); + send_data(0x2500); + + send_cmd(0xb0); + send_data(0x00d0); + + send_cmd(0xE0); + send_data(0xd00E); + send_data(0x1810); + send_data(0x0E2A); + send_data(0x3E54); + send_data(0x4C2B); + send_data(0x1716); + send_data(0x1D21); + + send_cmd(0XE1); + send_data(0xd00E); + send_data(0x1710); + send_data(0x0E29); + send_data(0x3C44); + send_data(0x4D2C); + send_data(0x1615); + send_data(0x1E22); + + send_cmd(0x29); +#else // 16/18/24bit + send_cmd(0xB7); send_data(0x35); + send_cmd(0xBB); send_data(0x1A); + send_cmd(0xC2); send_data(0x01); + send_cmd(0xC3); send_data(0x0B); + send_cmd(0xC4); send_data(0x20); + send_cmd(0xD0); send_data(0xA4);send_data(0xA1); + send_cmd(0xE8); send_data(0x83); + send_cmd(0xE9); send_data(0x09);send_data(0x09);send_data(0x08); + + //Init setting + send_cmd(0x36); send_data(0x00); + send_cmd(0x35); send_data(0x00); + send_cmd(0x3A); send_data(0x05);//0x06: 262k 0x05:65k + send_cmd(0xD2); send_data(0x4C); + send_cmd(0xB2);send_data(0x0C);send_data(0x0C);send_data(0x00);send_data(0x33);send_data(0x33); + send_cmd(0xC6); send_data(0x09); + + //Gamma setting + send_cmd(0xE0); + send_data(0xD0); + send_data(0x02); + send_data(0x11); + send_data(0x12); + send_data(0x12); + send_data(0x2A); + send_data(0x3D); + send_data(0x44); + send_data(0x4C); + send_data(0x2B); + send_data(0x16); + send_data(0x14); + send_data(0x1E); + send_data(0x21); + + send_cmd(0xE1); + send_data(0xD0); + send_data(0x02); + send_data(0x11); + send_data(0x11); + send_data(0x12); + send_data(0x2A); + send_data(0x3B); + send_data(0x44); + send_data(0x4C); + send_data(0x2B); + send_data(0x16); + send_data(0x15); + send_data(0x1E); + send_data(0x21); + + send_cmd(0x29); //Display On +#endif + return 0; +} + + +static int32_t st7789v_set_window(struct panel_spec *self, + uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) +{ + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + send_data_t send_data = self->info.mcu->ops->send_data; + + pr_debug("st7789v_set_window\n"); + +#if defined(ST7789V_BUS_WIDTH_8BIT) + send_cmd(0x002A); // col + send_data(left); + send_data(right); + + send_cmd(0x002B); // row + send_data(top); + send_data(bottom); + send_cmd(0x002C); +#else // 16/18/24bit + send_cmd(0x2A); // col + send_data((left >> 8)); + send_data((left & 0xFF)); + send_data((right >> 8)); + send_data((right & 0xFF)); + + send_cmd(0x2B); // row + send_data((top >> 8)); + send_data((top & 0xFF)); + send_data((bottom >> 8)); + send_data((bottom & 0xFF)); + send_cmd(0x2C); +#endif + + return 0; +} + + +static int32_t st7789v_invalidate(struct panel_spec *self) +{ + pr_debug("st7789v_invalidate\n"); + + return self->ops->panel_set_window(self, 0, 0, + self->width-1, self->height-1); +} + +static int32_t st7789v_invalidate_rect(struct panel_spec *self, + uint16_t left, uint16_t top, + uint16_t right, uint16_t bottom) +{ + + pr_debug("st7789v_invalidate_rect : (%d, %d, %d, %d)\n",left, top, right, bottom); + + return self->ops->panel_set_window(self, left, top, + right, bottom); +} + +static int32_t st7789v_set_direction(struct panel_spec *self, uint16_t direction) +{ + + pr_debug("st7789v_set_direction\n"); + return 0; +} + +static int32_t st7789v_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + //send_data_t send_cmd = self->info.mcu->ops->send_cmd; + + if(is_sleep) { + //send_cmd(0x10); + mdelay(120); + } + else { + //send_cmd(0x11); + mdelay(120); + } + return 0; +} + +#define LCD_MTP_ID 0x51a0f0 +static uint32_t st7789v_read_id(struct panel_spec *self) +{ + int32_t read_value = 0; + + send_data_t send_cmd = self->info.mcu->ops->send_cmd; + read_data_t read_data = self->info.mcu->ops->read_data; + + send_cmd(0x04); + +#if defined(ST7789V_BUS_WIDTH_8BIT) + read_value += (read_data() &0xff)<<16; + read_value += read_data(); +#else + read_data(); + read_value += read_data()<< 16; + read_value += read_data()<< 8; + read_value += read_data(); +#endif + pr_debug("st7789v_read_id=%x\n",read_value); + + if(read_value == LCD_MTP_ID) + read_value = 0x7789; + + return read_value; +} + +static struct panel_operations lcd_st7789v_operations = { + .panel_init = st7789v_init, + .panel_set_window = st7789v_set_window, + .panel_invalidate = st7789v_invalidate, + //.lcd_invalidate_rect = st7789v_invalidate_rect, + .panel_set_direction = st7789v_set_direction, + .panel_enter_sleep = st7789v_enter_sleep, + .panel_readid = st7789v_read_id, +}; + +static struct timing_mcu lcd_st7789v_timing[] = { + [MCU_LCD_REGISTER_TIMING] = { + .rcss = 45, + .rlpw = 60, + .rhpw = 100, + .wcss = 10, + .wlpw = 28, + .whpw = 28, + }, + [MCU_LCD_GRAM_TIMING] = { + .rcss = 25, /* 25 ns */ + .rlpw = 70, + .rhpw = 70, + .wcss = 10, + .wlpw = 28, + .whpw = 28, + } +}; + + +static struct info_mcu lcd_st7789v_info = { + .bus_mode = LCD_BUS_8080, + .bus_width = 8, //16, + .bpp = 16, /*RGB565*/ + .timing = &lcd_st7789v_timing, + .ops = NULL, +}; + +struct panel_spec lcd_panel_st7789v = { + .width = 240, + .height = 320, + .fps = 60, + .type = LCD_MODE_MCU, + .direction = LCD_DIRECT_NORMAL, + .info = { + .mcu = &lcd_st7789v_info + }, + .ops = &lcd_st7789v_operations, +}; + +struct panel_cfg lcd_st7789v = { + /* this panel may on both CS0/1 */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x7789, + .lcd_name = "lcd_st7789v", + .panel = &lcd_panel_st7789v, +}; + +static int __init lcd_st7789v_init(void) +{ + return sprdfb_panel_register(&lcd_st7789v); +} + +subsys_initcall(lcd_st7789v_init);
\ No newline at end of file diff --git a/drivers/video/sprdfb/lcd/lcd_t8861_mipi.c b/drivers/video/sprdfb/lcd/lcd_t8861_mipi.c new file mode 100644 index 00000000..51e8a908 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_t8861_mipi.c @@ -0,0 +1,485 @@ +/* drivers/video/sprdfb/lcd/lcd_t8861_mipi.c
+ *
+ * Support for t8861 mipi LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include "../sprdfb_panel.h"
+
+//#define LCD_DEBUG
+#ifdef LCD_DEBUG
+#define LCD_PRINT printk
+#else
+#define LCD_PRINT(...)
+#endif
+
+#define MAX_DATA 48
+
+typedef struct LCM_Init_Code_tag {
+ unsigned int tag;
+ unsigned char data[MAX_DATA];
+}LCM_Init_Code;
+
+typedef struct LCM_force_cmd_code_tag{
+ unsigned int datatype;
+ LCM_Init_Code real_cmd_code;
+}LCM_Force_Cmd_Code;
+
+#define LCM_TAG_SHIFT 24
+#define LCM_TAG_MASK ((1 << 24) -1)
+#define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
+#define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
+//#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
+
+#define LCM_TAG_SEND (1<< 0)
+#define LCM_TAG_SLEEP (1 << 1)
+
+static LCM_Init_Code init_data[] = {
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+ {LCM_SLEEP(5)},
+
+ {LCM_SEND(2), {0x08,0x10}},
+
+ {LCM_SEND(2), {0x21,0x01}},
+
+ {LCM_SEND(2), {0x30,0x02}},
+ {LCM_SEND(2), {0x31,0x00}}, //0x02
+
+ {LCM_SEND(2), {0x60,0x07}},
+ {LCM_SEND(2), {0x61,0x06}},
+ {LCM_SEND(2), {0x62,0x06}},
+ {LCM_SEND(2), {0x63,0x04}},
+
+ {LCM_SEND(2), {0x40,0x14}},
+ {LCM_SEND(2), {0x41,0x44}},//22
+ {LCM_SEND(2), {0x42,0x01}},
+ {LCM_SEND(2), {0x43,0x89}},
+ {LCM_SEND(2), {0x44,0x89}},
+ {LCM_SEND(2), {0x45,0x1b}},
+ {LCM_SEND(2), {0x46,0x44}},
+ {LCM_SEND(2), {0x47,0x44}},
+
+ {LCM_SEND(2), {0x50,0x85}},
+ {LCM_SEND(2), {0x51,0x85}},
+ {LCM_SEND(2), {0x52,0x00}},
+ {LCM_SEND(2), {0x53,0x64}},//90
+
+ //{LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+
+ {LCM_SEND(2), {0xA0,0x00}},
+ {LCM_SEND(2), {0xA1,0x00}},//01
+ {LCM_SEND(2), {0xA2,0x03}},//08
+ {LCM_SEND(2), {0xA3,0x0e}},//0e
+ {LCM_SEND(2), {0xA4,0x08}},//08
+ {LCM_SEND(2), {0xA5,0x1f}},//19
+ {LCM_SEND(2), {0xA6,0x0f}},//0b
+ {LCM_SEND(2), {0xA7,0x0b}},//0a
+ {LCM_SEND(2), {0xA8,0x03}},//02
+ {LCM_SEND(2), {0xA9,0x06}},//08
+ {LCM_SEND(2), {0xAA,0x05}},//04
+ {LCM_SEND(2), {0xAB,0x02}},//03
+ {LCM_SEND(2), {0xAC,0x0e}},//0a
+ {LCM_SEND(2), {0xAD,0x25}},//2c
+ {LCM_SEND(2), {0xAE,0x1d}},//28
+ {LCM_SEND(2), {0xAF,0x00}},
+
+ {LCM_SEND(2), {0xC0,0x00}},//00
+ {LCM_SEND(2), {0xC1,0x04}},//02
+ {LCM_SEND(2), {0xC2,0x0f}},//09
+ {LCM_SEND(2), {0xC3,0x10}},//0e
+ {LCM_SEND(2), {0xC4,0x0b}},//09
+ {LCM_SEND(2), {0xC5,0x1e}},//19
+ {LCM_SEND(2), {0xC6,0x09}},//0a
+ {LCM_SEND(2), {0xC7,0x0a}},//0a
+ {LCM_SEND(2), {0xC8,0x00}},//02
+ {LCM_SEND(2), {0xC9,0x0a}},//07
+ {LCM_SEND(2), {0xCA,0x01}},//05
+ {LCM_SEND(2), {0xCB,0x06}},//04
+ {LCM_SEND(2), {0xCC,0x09}},//0a
+ {LCM_SEND(2), {0xCD,0x2a}},//2d
+ {LCM_SEND(2), {0xCE,0x28}},//28
+ {LCM_SEND(2), {0xCF,0x00}},//00
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x06}},
+ {LCM_SEND(2), {0x00,0xa0}},
+ {LCM_SEND(2), {0x01,0x05}},
+ {LCM_SEND(2), {0x02,0x00}},
+ {LCM_SEND(2), {0x03,0x00}},
+ {LCM_SEND(2), {0x04,0x01}},
+ {LCM_SEND(2), {0x05,0x01}},
+ {LCM_SEND(2), {0x06,0x88}},
+ {LCM_SEND(2), {0x07,0x04}},
+ {LCM_SEND(2), {0x08,0x01}},
+ {LCM_SEND(2), {0x09,0x90}},
+ {LCM_SEND(2), {0x0A,0x04}},
+ {LCM_SEND(2), {0x0B,0x01}},
+ {LCM_SEND(2), {0x0C,0x01}},
+ {LCM_SEND(2), {0x0D,0x01}},
+ {LCM_SEND(2), {0x0E,0x00}},
+ {LCM_SEND(2), {0x0F,0x00}},
+
+ {LCM_SEND(2), {0x10,0x55}},
+ {LCM_SEND(2), {0x11,0x50}},
+ {LCM_SEND(2), {0x12,0x01}},
+ {LCM_SEND(2), {0x13,0x85}},
+ {LCM_SEND(2), {0x14,0x85}},
+ {LCM_SEND(2), {0x15,0xc0}},
+ {LCM_SEND(2), {0x16,0x0B}},
+ {LCM_SEND(2), {0x17,0x00}},
+ {LCM_SEND(2), {0x18,0x00}},
+ {LCM_SEND(2), {0x19,0x00}},
+ {LCM_SEND(2), {0x1A,0x00}},
+ {LCM_SEND(2), {0x1B,0x00}},
+ {LCM_SEND(2), {0x1C,0x00}},
+ {LCM_SEND(2), {0x1D,0x00}},
+
+ {LCM_SEND(2), {0x20,0x01}},
+ {LCM_SEND(2), {0x21,0x23}},
+ {LCM_SEND(2), {0x22,0x45}},
+ {LCM_SEND(2), {0x23,0x67}},
+ {LCM_SEND(2), {0x24,0x01}},
+ {LCM_SEND(2), {0x25,0x23}},
+ {LCM_SEND(2), {0x26,0x45}},
+ {LCM_SEND(2), {0x27,0x67}},
+
+ {LCM_SEND(2), {0x30,0x02}},
+ {LCM_SEND(2), {0x31,0x22}},
+ {LCM_SEND(2), {0x32,0x11}},
+ {LCM_SEND(2), {0x33,0xaa}},
+ {LCM_SEND(2), {0x34,0xbb}},
+ {LCM_SEND(2), {0x35,0x66}},
+ {LCM_SEND(2), {0x36,0x00}},
+ {LCM_SEND(2), {0x37,0x22}},
+ {LCM_SEND(2), {0x38,0x22}},
+ {LCM_SEND(2), {0x39,0x22}},
+ {LCM_SEND(2), {0x3A,0x22}},
+ {LCM_SEND(2), {0x3B,0x22}},
+ {LCM_SEND(2), {0x3C,0x22}},
+ {LCM_SEND(2), {0x3D,0x22}},
+ {LCM_SEND(2), {0x3E,0x22}},
+ {LCM_SEND(2), {0x3F,0x22}},
+
+ {LCM_SEND(2), {0x40,0x22}},
+ {LCM_SEND(2), {0x53,0x1a}},
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x07}},
+ {LCM_SEND(2), {0x18,0x1d}},
+ {LCM_SEND(2), {0x17,0x12}},
+
+ {LCM_SEND(2), {0x02,0x77}},
+
+ {LCM_SEND(2), {0xe1,0x79}},
+
+ {LCM_SEND(2), {0x06,0x13}},
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+
+// {LCM_SEND(2), {0x35,0x00}},
+
+ {LCM_SEND(1), {0x11}},
+ {LCM_SLEEP(120)},
+
+ {LCM_SEND(1), {0x29}},
+ {LCM_SLEEP(1)},
+
+// {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x08}},
+
+};
+
+static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
+
+static LCM_Init_Code sleep_in[] = {
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+ {LCM_SLEEP(1)},
+
+
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x00}},
+ {LCM_SLEEP(1)},
+
+{LCM_SEND(1), {0x28}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x10}},
+{LCM_SLEEP(10)},
+ {LCM_SEND(8), {6, 0,0xFF,0xFF,0x98,0x06,0x04,0x01}},
+ {LCM_SLEEP(1)},
+
+ {LCM_SEND(2), {0x58,0x91}},
+
+};
+
+static LCM_Init_Code sleep_out[] = {
+{LCM_SEND(1), {0x11}},
+{LCM_SLEEP(120)},
+{LCM_SEND(1), {0x29}},
+{LCM_SLEEP(20)},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code[]={
+ {0x39, {LCM_SEND(8), {0x6, 0, 0xFF, 0xFF, 0x98, 0x06,0x04,0x01}}},
+ {0x37, {LCM_SEND(2), {0x3, 0}}},
+};
+
+static LCM_Force_Cmd_Code rd_prep_code_1[]={
+ {0x37, {LCM_SEND(2), {0x1, 0}}},
+};
+static int32_t t8861_mipi_init(struct panel_spec *self)
+{
+ int32_t i;
+ LCM_Init_Code *init = init_data;
+ unsigned int tag;
+
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug(KERN_DEBUG "t8861_mipi_init\n");
+
+ msleep(2);
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i < ARRAY_SIZE(init_data); i++){
+ tag = (init->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
+ udelay(20);
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((init->tag & LCM_TAG_MASK) * 1000);
+ msleep(init->tag & LCM_TAG_MASK);
+ }
+ init++;
+ }
+ mipi_eotp_set(1,1);
+
+ return 0;
+}
+
+static uint32_t t8861_readid(struct panel_spec *self)
+{
+ /*Jessica TODO: need read id*/
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
+ uint8_t read_data[3] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk("lcd_t8861_mipi read id!\n");
+
+ mipi_set_cmd_mode();
+ mipi_eotp_set(1,0);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ udelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK) * 1000);
+ }
+ rd_prepare++;
+ }
+ read_rtn = mipi_force_read(0x02, 3,(uint8_t *)read_data);
+ printk("lcd_t8861_mipi read id 0xc5 value is 0x%x, 0x%x, 0x%x!\n", read_data[0], read_data[1], read_data[2]);
+
+ if((0x04 == read_data[0])){
+ printk("lcd_t8861_mipi read id success!\n");
+ mipi_eotp_set(1,1);
+ return 0x04;
+ }
+ }
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+static int32_t t8861_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ int32_t i;
+ LCM_Init_Code *sleep_in_out = NULL;
+ unsigned int tag;
+ int32_t size = 0;
+
+ mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ printk(KERN_DEBUG "t8861_enter_sleep, is_sleep = %d\n", is_sleep);
+
+ if(is_sleep){
+ sleep_in_out = sleep_in;
+ size = ARRAY_SIZE(sleep_in);
+ }else{
+ sleep_in_out = sleep_out;
+ size = ARRAY_SIZE(sleep_out);
+ }
+ mipi_eotp_set(1,0);
+
+ for(i = 0; i <size ; i++){
+ tag = (sleep_in_out->tag >>24);
+ if(tag & LCM_TAG_SEND){
+ mipi_gen_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ //udelay((sleep_in_out->tag & LCM_TAG_MASK) * 1000);
+ msleep((sleep_in_out->tag & LCM_TAG_MASK));
+ }
+ sleep_in_out++;
+ }
+ return 0;
+}
+
+static uint32_t t8861_readpowermode(struct panel_spec *self)
+{
+ int32_t i = 0;
+ uint32_t j =0;
+ LCM_Force_Cmd_Code * rd_prepare = rd_prep_code_1;
+ uint8_t read_data[1] = {0};
+ int32_t read_rtn = 0;
+ unsigned int tag = 0;
+ uint32_t reg_val_1 = 0;
+ uint32_t reg_val_2 = 0;
+
+ mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
+ mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
+ mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
+
+ pr_debug("lcd_t8861_mipi read power mode!\n");
+ mipi_eotp_set(0,1);
+
+ for(j = 0; j < 4; j++){
+ rd_prepare = rd_prep_code_1;
+ for(i = 0; i < ARRAY_SIZE(rd_prep_code_1); i++){
+ tag = (rd_prepare->real_cmd_code.tag >> 24);
+ if(tag & LCM_TAG_SEND){
+ mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
+ }else if(tag & LCM_TAG_SLEEP){
+ udelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK) * 1000);
+ }
+ rd_prepare++;
+ }
+
+ read_rtn = mipi_force_read(0x0A, 1,(uint8_t *)read_data);
+ //printk("lcd_t8861 mipi read power mode 0x0A value is 0x%x! , read result(%d)\n", read_data[0], read_rtn);
+
+ if((0x9c == read_data[0]) && (0 == read_rtn)){
+ pr_debug("lcd_t8861_mipi read power mode success!\n");
+ mipi_eotp_set(1,1);
+ return 0x9c;
+ }
+ }
+
+ mipi_eotp_set(1,1);
+ return 0x0;
+}
+
+
+static uint32_t t8861_check_esd(struct panel_spec *self)
+{
+ uint32_t power_mode;
+
+ pr_debug("t8861_check_esd!\n");
+ mipi_set_lp_mode_t mipi_set_data_lp_mode = self->info.mipi->ops->mipi_set_data_lp_mode;
+ mipi_set_hs_mode_t mipi_set_data_hs_mode = self->info.mipi->ops->mipi_set_data_hs_mode;
+
+ mipi_set_lp_mode_t mipi_set_lp_mode = self->info.mipi->ops->mipi_set_lp_mode;
+ mipi_set_hs_mode_t mipi_set_hs_mode = self->info.mipi->ops->mipi_set_hs_mode;
+ uint16_t work_mode = self->info.mipi->work_mode;
+
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_lp_mode();
+ }else{
+ mipi_set_data_lp_mode();
+ }
+ power_mode = t8861_readpowermode(self);
+ //power_mode = 0x0;
+ if(SPRDFB_MIPI_MODE_CMD==work_mode){
+ mipi_set_hs_mode();
+ }else{
+ mipi_set_data_hs_mode();
+ }
+ if(power_mode == 0x9c){
+ pr_debug("t8861_check_esd OK!\n");
+ return 1;
+ }else{
+ printk("t8861_check_esd fail!(0x%x)\n", power_mode);
+ return 0;
+ }
+}
+
+
+static struct panel_operations lcd_t8861_mipi_operations = {
+ .panel_init = t8861_mipi_init,
+ .panel_readid = t8861_readid,
+ .panel_enter_sleep = t8861_enter_sleep,
+ .panel_esd_check = t8861_check_esd,
+};
+ +static struct timing_rgb lcd_t8861_mipi_timing = {
+ .hfp = 60, /* unit: pixel */// 100
+ .hbp = 80,//80
+ .hsync = 60,//6
+ .vfp = 20, /*unit: line*/
+ .vbp = 14,
+ .vsync =6, //6,
+};
+
+static struct info_mipi lcd_t8861_mipi_info = {
+ .work_mode = SPRDFB_MIPI_MODE_VIDEO,
+ .video_bus_width = 24, /*18,16*/
+ .lan_number = 2,
+ .phy_feq = 500*1000, //500->10MHz,400->8M in lp mode
+ .h_sync_pol = SPRDFB_POLARITY_POS,
+ .v_sync_pol = SPRDFB_POLARITY_POS,
+ .de_pol = SPRDFB_POLARITY_POS,
+ .te_pol = SPRDFB_POLARITY_POS,
+ .color_mode_pol = SPRDFB_POLARITY_NEG,
+ .shut_down_pol = SPRDFB_POLARITY_NEG,
+ .timing = &lcd_t8861_mipi_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_t8861_mipi_spec = {
+ //.cap = PANEL_CAP_NOT_TEAR_SYNC,
+ .width = 480,
+ .height = 800,
+ .fps = 60,
+ .type = LCD_MODE_DSI,
+ .direction = LCD_DIRECT_NORMAL,
+ .is_clean_lcd = true,
+ .info = {
+ .mipi = &lcd_t8861_mipi_info
+ },
+ .ops = &lcd_t8861_mipi_operations,
+};
+
+struct panel_cfg lcd_t8861_mipi = {
+ /* this panel can only be main lcd */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x04,
+ .lcd_name = "lcd_t8861_mipi",
+ .panel = &lcd_t8861_mipi_spec,
+};
+
+static int __init lcd_t8861_mipi_init(void)
+{
+ return sprdfb_panel_register(&lcd_t8861_mipi);
+}
+
+subsys_initcall(lcd_t8861_mipi_init);
diff --git a/drivers/video/sprdfb/lcd/lcd_vx5b3d_mipi.c b/drivers/video/sprdfb/lcd/lcd_vx5b3d_mipi.c new file mode 100755 index 00000000..94cc6486 --- /dev/null +++ b/drivers/video/sprdfb/lcd/lcd_vx5b3d_mipi.c @@ -0,0 +1,965 @@ +#include <linux/bug.h> +#include <linux/delay.h> +#include "../sprdfb_panel.h" +#include <mach/gpio.h> +#include <linux/i2c.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <mach/i2c-sprd.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <linux/of_gpio.h> +#define LCD_DEBUG +#define pr_info printk +#define LCD_PRINT printk +#define MAX_DATA 100 +//#define QUICKLOGIC_DEBUG + +struct bridge_data { + u16 addr; + u32 data; +}__attribute__ ((packed)); + +struct vx5b3d_dt_data { + int gpio_bridge_en; + int gpio_bridge_rst; + int gpio_blic_en; + int gpio_lcd_3v3_en; +}; +struct vx5b3d_dt_data *pdata = NULL; + +static struct i2c_client *g_client = NULL; +struct regulator *lvds_1v8; +struct regulator *lvds_3v3; +struct panel_spec lcd_vx5b3d_mipi_spec; +struct panel_spec *self = &lcd_vx5b3d_mipi_spec; +struct i2c_driver quicklogic_i2c_driver; +extern uint32_t sprdfb_panel_reset_all(void); + +#define QUICKLOGIC_MIPI_VENDOR_ID_1 0x5 +#define QUICKLOGIC_MIPI_VENDOR_ID_2 0x1 +#define QUICKLOGIC_MIPI_COMMAND_CSR_WRITE 0x40 +#define QUICKLOGIC_MIPI_COMMAND_CSR_OFFSET 0x41 + +#define VX5B3D_I2C_RETRY_CNT (5) + +#define DELAY_CMD (0xFFFF) + +struct bridge_data vx5b3d_init[] = { + {0x700, 0x6C900040}, + {0x704, 0x0003040A}, + {0x70C, 0x00004604}, + {0x710, 0x054D000B}, + {0x714, 0x00000020}, + {0x718, 0x00000102}, + {0x71C, 0x00A8002F}, + {0x720, 0x00000000}, + + {DELAY_CMD, 100}, /* For pll locking */ + {0x154, 0x00000000}, + {0x154, 0x80000000}, + {DELAY_CMD, 100}, /* For pll locking */ + + {0x700, 0x6C900840}, + {0x70C, 0x00005E56}, + {0x718, 0x00000202}, + + {0x154, 0x00000000}, + {0x154, 0x80000000}, + {DELAY_CMD, 100}, /* For pll locking */ + + {0x37C, 0x00001063}, + {0x380, 0x82A86030}, + {0x384, 0x2861408B}, + {0x388, 0x00130285}, + {0x38C, 0x10630009}, + {0x394, 0x400B82A8}, + {0x600, 0x016CC78C}, + {0x604, 0x3FFFFFE0}, + {0x608, 0x00000D8C}, + {0x154, 0x00000000}, + {0x154, 0x80000000}, + {0x120, 0x00000005}, + {0x124, 0x1892C400}, + {0x128, 0x00102806}, + {0x12C, 0x00000062}, + {0x130, 0x00003C18}, + {0x134, 0x00000015}, + {0x138, 0x00FF8000}, + {0x13C, 0x00000000}, + + /*PWM 100 % duty ration*/ + {0x114, 0x000c6302}, + + /*backlight duty ratio control when device is first bring up.*/ + {0x160, 0x000007F8}, + {0x164, 0x000002A8}, + {0x138, 0x3fff0000}, + {0x15C, 0x00000005}, + + {0x140, 0x00010000}, + /*Add for power consumtion*/ + {0x174, 0x00000000}, + /*end*/ + + /* + slope = 2 / variance = 0x55550022 + slope register [15,10] + */ + {0x404, 0x55550822}, + + /* + To minimize the text effect + this value from 0xa to 0xf + */ + {0x418, 0x555502ff}, + + /* + Disable brightnes issue Caused by IBC + read 4 bytes from address 0x410 to 0x413 + 0x15E50300 is read value for 0x410 register + 0x5E50300= 0x15E50300 & 0xefffffff + */ + {0x410, 0x05E50300}, + /*...end*/ + {0x20C, 0x00000124}, + {0x21C, 0x00000000}, + {0x224, 0x00000007}, + {0x228, 0x00050001}, + {0x22C, 0x0000FF03}, + {0x230, 0x00000001}, + {0x234, 0xCA033E10}, + {0x238, 0x00000060}, + {0x23C, 0x82E86030}, + {0x244, 0x001E0285}, + {0x258, 0x00060062}, + /*vee strenght initialization*/ + {0x400, 0x00000000}, + {0x158, 0x00000000}, + {0x158, 0x00000001}, +}; + +static DEFINE_MUTEX(lock); +#define QUICKLOGIC_MIPI_VENDOR_ID_1 0x5 +#define QUICKLOGIC_MIPI_VENDOR_ID_2 0x1 +#define QUICKLOGIC_MIPI_COMMAND_CSR_WRITE 0x40 +#define QUICKLOGIC_MIPI_COMMAND_CSR_OFFSET 0x41 + +#define QUICKLOGIC_IIC_READ_CONTROL 0x0E +#define QUICKLOGIC_IIC_WRITE_CONTROL 0x0A +#define QUICKLOGIC_BYTE_I2C_RELEASE (0x0u) +#define QUICKLOGIC_IIC_RELEASE {\ + QUICKLOGIC_BYTE_I2C_RELEASE, \ +} + +#define QL_MIPI_PANEL_CMD_SIZE 255 +#define QL_VX_LCD_VC 0 /* dcs read/write */ +#define CONTROL_BYTE_DCS (0x08u) + +#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */ +#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */ +#define DTYPE_DCS_READ 0x06 /* read */ +#define DTYPE_DCS_LWRITE 0x39 /* long write *//* generic read/write */ +#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */ +#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */ +#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */ +#define DTYPE_GEN_LWRITE 0x29 /* long write */ +#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */ +#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */ +#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */ + + +#define I2CID_BRIDGE 3 +#define I2C_NT50366_ADDR_WRITE 0x9E /* NT50366C 100_1111 0 */ +#define I2C_NT51017_ADDR_WRITE 0xD0 /* NT51017 110_1000 0 */ +#define I2C_BRIDGE_ADDR_WRITE0 0x58 /* 0101_100 0 ADDR=Low */ +#define I2C_BRIDGE_ADDR_WRITE1 0x5A /* 0101_101 0 ADDR=High */ +#define I2C_BRIDGE_ADDR I2C_BRIDGE_ADDR_WRITE0 + +#define CONTROL_BYTE_GEN (0x09u) +/************************************************** + * QUICKLOGIC MACRO FOR I2C * + ***************************************************/ +#define GEN_QL_CSR_OFFSET_LENGTH {\ + CONTROL_BYTE_GEN, \ + 0x29, /* Data ID */\ + 0x05, /* Vendor Id 1 */\ + 0x01, /* Vendor Id 2 */\ + 0x41, /* Vendor Unique Command */\ + 0x00, /* Address LS */\ + 0x00, /* Address MS */\ + 0x00, /* Length LS */\ + 0x00, /* Length MS */\ +} + +#define GEN_QL_CSR_WRITE {\ + CONTROL_BYTE_GEN, \ + 0x29, /* Data ID */\ + 0x05, /* Vendor Id 1 */\ + 0x01, /* Vendor Id 2 */\ + 0x40, /* Vendor Unique Command */\ + 0x00, /* Address LS */\ + 0x00, /* Address MS */\ + 0x00, /* data LS */\ + 0x00, \ + 0x00, \ + 0x00, /* data MS */\ +} + + +int Quicklogic_i2c_read32(u16 reg, u32 *pval) +{ + int ret; + int status; + u8 address[3], data[4]; + + if (g_client == NULL) /* No global client pointer? */ + return -EIO; + + mutex_lock(&lock); + memset(data, 0, 4); + address[0] = (reg >> 8) & 0xff; + address[1] = reg & 0xff; + address[2] = 0xE; + + ret = i2c_master_send(g_client, address, 3); + if (ret < 0) { + status = -EIO; + } + ret = i2c_master_recv(g_client, data, 4); + if (ret >= 0) { + status = 0; + *pval = data[0] | (data[1] << 8) | (data[2] << 16) + | (data[3] << 24); + } else + status = -EIO; + + mutex_unlock(&lock); + + return status; +} +EXPORT_SYMBOL(Quicklogic_i2c_read32); + +int Quicklogic_i2c_read(u32 addr, u32 *val, u32 data_size) +{ + u32 data; + char buf[] = GEN_QL_CSR_OFFSET_LENGTH; + char rx[10]; + int ret = -1; + int write_size; + + if (g_client == NULL) /* No global client pointer? */ + return -EIO; + + mutex_lock(&lock); + + buf[5] = addr & 0xff; + buf[6] = (addr >> 8) & 0xff; + buf[7] = data_size & 0xff; + buf[8] = (data_size >> 8) & 0xff; + + write_size = 9; + + if ((ret = i2c_master_send( g_client, + (char*)(&buf[0]), + write_size )) != write_size) { + printk(KERN_ERR + "%s: i2c_master_send failed (%d)!\n", __func__, ret); + mutex_unlock(&lock); + + return -EIO; + } + + /*generic read request 0x24 to send generic read command */ + write_size = 4; + + buf[0] = CONTROL_BYTE_GEN; + buf[1] = 0x24; /* Data ID */ + buf[2] = 0x05; /* Vendor Id 1 */ + buf[3] = 0x01; /* Vendor Id 2 */ + + if ((ret = i2c_master_send(g_client, + (char*)(&buf[0]), + write_size )) != write_size) { + + pr_info("i2c_master_send failed (%d)!\n", ret); + mutex_unlock(&lock); + return -EIO; + } + + /*return number of bytes or error*/ + if ((ret = i2c_master_recv(g_client, + (char*)(&rx[0]), + data_size )) != data_size) { + + pr_info("i2c_master_recv failed (%d)!\n", ret); + mutex_unlock(&lock); + return -EIO; + } + + data = rx[0]; + if (data_size > 1) + data |= (rx[1] << 8); + if (data_size > 2) + data |= (rx[2] << 16) | (rx[3] << 24); + + *val = data; + + mutex_unlock(&lock); + + pr_info("QX_read value0x%x=0x%x\n",addr,data); + + return 0; + +} +EXPORT_SYMBOL(Quicklogic_i2c_read); + +int Quicklogic_i2c_write32(u16 reg, u32 val) +{ + int status = 0; + /*int write_size;*/ + char buf[] = GEN_QL_CSR_WRITE; + + if (g_client == NULL) /* No global client pointer? */ + return -EIO; + + mutex_lock(&lock); + + buf[5] = (uint8_t)reg; /* Address LS */ + buf[6] = (uint8_t)(reg >> 8); /* Address MS */ + + buf[7] = val & 0xff; + buf[8] = (val >> 8) & 0xff; + buf[9] = (val >> 16) & 0xff; + buf[10] =(val >> 24) & 0xff; + status = i2c_master_send(g_client, (char *)(&buf[0]), 11); + + if (status >= 0) + status = 0; + else { + printk("zyun: i2c write 32 single error! [0x%04x] -EIO\n", reg); + status = -EIO; + } + + udelay(10); + mutex_unlock(&lock); + + return status; + +} +EXPORT_SYMBOL(Quicklogic_i2c_write32); + +int Quicklogic_i2c_release(void) +{ + int write_size; + int ret = 0; + char buf[] = QUICKLOGIC_IIC_RELEASE; + + if (g_client == NULL) /* No global client pointer? */ + return -1; + + mutex_lock(&lock); + + write_size = 1; + + if ((ret = i2c_master_send( g_client, + (char*)(&buf[0]), + write_size )) != write_size) + pr_info("i2c_master_send failed (%d)!\n", ret); + + mutex_unlock(&lock); + + return ret; +} +EXPORT_SYMBOL(Quicklogic_i2c_release); + +int Quicklogic_i2cTomipi_write(int dtype, int vit_com, u8 data_size, u8 *ptr ) +{ + char buf[QL_MIPI_PANEL_CMD_SIZE]; + int write_size; + int i; + int ret = -1; + int dtype_int; + + + if (g_client == NULL) /* No global client pointer? */ + return -1; + + if (data_size > (QL_MIPI_PANEL_CMD_SIZE - 10)) { + printk("data size (%d) too big, adjust the QL_MIPI_PANEL_CMD_SIZE!\n", data_size); + return ret; + } + dtype_int = dtype; + + mutex_lock(&lock); + + switch (dtype) { + case DTYPE_GEN_WRITE: + case DTYPE_GEN_LWRITE: + case DTYPE_GEN_WRITE1: + case DTYPE_GEN_WRITE2: + buf[0] = CONTROL_BYTE_GEN; + dtype_int = (data_size == 1) ? DTYPE_GEN_WRITE1 : + (data_size == 2) ? DTYPE_GEN_WRITE2 : DTYPE_GEN_LWRITE; + break; + case DTYPE_DCS_WRITE: + case DTYPE_DCS_LWRITE: + case DTYPE_DCS_WRITE1: + buf[0] = CONTROL_BYTE_DCS; + dtype_int = (data_size == 1) ? DTYPE_DCS_WRITE : + (data_size == 2) ? DTYPE_DCS_WRITE1 : DTYPE_DCS_LWRITE; + break; + default: + printk("Error unknown data type (0x%x).\n", dtype); + break; + } + + buf[1] = ((vit_com & 0x3) << 6) | dtype_int ; /*vc, Data ID *//* Copy data */ + + /* Copy data */ + for(i = 0; i < data_size; i++) + buf[2+i] = *ptr++; + + write_size = data_size + 2; + + if ((ret = i2c_master_send(g_client,(char*)(&buf[0]),write_size )) != write_size) { + printk("Quicklogic_i2c_write32 failed : %d\n", ret); + + mutex_unlock(&lock); + + return -EIO; + } + + mutex_unlock(&lock); + + return 0; +} +EXPORT_SYMBOL(Quicklogic_i2cTomipi_write); + +int Quicklogic_i2cTomipi_read(int dtype, int vit_com, u8 data_size, u8 reg , u8 *pval) +{ + char buf[QL_MIPI_PANEL_CMD_SIZE]; + char rx[10]; + int write_size; int ret = -1; int dtype_int; + + if (data_size > (QL_MIPI_PANEL_CMD_SIZE-10)) { + printk("data size (%d) too big, adjust the QL_MIPI_PANEL_CMD_SIZE!\n", data_size); + return ret; + } + + dtype_int = dtype; + + mutex_lock(&lock); + + switch (dtype) { + + case DTYPE_GEN_READ1: /*0x14*/ + case DTYPE_GEN_READ2: /*0x24*/ + buf[0] = CONTROL_BYTE_GEN; + break; + + case DTYPE_DCS_READ: /*0x6*/ + buf[0] = CONTROL_BYTE_DCS; + break; + + default: + printk("Error unknown data type (0x%x).\n", dtype); + break; + } + + buf[1] = ((vit_com & 0x3) << 6) | dtype_int ; /*vc, Data ID */ + + switch (dtype) { + + case DTYPE_GEN_READ2: /* short read, 2 parameter */ + + write_size = 4; + buf[2] = reg; + buf[3] = 0; + break; + + default: + buf[2] = reg; + break; + } + + write_size = 3; + + if ((ret = i2c_master_send(g_client,(char*)(&buf[0]), + write_size )) != write_size) { + + printk("%s: i2c_master_send failed (%d)!\n", __func__, ret); + + mutex_unlock(&lock); + return -EIO; + } + + if ((ret = i2c_master_recv(g_client, (char*)(&rx[0]), + data_size )) != data_size) { + + printk("%s: i2c_master_recv failed (%d)!\n", __func__, ret); + + mutex_unlock(&lock); + return -EIO; + } + + if (ret < 0) + printk("Quicklogic_i2c_read32 failed : %d\n", ret); + + *pval = rx[0]; + + if (data_size > 1) + *pval |= (rx[1] << 8); + if (data_size > 2) + *pval |= (rx[2] << 16) | (rx[3] << 24); + + printk("QuickBridge reg=[0x%x]..return=[0x%x]\n",reg,*pval); + + mutex_unlock(&lock); + + return 0; +} +EXPORT_SYMBOL(Quicklogic_i2cTomipi_read); + + +int vx5b3d_mipi_write32(struct panel_spec *self, u16 addr, u32 data) +{ + int i; + static u8 packet[] = { + 0x09, 0x00, /* data length */ + QUICKLOGIC_MIPI_VENDOR_ID_1, + QUICKLOGIC_MIPI_VENDOR_ID_2, + QUICKLOGIC_MIPI_COMMAND_CSR_WRITE, + 0x0, 0x0, /* address 16bits */ + 0x0, 0x0, 0x0, 0x0 /* data max 32bits */ + }; + mipi_dcs_write_t mipi_gen_write= + self->info.mipi->ops->mipi_gen_write; + + for (i = 0; i < 2; i++) + packet[5 + i] = (u8)(addr >> (8 * i) & 0xff); + + for (i = 0; i < 4; i++) + packet[7 + i] = (u8)((data >> (8 * i)) & 0xff); + +#ifdef VX5B3D_DEBUG + for (i = 0; i < ARRAY_SIZE(packet); i++) + printf("packet[%d] = 0x%02x\n", i, packet[i]); +#endif + + mipi_gen_write(packet, ARRAY_SIZE(packet)); + + udelay(1); + + return 0; +} + +int vx5b3d_mipi_write32_array(struct panel_spec *self, + struct bridge_data *b_data, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (b_data[i].addr == DELAY_CMD) { + mdelay(b_data[i].data); + continue; + } + vx5b3d_mipi_write32(self, b_data[i].addr, b_data[i].data); + } + + return 0; +} + +int vx5b3d_i2c_write32(u16 addr, u32 data) +{ + int ret, i; + int retry_cnt = VX5B3D_I2C_RETRY_CNT; + + do { + ret = Quicklogic_i2c_write32(addr, data); + } while (--retry_cnt && ret); + + if (!retry_cnt) + printk("zyun: vx5b3d_i2c_write32 failed![%d, addr:0x%04x, data:0x%08x] failed!!\n", + i, addr, data); + + return ret; +} + +int vx5b3d_i2c_write32_array(struct bridge_data *b_data, int len) +{ + int i, ret; + + for (i = 0; i < len; i++) { + if (b_data[i].addr == DELAY_CMD) { + mdelay(b_data[i].data); + continue; + } + ret = vx5b3d_i2c_write32(b_data[i].addr, b_data[i].data); + } + + return ret; +} + +static u32 vx5b3d_i2c_read32(u16 addr) +{ + u32 buf; + Quicklogic_i2c_read(addr, &buf, 4); + + return buf; +} + +/* +static u32 vx5b3d_compare(struct bridge_data *b_data, int len) +{ + int i; + u32 rd_data; + + for (i = 0; i < len; i++) { + if (b_data[i].addr == DELAY_CMD) { + continue; + } + rd_data = vx5b3d_i2c_read32(b_data[i].addr); + if (rd_data != b_data[i].data) + pr_err("[0x%04x] rd_data:0x%x, data:0x%x - not match!!\n", + b_data[i].addr, rd_data, b_data[i].data); + } +} +*/ + +static int32_t vx5b3d_power(int on) +{ + static int probe = 0; + if (!probe) { + gpio_request(pdata->gpio_lcd_3v3_en, "LCD_3V3_EN"); + gpio_direction_output(pdata->gpio_lcd_3v3_en, 0); + if (gpio_request(pdata->gpio_bridge_en, "BRIDGE_EN")) { + printk("[%s] GPIO%d request failed!\n", "BRIDGE_EN", pdata->gpio_bridge_en); + return 0; + } + gpio_direction_output(pdata->gpio_bridge_en, 1); + + if (gpio_request(pdata->gpio_bridge_rst, "BRIDGE_RST")){ + printk("[%s] GPIO%d request failed!\n", "BRIDGE_RST", pdata->gpio_bridge_rst); + return 0; + } + gpio_direction_output(pdata->gpio_bridge_rst, 1); + + if (gpio_request(pdata->gpio_blic_en, "BLIC_EN")) { + printk("[%s] GPIO%d request failed!\n", "BLIC_EN", pdata->gpio_blic_en); + return 0; + } + gpio_direction_output(pdata->gpio_blic_en, 1); + + lvds_1v8 = regulator_get(NULL,"vddsim1"); + if (IS_ERR(lvds_1v8)) { + lvds_1v8 = NULL; + pr_info("%s regulator 1v8 get failed!!\n", "vddsim1"); + } else { + regulator_set_voltage(lvds_1v8, 1800000, 1800000); + regulator_enable(lvds_1v8); + } + + lvds_3v3 = regulator_get(NULL,"vddwifipa"); + if (IS_ERR(lvds_3v3)) { + lvds_3v3 = NULL; + pr_info("%s regulator 3v3 get failed!!\n", "vddwifipa"); + } else { + regulator_set_voltage(lvds_3v3, 3300000, 3300000); + regulator_enable(lvds_3v3); + } + probe = 1; + } + + printk("%s, on= %d\n", __func__, on); + if (on) { + gpio_set_value(pdata->gpio_lcd_3v3_en, 1); + gpio_set_value(pdata->gpio_bridge_en, 1); + regulator_enable(lvds_1v8); + regulator_enable(lvds_3v3); + udelay(20); + gpio_set_value(pdata->gpio_bridge_rst, 1); + udelay(20); + gpio_set_value(pdata->gpio_blic_en, 1); + } else { + gpio_set_value(pdata->gpio_lcd_3v3_en, 0); + gpio_set_value(pdata->gpio_bridge_rst, 0); + udelay(20); + regulator_disable(lvds_3v3); + regulator_disable(lvds_1v8); + gpio_set_value(pdata->gpio_bridge_en, 0); + gpio_set_value(pdata->gpio_blic_en, 0); + msleep(350); + } +} + +static int32_t vx5b3d_mipi_init(struct panel_spec *self) +{ + mipi_set_lp_mode_t mipi_set_lp_mode = + self->info.mipi->ops->mipi_set_lp_mode; + mipi_set_video_mode_t mipi_set_video_mode = + self->info.mipi->ops->mipi_set_video_mode; + + if (!g_client) + { + pr_info("zyun: g_client is NULL!\n"); + return 0; + } + /* step 1 : All DSI into LP11*/ + + mipi_set_lp_mode(); + vx5b3d_power(1); + + /* step 3 : Delay*/ + mdelay(10); +#ifdef QUICKLOGIC_DEBUG + pr_info("[QUICKLOGIC] : VX5B3D INIT - START\n"); + pr_info("[QUICKLOGIC] : VX5B3D INIT - Waiting...(10sec)\n"); + mdelay(10 * 1000); + + pr_info("[QUICKLOGIC] : START VX5B3D INIT - Waiting Done!!\n"); +#else +// vx5b3d_mipi_write32_array(self, vx5b3d_init, ARRAY_SIZE(vx5b3d_init)); + vx5b3d_i2c_write32_array(vx5b3d_init, ARRAY_SIZE(vx5b3d_init)); +#endif + /* step 5 : Start the DSI video stream */ + mipi_set_video_mode(); + mdelay(5); + + printk("zyun: init done! 1 \n"); + pr_info("[QUICKLOGIC] : VX5B3D INIT - DONE\n"); + //vx5b3d_compare(vx5b3d_init, ARRAY_SIZE(vx5b3d_init)); + + return 0; +} + +static uint32_t vx5b3d_readid(struct panel_spec *self) +{ + int32_t j =0; + uint8_t read_data[4] = {0}; + int32_t read_rtn = 0; + uint8_t param[2] = {0}; + mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode; + mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write; + mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read; + mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set; + + pr_info("%s\n", __func__); + + mipi_set_cmd_mode(); + mipi_eotp_set(0,0); + + for(j = 0; j < 4; j++){ + param[0] = 0x01; + param[1] = 0x00; + mipi_force_write(0x04, param, 2); + read_rtn = mipi_force_read(0xda,1,&read_data[0]); + LCD_PRINT("lcd_vx5b3d_mipi read id 0xda value is 0x%x!\n",read_data[0]); + read_rtn = mipi_force_read(0xdb,1,&read_data[1]); + LCD_PRINT("lcd_vx5b3d_mipi read id 0xdb value is 0x%x!\n",read_data[1]); + read_rtn = mipi_force_read(0xdc,1,&read_data[2]); + LCD_PRINT("lcd_vx5b3d_mipi read id 0xdc value is 0x%x!\n",read_data[2]); + + // if((0x55 == read_data[0])&&(0xbc == read_data[1])&&(0x90 == read_data[2])){ + printk("lcd_vx5b3d_mipi read id success!\n"); + return 0x8282; + // } + } + + mipi_eotp_set(0,0); + + return 0; +} + + +static int32_t vx5b3d_enter_sleep(struct panel_spec *self, uint8_t is_sleep) +{ + pr_info("%s\n", __func__); + + vx5b3d_power(0); + + return 0; +} + +static struct panel_operations lcd_vx5b3d_mipi_operations = { + .panel_init = vx5b3d_mipi_init, + .panel_readid = vx5b3d_readid, + .panel_enter_sleep = vx5b3d_enter_sleep, +}; + +static struct timing_rgb lcd_vx5b3d_mipi_timing = { + .hfp = 123, + .hbp = 100, + .hsync = 120, + .vfp = 13, + .vbp = 10, + .vsync = 10, +}; + + +static struct info_mipi lcd_vx5b3d_mipi_info = { + .work_mode = SPRDFB_MIPI_MODE_VIDEO, + .video_bus_width = 24, /*18,16*/ + .lan_number = 4, + .phy_feq = 480*1000, + .h_sync_pol = SPRDFB_POLARITY_POS, + .v_sync_pol = SPRDFB_POLARITY_POS, + .de_pol = SPRDFB_POLARITY_POS, + .te_pol = SPRDFB_POLARITY_POS, + .color_mode_pol = SPRDFB_POLARITY_NEG, + .shut_down_pol = SPRDFB_POLARITY_NEG, + .timing = &lcd_vx5b3d_mipi_timing, + .ops = NULL, +}; + +struct panel_spec lcd_vx5b3d_mipi_spec = { + .width = 1024, + .height = 600, + .fps = 60, + .type = LCD_MODE_DSI, + .direction = LCD_DIRECT_NORMAL, + .suspend_mode = SEND_SLEEP_CMD, + .info = { + .mipi = &lcd_vx5b3d_mipi_info + }, + .ops = &lcd_vx5b3d_mipi_operations, +}; +struct panel_cfg lcd_vx5b3d_mipi = { + /* this panel can only be main lcd */ + .dev_id = SPRDFB_MAINLCD_ID, + .lcd_id = 0x8282, + .lcd_name = "lcd_vx5b3d_mipi", + .panel = &lcd_vx5b3d_mipi_spec, +}; +//temp code +static int __init lcd_vx5b3d_mipi_init(void) +{ + printk("zyun: %s\n", __func__); + i2c_add_driver(&quicklogic_i2c_driver); + return sprdfb_panel_register(&lcd_vx5b3d_mipi); +} +subsys_initcall(lcd_vx5b3d_mipi_init); + + +#ifdef CONFIG_OF +static int vx5b3d_parse_dt(struct vx5b3d_dt_data *data, struct device *dev) +{ + struct device_node *dNode = dev->of_node; + if (dNode == NULL) + return -ENODEV; + pdata->gpio_bridge_en = of_get_named_gpio(dNode, "gpio_bridge_en", 0); + pdata->gpio_bridge_rst = of_get_named_gpio(dNode, "gpio_bridge_rst", 0); + pdata->gpio_blic_en= of_get_named_gpio(dNode, "gpio_backlight_en", 0); + pdata->gpio_lcd_3v3_en = of_get_named_gpio(dNode, "gpio_lcd_3v3_en", 0); + if(pdata->gpio_bridge_en < 0 + || pdata->gpio_bridge_rst < 0 + || pdata->gpio_blic_en < 0 + || pdata->gpio_lcd_3v3_en < 0){ + pr_err("[%s] - get gpio error: bridge_en:%d, bridge_rst:%d, blic_en:%d, lcd_3v3_en:%d\n", + __func__, pdata->gpio_bridge_en, pdata->gpio_bridge_rst, pdata->gpio_blic_en, pdata->gpio_lcd_3v3_en); + return -ENODEV; + } + return 0; +} +#endif + +static int __init quicklogic_probe(struct i2c_client *client, + const struct i2c_device_id * id) +{ + static is_i2c_init=false; + /*globle data, defined in this file*/ + pdata = kzalloc(sizeof(struct vx5b3d_dt_data), GFP_KERNEL); + if(pdata == NULL){ + pr_err("[%s] line %d kzalloc fail!\n", __func__, __LINE__); + return -ENOMEM; + } +#ifdef CONFIG_OF + int ret = vx5b3d_parse_dt(pdata, &client->dev); + if(ret != 0){ + return ret; + } +#endif + if(is_i2c_init) + return 0; + if(client==NULL) + { + printk("zyun: I2C probe error!\n"); + return 0; + } + else + { + is_i2c_init=true; + printk("zyun: i2c client, addr=0x%x, name = %s\n", client->addr, client->name); + } + + g_client = client; + sprd_i2c_ctl_chg_clk(3, 400000); // up h/w i2c 1 400k + vx5b3d_power(1); + + return 0; +} +static int __exit quicklogic_remove(struct i2c_client *client) +{ + pr_info("%s\n", __func__); + + return 0; +} + + +#define QUICKLOGIC_DEV_NAME ("bridge") +static struct i2c_device_id quicklogic_id_table[] = { + { QUICKLOGIC_DEV_NAME, 0 }, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, quicklogic_id_table); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static const struct dev_pm_ops quicklogic_pm_ops = { +}; +#endif + +#ifdef CONFIG_OF +static const struct of_device_id quicklogic_of_match[] = { + { .compatible = "quicklogic,i2c", }, +}; +#endif + +struct i2c_driver quicklogic_i2c_driver = { + .id_table = quicklogic_id_table, + .probe = quicklogic_probe, + .remove = __exit_p(quicklogic_remove), + .driver = { + .owner = THIS_MODULE, + .name = QUICKLOGIC_DEV_NAME, +#ifdef CONFIG_HAS_EARLYSUSPEND + .pm = &quicklogic_pm_ops, +#endif + +#ifdef CONFIG_OF + .of_match_table = quicklogic_of_match, +#endif + }, +}; + +static int __init quicklogic_init(void) +{ + pr_info("%s, add quicklogic i2c\n", __func__); +// return i2c_add_driver(&quicklogic_i2c_driver); + return 0; +} + +static void __exit quicklogic_exit(void) +{ + pr_info("%s, delete quicklogic i2c\n", __func__); + i2c_del_driver(&quicklogic_i2c_driver); +} + +module_init(quicklogic_init); +module_exit(quicklogic_exit); + +MODULE_DESCRIPTION("QuickLogic Bridge Driver"); +MODULE_LICENSE("GPL"); |
