/*++ * linux/drivers/video/wmt/devices/lcd-gl5001w.c * WonderMedia video post processor (VPP) driver * * Copyright c 2012 WonderMedia Technologies, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * WonderMedia Technologies, Inc. * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C --*/ #include #include #include #include #include #include #include #include #include #include //wangaq+ #include "../lcd.h" //#include //#include #include //wangaq+ #include "../lcd.h"//yangchen add #define DRIVER_NAME "tc358768" #define I2C_ADDR 0x0E #define I2C_ADAPTER 0 #define DTYPE_DCS_SWRITE_0P 0X05 #define DTYPE_DCS_SWRITE_1P 0X15 #define DTYPE_DCS_LWRITE 0X39 #define DTYPE_GEN_LWRITE 0X29 #define DTYPE_GEN_SWRITE_2P 0X23 #define DTYPE_GEN_SWRITE_1P 0X13 #define DTYPE_GEN_SWRITE_0P 0X03 #define Gl5001w_Reset_Port WMT_PIN_GP62_SUSGPIO0 #define Tc358768_Reset_Port WMT_PIN_GP1_GPIO8 //#define BackLight_Power_PORT WMT_PIN_GP0_GPIO0 static void lcd_set_power(int status); static int save=1; //static struct work_struct cw500_resume_work; struct cw500_data { struct work_struct cw500_resume_work; }; struct cw500_data *data; #if 0 #define lcd_debug printk #else #define lcd_debug(fmt...) do { } while (0) #endif #define __unused __attribute__ ((unused)) static bool lcd_init_gl500 = false; typedef enum { //LCD_BTL504880, LCD_YT50F62C6, LCD_BT050TN, LCD_ILI9806, LCD_OTM8019A, LCD_MAX } lcd_panel_enum; struct lcd_deviceid_struct{ unsigned short id; unsigned char addr; unsigned char read_start; unsigned char len; }; static struct lcd_deviceid_struct lcd_deviceid[LCD_MAX]={ //{0x8009,0xa1,6,2}, {0x9805,0xd3,5,2}, {0x8009,0xa1,6,2}, {0x9816,0xd3,5,2}, {0x8019,0xa1,6,2} }; //LCD_YT50F62C6 static unsigned char LCD_YT50F62C6_CMD_FF_3DATA[] = {0xFF,0xFF,0x98,0x05}; //EXTC Command Set enable register static unsigned char LCD_YT50F62C6_CMD_FD_4DATA[] = {0xFD,0x03,0x13,0x44,0x00}; static unsigned char LCD_YT50F62C6_CMD_F8_15DATA[] = {0xF8,0x15,0x02,0x02,0x15,0x02,0x02,0x30,0x01,0x01,0x30,0x01,0x01,0x30,0x01,0x01}; static unsigned char LCD_YT50F62C6_CMD_B8_1DATA[] = {0xB8,0x73}; //DBI Type B Interface Setting static unsigned char LCD_YT50F62C6_CMD_F1_1DATA[] = {0xF1,0x00}; //Gate Modulation static unsigned char LCD_YT50F62C6_CMD_F2_3DATA[] = {0xF2,0x00,0x58,0x41}; //CR/EQ/PC static unsigned char LCD_YT50F62C6_CMD_FC_3DATA[] = {0xFC,0x04,0x0F,0x01}; static unsigned char LCD_YT50F62C6_CMD_FE_1DATA[] = {0xFE,0x19}; //SRAM Repair static unsigned char LCD_YT50F62C6_CMD_EB_2DATA[] = {0xEB,0x08,0x0F}; // 3 Gamma & Dithering static unsigned char LCD_YT50F62C6_CMD_E0_16DATA[] = {0xE0,0x00,0x02,0x07,0x10,0x10,0x1D,0x0F,0x0B,0x00,0x03,0x02,0x0B,0x0C,0x33,0x2F,0x00}; //P-Gamma static unsigned char LCD_YT50F62C6_CMD_E1_16DATA[] = {0xE1,0x00,0x02,0x07,0x10,0x10,0x17,0x0B,0x0B,0x00,0x03,0x02,0x0B,0x0C,0x33,0x2F,0x00}; //N-Gamma static unsigned char LCD_YT50F62C6_CMD_C1_4DATA[] = {0xC1,0x13,0x26,0x06,0x26}; //Power Control 1 static unsigned char LCD_YT50F62C6_CMD_C7_1DATA[] = {0xC7,0xC4}; static unsigned char LCD_YT50F62C6_CMD_B1_3DATA[] = {0xB1,0x00,0x12,0x14}; //Frame Rate Control static unsigned char LCD_YT50F62C6_CMD_B4_1DATA[] = {0xB4,0x02}; // 2 Dot Inversion static unsigned char LCD_YT50F62C6_CMD_36_1DATA[] = {0x36,0x0A}; //Memory Access static unsigned char LCD_YT50F62C6_CMD_3A_1DATA[] = {0x3A,0x77}; //16 & 18 & 24 bits static unsigned char LCD_YT50F62C6_CMD_21_0DATA[] = {0x21}; //Display Inv-On static unsigned char LCD_YT50F62C6_CMD_B0_1DATA[] = {0xB0,0x00}; //RGB I/F Polarity static unsigned char LCD_YT50F62C6_CMD_B6_1DATA[] = {0xB6,0x01}; //CPU/RGB I/F Select static unsigned char LCD_YT50F62C6_CMD_C2_1DATA[] = {0xC2,0x11}; static unsigned char LCD_YT50F62C6_CMD_11_0DATA[] = {0x11}; //Sleep out static unsigned char LCD_YT50F62C6_CMD_29_0DATA[] = {0x29}; //Display on static unsigned char LCD_YT50F62C6_CMD_2C_0DATA[] = {0x2C}; //Memory write //LCD_BT050TN static unsigned char LCD_BT050TN_CMD_FF00_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_FF00_3DATA[] = {0xFF,0x80,0x09,0x01}; static unsigned char LCD_BT050TN_CMD_FF80_0DATA[] = {0x00,0x80}; static unsigned char LCD_BT050TN_CMD_FF80_2DATA[] = {0xFF,0x80,0x09}; static unsigned char LCD_BT050TN_CMD_FF03_0DATA[] = {0x00,0x03}; static unsigned char LCD_BT050TN_CMD_FF03_1DATA[] = {0xFF,0x01}; static unsigned char LCD_BT050TN_CMD_2100_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_2100_1DATA[] = {0x21,0x00}; static unsigned char LCD_BT050TN_CMD_D800_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_D800_2DATA[] = {0xD8,0x6F,0x6F}; static unsigned char LCD_BT050TN_CMD_C582_0DATA[] = {0x00,0x82}; static unsigned char LCD_BT050TN_CMD_C582_1DATA[] = {0xC5,0xA3}; static unsigned char LCD_BT050TN_CMD_C181_0DATA[] = {0x00,0x81}; static unsigned char LCD_BT050TN_CMD_C181_1DATA[] = {0xC1,0x66}; static unsigned char LCD_BT050TN_CMD_C1A1_0DATA[] = {0x00,0xA1}; static unsigned char LCD_BT050TN_CMD_C1A1_1DATA[] = {0xC1,0x08}; static unsigned char LCD_BT050TN_CMD_B4C0_0DATA[] = {0x00,0xB4}; static unsigned char LCD_BT050TN_CMD_B4C0_1DATA[] = {0xC0,0x50}; static unsigned char LCD_BT050TN_CMD_C0A3_0DATA[] = {0x00,0xA3}; static unsigned char LCD_BT050TN_CMD_C0A3_1DATA[] = {0xC0,0x00}; static unsigned char LCD_BT050TN_CMD_C489_0DATA[] = {0x00,0x89}; static unsigned char LCD_BT050TN_CMD_C489_1DATA[] = {0xC4,0x08}; static unsigned char LCD_BT050TN_CMD_C481_0DATA[] = {0x00,0x81}; static unsigned char LCD_BT050TN_CMD_C481_1DATA[] = {0xC4,0x83}; static unsigned char LCD_BT050TN_CMD_C590_0DATA[] = {0x00,0x90}; static unsigned char LCD_BT050TN_CMD_C590_3DATA[] = {0xC5,0x96,0xA7,0x01}; static unsigned char LCD_BT050TN_CMD_C5B1_0DATA[] = {0x00,0xB1}; static unsigned char LCD_BT050TN_CMD_C5B1_1DATA[] = {0xC5,0xA9}; static unsigned char LCD_BT050TN_CMD_D900_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_D900_1DATA[] = {0xD9,0x15}; static unsigned char LCD_BT050TN_CMD_E100_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_E100_16DATA[] = {0xE1,0x02,0x08,0x0E,0x10,0x09,0x1D,0x0E,0x0E,0x00,0x05,0x02,0x07,0x0E,0x24,0x23,0x1D}; static unsigned char LCD_BT050TN_CMD_E200_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_E200_16DATA[] = {0xE2,0x02,0x08,0x0E,0x0F,0x09,0x1D,0x0E,0x0D,0x00,0x04,0x02,0x07,0x0E,0x25,0x23,0x1D}; static unsigned char LCD_BT050TN_CMD_0000_0DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_0000_1DATA[] = {0x00,0x00}; static unsigned char LCD_BT050TN_CMD_B3A1_0DATA[] = {0x00,0xA1}; static unsigned char LCD_BT050TN_CMD_B3A1_1DATA[] = {0xB3,0x10}; static unsigned char LCD_BT050TN_CMD_B3A7_0DATA[] = {0x00,0xA7}; static unsigned char LCD_BT050TN_CMD_B3A7_1DATA[] = {0xB3,0x10}; static unsigned char LCD_BT050TN_CMD_C090_0DATA[] = {0x00,0x90}; static unsigned char LCD_BT050TN_CMD_C090_6DATA[] = {0xC0,0x00,0x44,0x00,0x00,0x00,0x03}; static unsigned char LCD_BT050TN_CMD_C1A6_0DATA[] = {0x00,0xA6}; static unsigned char LCD_BT050TN_CMD_C1A6_3DATA[] = {0xC1,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CE80_0DATA[] = {0x00,0x80}; static unsigned char LCD_BT050TN_CMD_CE80_6DATA[] = {0xCE,0x87,0x03,0x00,0x86,0x03,0x00}; static unsigned char LCD_BT050TN_CMD_CE90_0DATA[] = {0x00,0x90}; static unsigned char LCD_BT050TN_CMD_CE90_6DATA[] = {0xCE,0x33,0x1E,0x00,0x33,0x1F,0x00}; static unsigned char LCD_BT050TN_CMD_CEA0_0DATA[] = {0x00,0xA0}; static unsigned char LCD_BT050TN_CMD_CEA0_14DATA[] = {0xCE,0x38,0x03,0x03,0x20,0x00,0x00,0x00,0x38,0x02,0x03,0x21,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CEB0_0DATA[] = {0x00,0xb0}; static unsigned char LCD_BT050TN_CMD_CEB0_14DATA[] = {0xCE,0x38,0x01,0x03,0x22,0x00,0x00,0x00,0x38,0x00,0x03,0x23,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CEC0_0DATA[] = {0x00,0xC0}; static unsigned char LCD_BT050TN_CMD_CEC0_14DATA[] = {0xCE,0x30,0x00,0x03,0x24,0x00,0x00,0x00,0x30,0x01,0x03,0x25,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CED0_0DATA[] = {0x00,0xD0}; static unsigned char LCD_BT050TN_CMD_CED0_14DATA[] = {0xCE,0x30,0x02,0x03,0x26,0x00,0x00,0x00,0x30,0x03,0x03,0x27,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CFC6_0DATA[] = {0x00,0xC6}; static unsigned char LCD_BT050TN_CMD_CFC6_2DATA[] = {0xCF,0x01,0x80}; static unsigned char LCD_BT050TN_CMD_CFC9_0DATA[] = {0x00,0xC9}; static unsigned char LCD_BT050TN_CMD_CFC9_1DATA[] = {0xCF,0x00}; static unsigned char LCD_BT050TN_CMD_CBC0_0DATA[] = {0x00,0xC0}; static unsigned char LCD_BT050TN_CMD_CBC0_15DATA[] = {0xCB,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CBD0_0DATA[] = {0x00,0xD0}; static unsigned char LCD_BT050TN_CMD_CBD0_15DATA[] = {0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04}; static unsigned char LCD_BT050TN_CMD_CBE0_0DATA[] = {0x00,0xE0}; static unsigned char LCD_BT050TN_CMD_CBE0_10DATA[] = {0xCB,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CC80_0DATA[] = {0x00,0x80}; static unsigned char LCD_BT050TN_CMD_CC80_10DATA[] = {0xCC,0x00,0x26,0x25,0x02,0x06,0x00,0x00,0x0A,0x0E,0x0C}; static unsigned char LCD_BT050TN_CMD_CC90_0DATA[] = {0x00,0x90}; static unsigned char LCD_BT050TN_CMD_CC90_15DATA[] = {0xCC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x25,0x01,0x05}; static unsigned char LCD_BT050TN_CMD_CCA0_0DATA[] = {0x00,0xA0}; static unsigned char LCD_BT050TN_CMD_CCA0_15DATA[] = {0xCC,0x00,0x00,0x09,0x0d,0x0b,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_CCB0_0DATA[] = {0x00,0xB0}; static unsigned char LCD_BT050TN_CMD_CCB0_10DATA[] = {0xCC,0x00,0x25,0x26,0x05,0x01,0x00,0x00,0x0F,0x0B,0x0D}; static unsigned char LCD_BT050TN_CMD_CCC0_0DATA[] = {0x00,0xC0}; static unsigned char LCD_BT050TN_CMD_CCC0_15DATA[] = {0xCC,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x26,0x06,0x02}; static unsigned char LCD_BT050TN_CMD_CCD0_0DATA[] = {0x00,0xD0}; static unsigned char LCD_BT050TN_CMD_CCD0_15DATA[] = {0xCC,0x00,0x00,0x10,0x0c,0x0e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static unsigned char LCD_BT050TN_CMD_21_0DATA[] = {0x21}; static unsigned char LCD_BT050TN_CMD_36_0DATA[] = {0x36}; static unsigned char LCD_BT050TN_CMD_00_0DATA[] = {0x00}; static unsigned char LCD_BT050TN_CMD_11_0DATA[] = {0x11}; static unsigned char LCD_BT050TN_CMD_29_0DATA[] = {0x29}; static unsigned char LCD_BT050TN_CMD_2C_0DATA[] = {0x2C}; //LCD_ILI9806 static unsigned char LCD_ILI9806_CMD_FF_3DATA[] = {0xFF,0xFF,0x98,0x16}; static unsigned char LCD_ILI9806_CMD_BA_1DATA[] = {0xBA,0x60}; static unsigned char LCD_ILI9806_CMD_F3_1DATA[] = {0xF3,0x70}; static unsigned char LCD_ILI9806_CMD_F9_3DATA[] = {0xF9,0x04,0xFB,0x84}; static unsigned char LCD_ILI9806_CMD_B0_1DATA[] = {0xB0,0x01}; static unsigned char LCD_ILI9806_CMD_BC_23DATA[] = {0xBC,0x01,0x0F,0x61,0xFE,0x01,0x01,0x0B,0x11,0x6C,0x63,0xFF,0xFF,0x01,0x01,0x00,0x00,0x55,0x53,0x01,0x00,0x00,0x43,0x0B}; static unsigned char LCD_ILI9806_CMD_BD_8DATA[] = {0xBD,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67}; static unsigned char LCD_ILI9806_CMD_BE_17DATA[] = {0xBE,0x13,0x11,0x00,0x22,0x22,0xBA,0xAB,0x22,0x22,0x22,0x66,0x22,0x22,0x22,0x22,0x22,0x22}; static unsigned char LCD_ILI9806_CMD_ED_2DATA[] = {0xED,0x7F,0x0F}; static unsigned char LCD_ILI9806_CMD_B4_3DATA[] = {0xB4,0x02,0x02,0x02}; static unsigned char LCD_ILI9806_CMD_B5_4DATA[] = {0xB5,0x14,0x14,0x04,0x00}; static unsigned char LCD_ILI9806_CMD_C0_3DATA[] = {0xC0,0x7F,0x0B,0x04}; static unsigned char LCD_ILI9806_CMD_C1_4DATA[] = {0xC1,0x17,0x78,0x78,0x20}; static unsigned char LCD_ILI9806_CMD_D7_1DATA[] = {0xD7,0x2A}; static unsigned char LCD_ILI9806_CMD_D8_1DATA[] = {0xD8,0x28}; static unsigned char LCD_ILI9806_CMD_FC_1DATA[] = {0xFC,0x05}; static unsigned char LCD_ILI9806_CMD_E0_16DATA[] = {0xE0,0x00,0x03,0x0A,0x0E,0x11,0x15,0x0A,0x08,0x04,0x09,0x07,0x0D,0x0D,0x2E,0x28,0x00}; static unsigned char LCD_ILI9806_CMD_E1_16DATA[] = {0xE1,0x00,0x02,0x09,0x0E,0x11,0x15,0x0A,0x09,0x04,0x09,0x08,0x0C,0x0D,0x2F,0x28,0x00}; static unsigned char LCD_ILI9806_CMD_D5_8DATA[] = {0xD5,0x09,0x0A,0x0D,0x0B,0xCB,0xA5,0x01,0x04}; static unsigned char LCD_ILI9806_CMD_F7_1DATA[] = {0xF7,0x89}; static unsigned char LCD_ILI9806_CMD_C7_1DATA[] = {0xC7,0x43}; static unsigned char LCD_ILI9806_CMD_36_1DATA[] = {0x36,0x00}; static unsigned char LCD_ILI9806_CMD_51_1DATA[] = {0x51,0xFF}; static unsigned char LCD_ILI9806_CMD_53_1DATA[] = {0x53,0x24}; static unsigned char LCD_ILI9806_CMD_55_1DATA[] = {0x55,0x03}; static unsigned char LCD_ILI9806_CMD_11_0DATA[] = {0x11}; static unsigned char LCD_ILI9806_CMD_29_0DATA[] = {0x29}; static unsigned char LCD_ILI9806_CMD_2C_0DATA[] = {0x2C}; //Memory write //OTM8019A static unsigned char LCD_OTM8019A_CMD_1[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_2[]= {0xFF,0x80,0x19,0x01}; static unsigned char LCD_OTM8019A_CMD_3[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_4[]= {0xFF,0x80,0x19}; static unsigned char LCD_OTM8019A_CMD_5[]= {0x00,0x90}; static unsigned char LCD_OTM8019A_CMD_6[]= {0xB3,0x02}; static unsigned char LCD_OTM8019A_CMD_7[]= {0x00,0x92}; static unsigned char LCD_OTM8019A_CMD_8[]= {0xB3,0x45}; static unsigned char LCD_OTM8019A_CMD_9[]= {0x00,0xA2}; static unsigned char LCD_OTM8019A_CMD_10[]= {0xC0,0x04,0x00,0x02}; static unsigned char LCD_OTM8019A_CMD_11[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_12[]= {0xC0,0x00,0x58,0x00,0x14,0x16}; static unsigned char LCD_OTM8019A_CMD_13[]= {0x00,0x90}; static unsigned char LCD_OTM8019A_CMD_14[]= {0xC0,0x00,0x15,0x00,0x00,0x00,0x03}; static unsigned char LCD_OTM8019A_CMD_15[]= {0x00,0xB4}; static unsigned char LCD_OTM8019A_CMD_16[]= {0xC0,0x70};//1+2 dot inversion static unsigned char LCD_OTM8019A_CMD_17[]= {0x00,0x81}; static unsigned char LCD_OTM8019A_CMD_18[]= {0xC1,0x33}; static unsigned char LCD_OTM8019A_CMD_19[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_20[]= {0xC4,0x30,0x83}; static unsigned char LCD_OTM8019A_CMD_21[]= {0x00,0x89}; static unsigned char LCD_OTM8019A_CMD_22[]= {0xC4,0x08}; static unsigned char LCD_OTM8019A_CMD_23[]= {0x00,0x82}; static unsigned char LCD_OTM8019A_CMD_24[]= {0xC5,0xB0}; static unsigned char LCD_OTM8019A_CMD_25[]= {0x00,0x90}; static unsigned char LCD_OTM8019A_CMD_26[]= {0xC5,0x4E,0x79,0x01,0x03}; static unsigned char LCD_OTM8019A_CMD_27[]= {0x00,0xB1}; static unsigned char LCD_OTM8019A_CMD_28[]= {0xC5,0xA9}; static unsigned char LCD_OTM8019A_CMD_29[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_30[]= {0xCE,0x87,0x03,0x00,0x85,0x03,0x00,0x86,0x03,0x00,0x84,0x03,0x00}; static unsigned char LCD_OTM8019A_CMD_31[]= {0x00,0xA0}; static unsigned char LCD_OTM8019A_CMD_32[]= {0xCE,0x38,0x03,0x03,0x58,0x00,0x00,0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_33[]= {0x00,0xB0}; static unsigned char LCD_OTM8019A_CMD_34[]= {0xCE,0x38,0x01,0x03,0x5A,0x00,0x00,0x00,0x38,0x00,0x03,0x5B,0x00,0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_35[]= {0x00,0xC0}; static unsigned char LCD_OTM8019A_CMD_36[]= {0xCE,0x30,0x00,0x03,0x5C,0x00,0x00,0x00,0x30,0x01,0x03,0x5D,0x00,0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_37[]= {0x00,0xD0}; static unsigned char LCD_OTM8019A_CMD_38[]= {0xCE,0x30,0x02,0x03,0x5E,0x00,0x00,0x00,0x30,0x03,0x03,0x5F,0x00,0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_39[]= {0x00,0xC7}; static unsigned char LCD_OTM8019A_CMD_40[]= {0xCF,0x00}; static unsigned char LCD_OTM8019A_CMD_41[]= {0x00,0xC9}; static unsigned char LCD_OTM8019A_CMD_42[]= {0xCF,0x00}; static unsigned char LCD_OTM8019A_CMD_43[]= {0x00,0xC4}; static unsigned char LCD_OTM8019A_CMD_44[]= {0xCB,0x01,0x01,0x01,0x01,0x01,0x01}; static unsigned char LCD_OTM8019A_CMD_45[]= {0x00,0xD9}; static unsigned char LCD_OTM8019A_CMD_46[]= {0xCB,0x00,0x00,0x01,0x01,0x01,0x01}; static unsigned char LCD_OTM8019A_CMD_47[]= {0x00,0xE0}; static unsigned char LCD_OTM8019A_CMD_48[]= {0xCB,0x01,0x01}; static unsigned char LCD_OTM8019A_CMD_49[]= {0x00,0x84}; static unsigned char LCD_OTM8019A_CMD_50[]= {0xCC,0x0C,0x0A,0x10,0x0E,0x03,0x04}; static unsigned char LCD_OTM8019A_CMD_51[]= {0x00,0x9E}; static unsigned char LCD_OTM8019A_CMD_52[]= {0xCC,0x00}; static unsigned char LCD_OTM8019A_CMD_53[]= {0x00,0xA0}; static unsigned char LCD_OTM8019A_CMD_54[]= {0xCC,0x00,0x02,0x01,0x0d,0x0f,0x09,0x0b}; static unsigned char LCD_OTM8019A_CMD_55[]= {0x00,0xB4}; static unsigned char LCD_OTM8019A_CMD_56[]= {0xCC,0x0D,0x0F,0x09,0x0B,0x02,0x01}; static unsigned char LCD_OTM8019A_CMD_57[]= {0x00,0xCE}; static unsigned char LCD_OTM8019A_CMD_58[]= {0xCC,0x85}; static unsigned char LCD_OTM8019A_CMD_59[]= {0x00,0xD0}; static unsigned char LCD_OTM8019A_CMD_60[]= {0xCC,0x05,0x03,0x04,0x0c,0x0a,0x10,0x0e}; static unsigned char LCD_OTM8019A_CMD_61[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_62[]= {0xD8,0x85,0x85}; static unsigned char LCD_OTM8019A_CMD_63[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_64[]= {0xD9,0x61}; static unsigned char LCD_OTM8019A_CMD_65[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_66[]= {0xE1,0x00,0x03,0x0a,0x1d,0x33,0x49,0x54,0x89,0x7a,0x8e,0x79,0x69,0x81,0x6d,0x73,0x6d,0x66,0x5d,0x52,0x00}; static unsigned char LCD_OTM8019A_CMD_67[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_68[]= {0xE2,0x00,0x04,0x0a,0x1d,0x33,0x49,0x54,0x89,0x7a,0x8e,0x79,0x69,0x81,0x6d,0x73,0x6d,0x66,0x5d,0x52,0x00}; static unsigned char LCD_OTM8019A_CMD_69[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_70[]= {0xC4,0x30}; static unsigned char LCD_OTM8019A_CMD_71[]= {0x00,0x98}; static unsigned char LCD_OTM8019A_CMD_72[]= {0xC0,0x00}; static unsigned char LCD_OTM8019A_CMD_73[]= {0x00,0xa9}; static unsigned char LCD_OTM8019A_CMD_74[]= {0xC0,0x06}; static unsigned char LCD_OTM8019A_CMD_75[]= {0x00,0xb0}; static unsigned char LCD_OTM8019A_CMD_76[]= {0xC1,0x20,0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_77[]= {0x00,0xe1}; static unsigned char LCD_OTM8019A_CMD_78[]= {0xC0,0x40,0x18}; static unsigned char LCD_OTM8019A_CMD_79[]= {0x00,0x80}; static unsigned char LCD_OTM8019A_CMD_80[]= {0xC1,0x03,0x33}; static unsigned char LCD_OTM8019A_CMD_81[]= {0x00,0xA0}; static unsigned char LCD_OTM8019A_CMD_82[]= {0xC1,0xe8}; static unsigned char LCD_OTM8019A_CMD_83[]= {0x00,0x90}; static unsigned char LCD_OTM8019A_CMD_84[]= {0xb6,0xb4}; static unsigned char LCD_OTM8019A_CMD_85[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_86[]= {0xfb,0x01}; static unsigned char LCD_OTM8019A_CMD_87[]= {0x00,0x00}; static unsigned char LCD_OTM8019A_CMD_88[]= {0xFF,0xFF,0xFF,0xFF}; static unsigned char LCD_OTM8019A_CMD_89[]= {0x11,0x00}; static unsigned char LCD_OTM8019A_CMD_90[]= {0x29,0x00}; //End of static struct i2c_client *tc358768_client; static inline int tc358768_rd_reg_32bits(uint32_t reg_addr) { int ret; struct i2c_msg msgs[2]; uint8_t buf[4]; struct i2c_client *client = tc358768_client; buf[0] = (reg_addr >> 8) & 0xff; buf[1] = reg_addr & 0xff; msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = 2; msgs[0].buf = buf; msgs[1].addr = client->addr; msgs[1].flags = I2C_M_RD; msgs[1].len = 2; msgs[1].buf = buf; ret = i2c_transfer(client->adapter, msgs, 2); if (ret < 0) { printk("%s:i2c_transfer fail =%d\n", __func__, ret); return -1; } ret = (buf[0] << 8) | buf[1]; return ret; } static inline int tc358768_wr_reg_32bits(uint32_t value) { struct i2c_msg msgs; int ret = -1; uint8_t buf[4]; struct i2c_client *client = tc358768_client; buf[0] = value>>24; buf[1] = value>>16; buf[2] = value>>8; buf[3] = value; msgs.addr = client->addr; msgs.flags = 0; msgs.len = 4; msgs.buf = buf; ret = i2c_transfer(client->adapter, &msgs, 1); if(ret < 0) printk("%d:i2c_transfer fail = %d\n",__LINE__, ret); return ret; } static int _tc358768_wr_regs_32bits(unsigned int reg_array[], int n) { int i = 0; lcd_debug("%s:%d\n", __func__, n); for(i = 0; i < n; i++) { if(reg_array[i] < 0x00020000) { if(reg_array[i] < 20000) udelay(reg_array[i]); else { mdelay(reg_array[i]/1000); } } else { tc358768_wr_reg_32bits(reg_array[i]); } } return 0; } #define tc358768_wr_regs_32bits(reg_array) \ _tc358768_wr_regs_32bits(reg_array, ARRAY_SIZE(reg_array)) static uint32_t initialize[] = { // ************************************************** // Initizlize -> Display On after power-on // ************************************************** // ************************************************** // Power on TC358768XBG according to recommended power-on sequence // Relase reset (RESX="H") // Start input REFCK and PCLK // ************************************************** // ************************************************** // TC358768XBG Software Reset // ************************************************** 0x00020001, //SYSctl, S/W Reset 10, 0x00020000, //SYSctl, S/W Reset release // ************************************************** // TC358768XBG PLL,Clock Setting // ************************************************** 0x00160063, //PLL Control Register 0 (PLL_PRD,PLL_FBD) 0x00180603, //PLL_FRS,PLL_LBWS, PLL oscillation enable 1000, 0x00180613, //PLL_FRS,PLL_LBWS, PLL clock out enable // ************************************************** // TC358768XBG DPI Input Control // ************************************************** 0x00060064, //FIFO Control Register // ************************************************** // TC358768XBG D-PHY Setting // ************************************************** 0x01400000, //D-PHY Clock lane enable 0x01420000, // 0x01440000, //D-PHY Data lane0 enable 0x01460000, // 0x01480000, //D-PHY Data lane1 enable 0x014A0000, // 0x014C0001, // 0x014E0001, // 0x01500001, // 0x01520001, // 0x01000002, // 0x01020000, // 0x01040000, // 0x01060002, // 0x01080002, // 0x010A0000, // 0x010C0002, // 0x010E0000, // 0x01100002, // 0x01120000, // // ************************************************** // TC358768XBG DSI-TX PPI Control // ************************************************** 0x02100A5A, //LINEINITCNT 0x02120000, // 0x02140002, //LPTXTIMECNT 0x02160000, // 0x02180E02, //TCLK_HEADERCNT 0x021A0000, // 0x021C0000, //TCLK_TRAILCNT 0x021E0000, // 0x02200002, //THS_HEADERCNT 0x02220000, // 0x02244650, //TWAKEUPCNT 0x02260000, // 0x02280000, //TCLK_POSTCNT 0x022A0000, // 0x022C0001, //THS_TRAILCNT 0x022E0000, // 0x02300005, //HSTXVREGCNT 0x02320000, // 0x02340007, //HSTXVREGEN enable 0x02360000, // 0x02380001, //DSI clock Enable/Disable during LP 0x023A0000, // 0x023C0002, //BTACNTRL1 0x023E0002, // 0x02040001, //STARTCNTRL 0x02060000, // // ************************************************** // TC358768XBG DSI-TX Timing Control // ************************************************** 0x06200001, //Sync Event mode setting Event mode 0x06220014, //V Control Register1 VBP 0x0624000C, //V Control Register2 not used 0x06260356, //V Control Register3 800 0x0628005E, //H Control Register1 0x062A003F, //H Control Register2 //0x062C0438, //H Control Register3 (480*18)/8=1080 0x062C05A0, //H Control Register3 (480*24)/8=1440 0x05180001, //DSI Start 0x051A0000, // }; static uint32_t start_dsi_hs_mode[] = { // ************************************************** // Set to HS mode // ************************************************** 0x05000083, //DSI lane setting, DSI mode=HS 0x0502A300, //bit set 0x05008000, //Switch to DSI mode 0x0502C300, // // ************************************************** // Host: RGB(DPI) input start // ************************************************** //0x00080047, //DSI-TX Format setting: RGB666 0x00080037, //DSI-TX Format setting//3 RGB888;4 RGB666 //0x0050001E, //DSI-TX Pixel stream packet Data Type setting 0x0050003E, //Packed Pixel Stream, 24-bit RGB, 8-8-8 Format 0x00320000, //HSYNC Polarity 0x00040040, //Configuration Control Register }; static inline void mipi_dsi_init(void) { tc358768_wr_regs_32bits(initialize); } static inline void mipi_dsi_hs_start(void) { tc358768_wr_regs_32bits(start_dsi_hs_mode); } static void tc_print(u32 addr) { lcd_debug("+++addr->%04x: %04x\n", addr, tc358768_rd_reg_32bits(addr)); } static int tc358768_command_tx_less8bytes(unsigned char type, unsigned char *regs, int n) { int i = 0; unsigned int command[] = { 0x06020000, 0x06040000, 0x06100000, 0x06120000, 0x06140000, 0x06160000, }; if(n <= 2) command[0] |= 0x1000; //short packet else { command[0] |= 0x4000; //long packet command[1] |= n; //word count byte } command[0] |= type; //data type lcd_debug("*cmd:\n"); lcd_debug("0x%08x\n", command[0]); lcd_debug("0x%08x\n", command[1]); for(i = 0; i < (n + 1)/2; i++) { command[i+2] |= regs[i*2]; if((i*2 + 1) < n) command[i+2] |= regs[i*2 + 1] << 8; lcd_debug("0x%08x\n", command[i+2]); } _tc358768_wr_regs_32bits(command, (n + 1)/2 + 2); tc358768_wr_reg_32bits(0x06000001); //Packet Transfer if(regs[0] == 0x29){ //tc358768_wr_reg_32bits(0x06000001); } //wait until packet is out i = 100; while(tc358768_rd_reg_32bits(0x0600) & 0x01) { if(i-- == 0) break; tc_print(0x0600); } //udelay(50); return 0; } static int __unused tc358768_command_tx_more8bytes_hs(unsigned char type, unsigned char regs[], int n) { int i = 0; unsigned int dbg_data = 0x00E80000, temp = 0; unsigned int command[] = { 0x05000080, // HS data 4 lane, EOT is added 0x0502A300, 0x00080001, 0x00500000, // Data ID setting 0x00220000, // Transmission byte count= byte 0x00E08000, // Enable I2C/SPI write to VB 0x00E20048, // Total word count = 0x48 (max 0xFFF). // This value should be adjusted considering // trade off between transmission time and // transmission start/stop time delay 0x00E4007F, // Vertical blank line = 0x7F }; command[3] |= type; //data type command[4] |= n & 0xffff; //Transmission byte count tc358768_wr_regs_32bits(command); for(i = 0; i < (n + 1)/2; i++) { temp = dbg_data | regs[i*2]; if((i*2 + 1) < n) temp |= (regs[i*2 + 1] << 8); lcd_debug("0x%08x\n", temp); tc358768_wr_reg_32bits(temp); } if((n % 4 == 1) || (n % 4 == 2)) //4 bytes align tc358768_wr_reg_32bits(dbg_data); tc358768_wr_reg_32bits(0x00E0C000); //Start command transmisison tc358768_wr_reg_32bits(0x00E00000); //Stop command transmission. This setting should be done just after above setting to prevent multiple output udelay(200); //Re-Initialize //tc358768_wr_regs_32bits(re_initialize); return 0; } static int tc358768_command_tx_more8bytes_lp(unsigned char type, unsigned char regs[], int n) { int i = 0; unsigned int dbg_data = 0x00E80000, temp = 0; unsigned int command[] = { 0x00080001, 0x00500000, //Data ID setting 0x00220000, //Transmission byte count= byte 0x00E08000, //Enable I2C/SPI write to VB }; command[1] |= type; //data type command[2] |= n & 0xffff; //Transmission byte count tc358768_wr_regs_32bits(command); for(i = 0; i < (n + 1)/2; i++) { temp = dbg_data | regs[i*2]; if((i*2 + 1) < n) temp |= (regs[i*2 + 1] << 8); lcd_debug("0x%08x\n", temp); tc358768_wr_reg_32bits(temp); } if((n % 4 == 1) || (n % 4 == 2)) //4 bytes align tc358768_wr_reg_32bits(dbg_data); tc358768_wr_reg_32bits(0x00E0E000); //Start command transmisison udelay(1000); tc358768_wr_reg_32bits(0x00E02000); //Keep Mask High to prevent short packets send out tc358768_wr_reg_32bits(0x00E00000); //Stop command transmission. This setting should be done just after above setting to prevent multiple output udelay(10); return 0; } int _tc358768_send_packet(unsigned char type, unsigned char regs[], int n) { if(n <= 8) { tc358768_command_tx_less8bytes(type, regs, n); } else { //tc358768_command_tx_more8bytes_hs(type, regs, n); tc358768_command_tx_more8bytes_lp(type, regs, n); } return 0; } /* * The DCS is separated into two functional areas: * the User Command Set and the Manufacturer Command Set. * Each command is an eight-bit code with 00h to AFh assigned to * the User Command Set and all other codes assigned to * the Manufacturer Command Set. */ int _mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { unsigned char type = 0; if(n == 1) { type = DTYPE_DCS_SWRITE_0P; } else if (n == 2) { type = DTYPE_DCS_SWRITE_1P; } else if (n > 2) { type = DTYPE_DCS_LWRITE; } _tc358768_send_packet(type, regs, n); return 0; } static int tc358768_command_read_bytes(unsigned char addr,unsigned char *regs, int n) { unsigned short *data = (unsigned short *)regs,i; unsigned int command[] = { 0x06021037, 0x06040000, 0x06100000, 0x06000001, 0x06021000, 0x06040000, 0x06100000, 0x06000001, }; lcd_debug("%s start addr=0x%x\n",__FUNCTION__,addr); command[2] |= 32; command[4] |= 0x14; command[6] |= addr; _tc358768_wr_regs_32bits(command,4); udelay(100); tc358768_wr_reg_32bits(0x05040010); tc358768_wr_reg_32bits(0x05060000); udelay(100); _tc358768_wr_regs_32bits(&command[4],4); while(n-- > 0){ *data = (unsigned short)tc358768_rd_reg_32bits(0x0430); //printf("%s *data=0x%x\n",__FUNCTION__,*data); data++; *data = (unsigned short)tc358768_rd_reg_32bits(0x0432); //printf("%s *data=0x%x\n",__FUNCTION__,*data); data++; udelay(100); } return 0; } static lcd_panel_enum tc358768_check_lcd_type(void) { unsigned char data[50]={0},i=0; int lcd_id; for(i=0;idev.parent); int ret = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { dev_warn(&adapter->dev, "I2C-Adapter doesn't support I2C_FUNC_I2C\n"); return -EIO; } tc358768_client = client; return ret; } static int tc358768_remove(struct i2c_client *client) { return 0; } static const struct i2c_device_id tc358768_id[] = { { DRIVER_NAME, 0 }, {}, }; MODULE_DEVICE_TABLE(i2c, tc358768_id); static void cw500_resume_work_func(struct work_struct *work) { save=0; //printk("-cw500_resume_work_func-\n"); lcd_set_enable(1); lcd_gl5001w_power_on(); return NULL; } static int get_gpio_lcd_gl5001w(void) { int ret = 0; ret = gpio_request(Gl5001w_Reset_Port,"Gl5001w_Reset_Port"); if (ret){ printk("gpio_request Gl5001w_Reset_Port for GL5001W failed\n"); goto err_get; } ret = gpio_request(Tc358768_Reset_Port,"Tc358768_Reset_Port"); if (ret){ printk("gpio_request Tc358768_Reset_Port for Tc358768 failed\n"); goto err_get; } //ret = gpio_request(BackLight_Power_PORT,"BackLight_Power_PORT"); //if (ret){ // printk("gpio_request BackLight_Power_PORT for backlight failed\n"); // goto err_get; //} return 0; err_get: return -1; } static void put_gpio_lcd_gl5001w(void) { gpio_free(Gl5001w_Reset_Port); gpio_free(Tc358768_Reset_Port); //gpio_free(BackLight_Power_PORT); return; } static int cw500_gl5001_suspend(struct i2c_client *c, pm_message_t state) { save=1; printk("-cw500_gl5001_suspend-\n"); put_gpio_lcd_gl5001w(); return 0; } static int cw500_gl5001_resume(struct i2c_client *c) { printk("-cw500_gl5001_resume\n"); get_gpio_lcd_gl5001w(); schedule_work(&data->cw500_resume_work); return 0; } static struct i2c_driver tc358768_driver = { .driver = { .name = DRIVER_NAME, }, .probe = tc358768_probe, .remove = __devexit_p(tc358768_remove), .id_table = tc358768_id, .resume= cw500_gl5001_resume, .suspend= cw500_gl5001_suspend, }; static void lcd_set_power(int status) { if (!lcd_init_gl500) { return; } if (save==0) { return; } if (status == LCD_POWER_ON) { lcd_gl5001w_power_on(); lcd_init_gl500 = false; } } static struct lcd_parm_t lcd_gl5001w_parm = { //.name = "GL5001W", //.fps = 60, /* frame per second */ .bits_per_pixel = 24, .capability = 0, .width = 480, .height = 854, .vmode = { .name = "GL5001W", // mipi_480x800 .refresh = 60, .xres = 480, .yres = 854, .pixclock = KHZ2PICOS(26000), //pixel_clock .left_margin = 20, //hbp .right_margin = 30, //hfp .upper_margin = 12, //vbp .lower_margin = 8, //vfp .hsync_len = 10, //hsync .vsync_len = 8, //vsync .sync = 0, //? .vmode = 0, .flag = 0, }, //.initial = dummy_call_path, //.uninitial = lcd_gl5001w_power_off, //.set_power = lcd_set_power, }; static struct lcd_parm_t *lcd_gl5001w_get_parm(int arg) { return &lcd_gl5001w_parm; } static int wmt_check_devices(void) { int ret = 0; int param[7]; char buf[96] = {0}; int len = sizeof(buf); ret = wmt_getsyspara("wmt.display.fb0", buf, &len); if (ret) { pr_err("Read wmt.display.param Failed.\n"); return -ENODEV; } ret = vpp_parse_param(buf, param, 6, 0); if (ret < 2) return -ENODEV; if (param[3] != LCD_GL5001W) return -ENODEV; return 0; } static struct i2c_board_info i2c_board_info = { I2C_BOARD_INFO(DRIVER_NAME, I2C_ADDR), }; #if 0 static int tc358768_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { lcd_gl5001w_power_on(); return 0; } #endif static int __init gl5001w_init(void) { int ret; struct i2c_client *client; struct i2c_adapter *adap; unsigned char buf[40]; int buflen = 40; unsigned int value; char *endp; if(wmt_getsyspara("wmt.support.lcd.gl5001w", buf, &buflen) == 0) { value = simple_strtoul(buf, &endp, 0); if(value == 0) return -1; } else return -1; ret = gpio_request(Gl5001w_Reset_Port,"Gl5001w_Reset_Port"); if (ret){ printk("gpio_request Gl5001w_Reset_Port for GL5001W failed\n"); goto err_get; } ret = gpio_request(Tc358768_Reset_Port,"Tc358768_Reset_Port"); if (ret){ printk("gpio_request Tc358768_Reset_Port for Tc358768 failed\n"); goto err_get; } //ret = gpio_request(BackLight_Power_PORT,"BackLight_Power_PORT"); //if (ret){ // printk("gpio_request BackLight_Power_PORT for backlight failed\n"); // goto err_get; //} data = kzalloc(sizeof(struct cw500_data), GFP_KERNEL); INIT_WORK(&data->cw500_resume_work, cw500_resume_work_func); ret = wmt_check_devices(); if (ret) { pr_info("LCD GL5001W not found\n"); return -ENODEV; } adap = i2c_get_adapter(I2C_ADAPTER); if (!adap) return -ENODEV; client = i2c_new_device(adap, &i2c_board_info); i2c_put_adapter(adap); if (!client) { printk("i2c_new_device error\n"); return -ENODEV; } ret = i2c_add_driver(&tc358768_driver); if (ret) { return -EIO; } ret = lcd_panel_register(LCD_GL5001W,(void *) lcd_gl5001w_get_parm); if (ret) { i2c_del_driver(&tc358768_driver); return -ENODEV; } /* for debug */ //create_proc_read_entry(DRIVER_NAME, 0666, NULL, tc358768_proc, NULL); return 0; err_get: return -1; } static void __exit gl5001w_exit(void) { struct i2c_client *client = tc358768_client; gpio_free(Gl5001w_Reset_Port); gpio_free(Tc358768_Reset_Port); //gpio_free(BackLight_Power_PORT); i2c_unregister_device(client); return i2c_del_driver(&tc358768_driver); } module_init(gl5001w_init); module_exit(gl5001w_exit); MODULE_DESCRIPTION("WonderMedia GL5001W LCD Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("i2c:gl5001w");