diff options
Diffstat (limited to 'drivers/video/sprdfb/lcd/lcd_vx5b3d_mipi.c')
| -rwxr-xr-x | drivers/video/sprdfb/lcd/lcd_vx5b3d_mipi.c | 965 |
1 files changed, 965 insertions, 0 deletions
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"); |
