273 lines
6.6 KiB
C
273 lines
6.6 KiB
C
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* 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 "msm_fb.h"
|
|
#include "mipi_dsi.h"
|
|
#include "mipi_truly.h"
|
|
|
|
static struct msm_panel_common_pdata *mipi_truly_pdata;
|
|
static struct dsi_buf truly_tx_buf;
|
|
static struct dsi_buf truly_rx_buf;
|
|
|
|
#define TRULY_CMD_DELAY 0
|
|
#define TRULY_SLEEP_OFF_DELAY 150
|
|
#define TRULY_DISPLAY_ON_DELAY 150
|
|
#define GPIO_TRULY_LCD_RESET 129
|
|
|
|
static int prev_bl = 17;
|
|
|
|
static char extend_cmd_enable[4] = {0xB9, 0xFF, 0x83, 0x69};
|
|
static char display_setting[16] = {
|
|
0xB2, 0x00, 0x23, 0x62,
|
|
0x62, 0x70, 0x00, 0xFF,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x03, 0x03, 0x00, 0x01,
|
|
};
|
|
static char wave_cycle_setting[6] = {0xB4, 0x00, 0x1D, 0x5F, 0x0E, 0x06};
|
|
static char gip_setting[27] = {
|
|
0xD5, 0x00, 0x04, 0x03,
|
|
0x00, 0x01, 0x05, 0x1C,
|
|
0x70, 0x01, 0x03, 0x00,
|
|
0x00, 0x40, 0x06, 0x51,
|
|
0x07, 0x00, 0x00, 0x41,
|
|
0x06, 0x50, 0x07, 0x07,
|
|
0x0F, 0x04, 0x00,
|
|
};
|
|
static char power_setting[20] = {
|
|
0xB1, 0x01, 0x00, 0x34,
|
|
0x06, 0x00, 0x0F, 0x0F,
|
|
0x2A, 0x32, 0x3F, 0x3F,
|
|
0x07, 0x3A, 0x01, 0xE6,
|
|
0xE6, 0xE6, 0xE6, 0xE6,
|
|
};
|
|
static char vcom_setting[3] = {0xB6, 0x56, 0x56};
|
|
static char pannel_setting[2] = {0xCC, 0x02};
|
|
static char gamma_setting[35] = {
|
|
0xE0, 0x00, 0x1D, 0x22,
|
|
0x38, 0x3D, 0x3F, 0x2E,
|
|
0x4A, 0x06, 0x0D, 0x0F,
|
|
0x13, 0x15, 0x13, 0x16,
|
|
0x10, 0x19, 0x00, 0x1D,
|
|
0x22, 0x38, 0x3D, 0x3F,
|
|
0x2E, 0x4A, 0x06, 0x0D,
|
|
0x0F, 0x13, 0x15, 0x13,
|
|
0x16, 0x10, 0x19,
|
|
};
|
|
static char mipi_setting[14] = {
|
|
0xBA, 0x00, 0xA0, 0xC6,
|
|
0x00, 0x0A, 0x00, 0x10,
|
|
0x30, 0x6F, 0x02, 0x11,
|
|
0x18, 0x40,
|
|
};
|
|
static char exit_sleep[2] = {0x11, 0x00};
|
|
static char display_on[2] = {0x29, 0x00};
|
|
static char display_off[2] = {0x28, 0x00};
|
|
static char enter_sleep[2] = {0x10, 0x00};
|
|
|
|
static struct dsi_cmd_desc truly_display_off_cmds[] = {
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 10, sizeof(display_off), display_off},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 120, sizeof(enter_sleep), enter_sleep}
|
|
};
|
|
|
|
static struct dsi_cmd_desc truly_display_on_cmds[] = {
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(extend_cmd_enable), extend_cmd_enable},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(display_setting), display_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(wave_cycle_setting), wave_cycle_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(gip_setting), gip_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(power_setting), power_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(vcom_setting), vcom_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(pannel_setting), pannel_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(gamma_setting), gamma_setting},
|
|
{DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
|
|
sizeof(mipi_setting), mipi_setting},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, TRULY_SLEEP_OFF_DELAY,
|
|
sizeof(exit_sleep), exit_sleep},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, TRULY_DISPLAY_ON_DELAY,
|
|
sizeof(display_on), display_on},
|
|
};
|
|
|
|
static int mipi_truly_lcd_on(struct platform_device *pdev)
|
|
{
|
|
struct msm_fb_data_type *mfd;
|
|
struct dcs_cmd_req cmdreq;
|
|
|
|
mfd = platform_get_drvdata(pdev);
|
|
|
|
if (!mfd)
|
|
return -ENODEV;
|
|
if (mfd->key != MFD_KEY)
|
|
return -EINVAL;
|
|
|
|
msleep(20);
|
|
|
|
memset(&cmdreq, 0, sizeof(cmdreq));
|
|
cmdreq.cmds = truly_display_on_cmds;
|
|
cmdreq.cmds_cnt = ARRAY_SIZE(truly_display_on_cmds);
|
|
cmdreq.flags = CMD_REQ_COMMIT;
|
|
cmdreq.rlen = 0;
|
|
cmdreq.cb = NULL;
|
|
mipi_dsi_cmdlist_put(&cmdreq);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mipi_truly_lcd_off(struct platform_device *pdev)
|
|
{
|
|
struct msm_fb_data_type *mfd;
|
|
struct dcs_cmd_req cmdreq;
|
|
|
|
mfd = platform_get_drvdata(pdev);
|
|
|
|
if (!mfd)
|
|
return -ENODEV;
|
|
if (mfd->key != MFD_KEY)
|
|
return -EINVAL;
|
|
|
|
memset(&cmdreq, 0, sizeof(cmdreq));
|
|
cmdreq.cmds = truly_display_off_cmds;
|
|
cmdreq.cmds_cnt = ARRAY_SIZE(truly_display_off_cmds);
|
|
cmdreq.flags = CMD_REQ_COMMIT;
|
|
cmdreq.rlen = 0;
|
|
cmdreq.cb = NULL;
|
|
mipi_dsi_cmdlist_put(&cmdreq);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define BL_LEVEL 17
|
|
static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
|
|
{
|
|
int step = 0, i = 0;
|
|
int bl_level = mfd->bl_level;
|
|
|
|
/* real backlight level, 1 - max, 16 - min, 17 - off */
|
|
bl_level = BL_LEVEL - bl_level;
|
|
|
|
if (bl_level > prev_bl) {
|
|
step = bl_level - prev_bl;
|
|
if (bl_level == BL_LEVEL)
|
|
step--;
|
|
} else if (bl_level < prev_bl) {
|
|
step = bl_level + 16 - prev_bl;
|
|
} else {
|
|
pr_debug("%s: no change\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (bl_level == BL_LEVEL) {
|
|
/* turn off backlight */
|
|
mipi_truly_pdata->pmic_backlight(0);
|
|
} else {
|
|
if (prev_bl == BL_LEVEL) {
|
|
/* turn on backlight */
|
|
mipi_truly_pdata->pmic_backlight(1);
|
|
udelay(30);
|
|
}
|
|
/* adjust backlight level */
|
|
for (i = 0; i < step; i++) {
|
|
mipi_truly_pdata->pmic_backlight(0);
|
|
udelay(1);
|
|
mipi_truly_pdata->pmic_backlight(1);
|
|
udelay(1);
|
|
}
|
|
}
|
|
msleep(20);
|
|
prev_bl = bl_level;
|
|
|
|
return;
|
|
}
|
|
|
|
static int __devinit mipi_truly_lcd_probe(struct platform_device *pdev)
|
|
{
|
|
if (pdev->id == 0) {
|
|
mipi_truly_pdata = pdev->dev.platform_data;
|
|
return 0;
|
|
}
|
|
|
|
msm_fb_add_device(pdev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct platform_driver this_driver = {
|
|
.probe = mipi_truly_lcd_probe,
|
|
.driver = {
|
|
.name = "mipi_truly",
|
|
},
|
|
};
|
|
|
|
static struct msm_fb_panel_data truly_panel_data = {
|
|
.on = mipi_truly_lcd_on,
|
|
.off = mipi_truly_lcd_off,
|
|
.set_backlight = mipi_truly_set_backlight,
|
|
};
|
|
|
|
static int ch_used[3];
|
|
|
|
int mipi_truly_device_register(struct msm_panel_info *pinfo,
|
|
u32 channel, u32 panel)
|
|
{
|
|
struct platform_device *pdev = NULL;
|
|
int ret;
|
|
|
|
if ((channel >= 3) || ch_used[channel])
|
|
return -ENODEV;
|
|
|
|
ch_used[channel] = TRUE;
|
|
|
|
pdev = platform_device_alloc("mipi_truly", (panel << 8)|channel);
|
|
|
|
if (!pdev)
|
|
return -ENOMEM;
|
|
|
|
truly_panel_data.panel_info = *pinfo;
|
|
|
|
ret = platform_device_add_data(pdev, &truly_panel_data,
|
|
sizeof(truly_panel_data));
|
|
if (ret) {
|
|
pr_err("%s: platform_device_add_data failed!\n", __func__);
|
|
goto err_device_put;
|
|
}
|
|
|
|
ret = platform_device_add(pdev);
|
|
|
|
if (ret) {
|
|
pr_err("%s: platform_device_register failed!\n", __func__);
|
|
goto err_device_put;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_device_put:
|
|
platform_device_put(pdev);
|
|
return ret;
|
|
}
|
|
|
|
static int __init mipi_truly_lcd_init(void)
|
|
{
|
|
mipi_dsi_buf_alloc(&truly_tx_buf, DSI_BUF_SIZE);
|
|
mipi_dsi_buf_alloc(&truly_rx_buf, DSI_BUF_SIZE);
|
|
|
|
return platform_driver_register(&this_driver);
|
|
}
|
|
|
|
module_init(mipi_truly_lcd_init);
|