/* drivers/video/sc8825/lcd_st7701_mipi.c
*
* Support for st7701 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,0x77,0x01,0x00,0x00,0x10}},
{LCM_SEND(5), {3,0,0xC0,0x77,0x00}},
{LCM_SEND(5), {3,0,0xC1,0x0B,0x02}},
{LCM_SEND(5), {3,0,0xC2,0x07,0x02}},
{LCM_SEND(4), {2,0,0xCC,0x30}},
//-------------------------------------Gamma Cluster Setting-------------------------------------------//
{LCM_SEND(19), {17,0,0xB0,0x00,0x06,0x0F,0x0A,0x0F,0x06,0x42,0x09,0x09,0x5F,0x05,0x12,0x10,0x25,0x2B,0x12}},
{LCM_SEND(19), {17,0,0xB1,0x00,0x06,0x0F,0x0A,0x0F,0x05,0x42,0x09,0x09,0x5F,0x04,0x12,0x10,0x25,0x2B,0x12}},
{LCM_SEND(8), {6,0,0xFF,0x77,0x01,0x00,0x00,0x11}},
{LCM_SEND(4), {2,0,0xB0,0x3D}},
//-------------------------------------------Vcom Setting---------------------------------------------------//
{LCM_SEND(4), {2,0,0xB1,0x20}},
//-----------------------------------------End Vcom Setting-----------------------------------------------//
{LCM_SEND(4), {2,0,0xB2,0x07}},
{LCM_SEND(4), {2,0,0xB3,0x80}},
{LCM_SEND(4), {2,0,0xB5,0x47}},
{LCM_SEND(4), {2,0,0xB7,0x85}},
{LCM_SEND(4), {2,0,0xB8,0x23}},
{LCM_SEND(4), {2,0,0xB9,0x10}},
{LCM_SEND(4), {2,0,0xC1,0x78}},
{LCM_SEND(4), {2,0,0xC2,0x78}},
{LCM_SEND(4), {2,0,0xD0,0x88}},
//{LCM_SEND(8), {6,0,0xFF,0x77,0x01,0x00,0x00,0x11}},
//---------------------------------End Power Control Registers Initial -------------------------------//
//---------------------------------------------GIP Setting----------------------------------------------------//
{LCM_SEND(6), {4,0,0xE0,0x00,0x00,0x02}},
{LCM_SEND(14), {12,0,0xE1,0x02,0x8C,0x04,0x8C,0x01,0x8C,0x03,0x8C,0x00,0x44,0x44}},
{LCM_SEND(16), {14,0,0xE2,0x00,0x00,0x00,0x00,0x00,0x8C,0x00,0x8C,0x00,0x8C,0x00,0x8C,0x00}},
{LCM_SEND(7), {5,0,0xE3,0x00,0x00,0x33,0x33}},
{LCM_SEND(5), {3,0,0xE4,0x44,0x44}},
{LCM_SEND(19), {17,0,0xE5,0x04,0xCA,0x8C,0x8C,0x06,0xCC,0x8C,0x8C,0x08,0xCE,0x8C,0x8C,0x0A,0xD0,0x8C,0x8C}},
{LCM_SEND(7), {5,0,0xE6,0x00,0x00,0x33,0x33}},
{LCM_SEND(5), {3,0,0xE7,0x44,0x44}},
{LCM_SEND(19), {17,0,0xE8,0x03,0xC9,0x8C,0x8C,0x05,0xCB,0x8C,0x8C,0x07,0xCD,0x8C,0x8C,0x09,0xCF,0x8C,0x8C}},
{LCM_SEND(10), {8,0,0xEB,0x02,0x00,0xE4,0xE4,0x44,0x00,0x00}},
{LCM_SEND(5), {3,0,0xEC,0x00,0x00}},
{LCM_SEND(19), {17,0,0xED,0xFB,0x10,0xFA,0xC6,0x74,0x5F,0xFF,0xFF,0xFF,0xFF,0xF5,0x47,0x6C,0xAF,0x10,0xBF}},
//---------------------------------------------End Setting-----------------------------------------------//
//------------------------------ Power Control Registers Initial End-----------------------------------//
//------------------------------------------Bank1 Setting----------------------------------------------------//
{LCM_SEND(8), {6,0,0xFF,0x77,0x01,0x00,0x00,0x00}},
{LCM_SEND(1), {0x11}},
{LCM_SLEEP(120)},
{LCM_SEND(1),{0x29}},
{LCM_SLEEP(50)},
};
static LCM_Init_Code sleep_out[] = {
{LCM_SEND(1), {0x11}},
{LCM_SLEEP(120)},
{LCM_SEND(1), {0x29}},
{LCM_SLEEP(20)},
};
static LCM_Init_Code sleep_in[] = {
{LCM_SEND(1), {0x28}},
{LCM_SLEEP(120)},
{LCM_SEND(1), {0x10}},
{LCM_SLEEP(20)},
};
static LCM_Force_Cmd_Code rd_prep_code[]={
{0x39, {LCM_SEND(8), {6, 0,0xFF,0x77,0x01,0x00,0x00,0x00}}},
{0x37, {LCM_SEND(2), {0x3, 0}}},
};
static LCM_Force_Cmd_Code rd_prep_code_1[]={
{0x37, {LCM_SEND(2), {0x1, 0}}},
};
static int32_t st7701_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;
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){
msleep(init->tag & LCM_TAG_MASK);
}
init++;
}
mipi_eotp_set(1,1);
return 0;
}
static uint32_t st7701_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;
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(0xA1, 2,(uint8_t *)read_data);
if((0x88 == read_data[0])&&(0x02 == read_data[1])){
mipi_eotp_set(1,1);
return 0x8802;
}
}
mipi_eotp_set(1,1);
return 0x0;
}
static struct panel_operations lcd_st7701_mipi_operations = {
.panel_init = st7701_mipi_init,
.panel_readid = st7701_readid,
};
static struct timing_rgb lcd_st7701_mipi_timing = {
.hfp = 50, /* unit: pixel */
.hbp =50,
.hsync = 10,
.vfp = 18,//20, /*unit: line*/18
.vbp = 10,//8,
.vsync = 4,//4,
};
static struct info_mipi lcd_st7701_mipi_info = {
.work_mode = SPRDFB_MIPI_MODE_VIDEO,
.video_bus_width = 24, /*18,16*/
.lan_number = 2,
.phy_feq = 450*1000,//500
.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_st7701_mipi_timing,
.ops = NULL,
};
struct panel_spec lcd_st7701s_mipi_spec = {
//.cap = PANEL_CAP_NOT_TEAR_SYNC,
.width = 480,
.height = 960,
.fps = 60,
.type = LCD_MODE_DSI,
.direction = LCD_DIRECT_NORMAL,
.is_clean_lcd = true,
.reset_timing = {5, 15, 120},
.info = {
.mipi = &lcd_st7701_mipi_info
},
.ops = &lcd_st7701_mipi_operations,
};
struct panel_cfg lcd_st7701_mipi = {
/* this panel can only be main lcd */
.dev_id = SPRDFB_MAINLCD_ID,
.lcd_id = 0x8802,
.lcd_name = "lcd_st7701_mipi",
.panel = &lcd_st7701s_mipi_spec,
};
static int __init lcd_st7701_mipi_init(void)
{
- 1
- 2
前往页