Commit e5bb1ba6 authored by Imre Deak's avatar Imre Deak Committed by Juha Yrjola

ARM: OMAP: omapfb: update LCD drivers

- replace custom debugging stuff with the default kernel one
- pass a pointer to the LCD object instance to member functions
- rename lcd_lph8923 to the more generic lcd_mipid
- use SPI_MODE_1 instead of SPI_MODE_0 in lcd_mipid
- add ESD spike recovery support to lcd_mipid
Signed-off-by: default avatarImre Deak <ext-imre.deak@nokia.com>
Signed-off-by: default avatarJuha Yrjola <juha.yrjola@solidboot.com>
parent e563dc81
......@@ -30,44 +30,32 @@
#include <asm/arch/mux.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
/* #define USE_35INCH_LCD 1 */
#include "debug.h"
static int apollon_panel_init(struct omapfb_device *fbdev)
static int apollon_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void apollon_panel_cleanup(void)
static void apollon_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int apollon_panel_enable(void)
static int apollon_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
/* configure LCD PWR_EN */
omap_cfg_reg(M21_242X_GPIO11);
DBGLEAVE(1);
return 0;
}
static void apollon_panel_disable(void)
static void apollon_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static unsigned long apollon_panel_get_caps(void)
static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -109,26 +97,22 @@ struct lcd_panel apollon_panel = {
static int apollon_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&apollon_panel);
return 0;
}
static int apollon_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int apollon_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int apollon_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -27,9 +27,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
#include "../drivers/ssi/omap-uwire.h"
#define MODULE_NAME "omapfb-lcd_h2"
......@@ -42,8 +39,6 @@ static int tsc2101_write_reg(int page, int reg, u16 data)
u16 cmd;
int r;
DBGENTER(1);
cmd = ((page & 3) << 11) | ((reg & 0x3f) << 5);
if (omap_uwire_data_transfer(TSC2101_UWIRE_CS, cmd, 16, 0, NULL, 1))
r = -1;
......@@ -51,14 +46,12 @@ static int tsc2101_write_reg(int page, int reg, u16 data)
r = omap_uwire_data_transfer(TSC2101_UWIRE_CS, data, 16, 0,
NULL, 0);
DBGLEAVE(1);
return r;
}
static int h2_panel_init(struct omapfb_device *fbdev)
static int h2_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
unsigned long uwire_flags;
DBGENTER(1);
/* Configure N15 pin to be uWire CS1 */
omap_cfg_reg(N15_1610_UWIRE_CS1);
......@@ -66,45 +59,35 @@ static int h2_panel_init(struct omapfb_device *fbdev)
uwire_flags |= UWIRE_FREQ_DIV_8;
omap_uwire_configure_mode(TSC2101_UWIRE_CS, uwire_flags);
DBGLEAVE(1);
return 0;
}
static void h2_panel_cleanup(void)
static void h2_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int h2_panel_enable(void)
static int h2_panel_enable(struct lcd_panel *panel)
{
int r;
DBGENTER(1);
/* Assert LCD_EN, BKLIGHT_EN pins on LCD panel
* page2, GPIO config reg, GPIO(0,1) to out and asserted
*/
r = tsc2101_write_reg(2, 0x23, 0xCC00) ? -1 : 0;
DBGLEAVE(1);
return r;
}
static void h2_panel_disable(void)
static void h2_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* Deassert LCD_EN and BKLIGHT_EN pins on LCD panel
* page2, GPIO config reg, GPIO(0,1) to out and deasserted
*/
if (tsc2101_write_reg(2, 0x23, 0x8800))
pr_err("failed to disable LCD panel\n");
DBGLEAVE(1);
}
static unsigned long h2_panel_get_caps(void)
static unsigned long h2_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -134,26 +117,22 @@ struct lcd_panel h2_panel = {
static int h2_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&h2_panel);
return 0;
}
static int h2_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int h2_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int h2_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -28,33 +28,23 @@
#include <asm/arch/tps65010.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
#define MODULE_NAME "omapfb-lcd_h3"
#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
static int h3_panel_init(struct omapfb_device *fbdev)
static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void h3_panel_cleanup(void)
static void h3_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int h3_panel_enable(void)
static int h3_panel_enable(struct lcd_panel *panel)
{
int r = 0;
DBGENTER(1);
/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
r = tps65010_set_gpio_out_value(GPIO1, HIGH);
if (!r)
......@@ -62,27 +52,22 @@ static int h3_panel_enable(void)
if (r)
pr_err("Unable to turn on LCD panel\n");
DBGLEAVE(1);
return r;
}
static void h3_panel_disable(void)
static void h3_panel_disable(struct lcd_panel *panel)
{
int r = 0;
DBGENTER(1);
/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
r = tps65010_set_gpio_out_value(GPIO1, LOW);
if (!r)
tps65010_set_gpio_out_value(GPIO2, LOW);
if (r)
pr_err("Unable to turn off LCD panel\n");
DBGLEAVE(1);
}
static unsigned long h3_panel_get_caps(void)
static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -113,26 +98,22 @@ struct lcd_panel h3_panel = {
static int h3_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&h3_panel);
return 0;
}
static int h3_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int h3_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -26,38 +26,25 @@
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
static int h4_panel_init(struct omapfb_device *fbdev)
static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void h4_panel_cleanup(void)
static void h4_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int h4_panel_enable(void)
static int h4_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void h4_panel_disable(void)
static void h4_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static unsigned long h4_panel_get_caps(void)
static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -87,26 +74,22 @@ struct lcd_panel h4_panel = {
static int h4_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&h4_panel);
return 0;
}
static int h4_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int h4_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -29,43 +29,28 @@
#include <asm/arch/fpga.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
static int innovator1510_panel_init(struct omapfb_device *fbdev)
static int innovator1510_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void innovator1510_panel_cleanup(void)
static void innovator1510_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int innovator1510_panel_enable(void)
static int innovator1510_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
DBGLEAVE(1);
return 0;
}
static void innovator1510_panel_disable(void)
static void innovator1510_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
DBGLEAVE(1);
}
static unsigned long innovator1510_panel_get_caps(void)
static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -96,26 +81,22 @@ struct lcd_panel innovator1510_panel = {
static int innovator1510_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&innovator1510_panel);
return 0;
}
static int innovator1510_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int innovator1510_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int innovator1510_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -27,20 +27,15 @@
#include <asm/arch/gpio.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
#define MODULE_NAME "omapfb-lcd_h3"
#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
static int innovator1610_panel_init(struct omapfb_device *fbdev)
static int innovator1610_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
int r = 0;
DBGENTER(1);
if (omap_request_gpio(14)) {
pr_err("can't request GPIO 14\n");
r = -1;
......@@ -56,44 +51,31 @@ static int innovator1610_panel_init(struct omapfb_device *fbdev)
omap_set_gpio_direction(14, 0);
omap_set_gpio_direction(15, 0);
exit:
DBGLEAVE(1);
return r;
}
static void innovator1610_panel_cleanup(void)
static void innovator1610_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
omap_free_gpio(15);
omap_free_gpio(14);
DBGLEAVE(1);
}
static int innovator1610_panel_enable(void)
static int innovator1610_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
/* set GPIO14 and GPIO15 high */
omap_set_gpio_dataout(14, 1);
omap_set_gpio_dataout(15, 1);
DBGLEAVE(1);
return 0;
}
static void innovator1610_panel_disable(void)
static void innovator1610_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* set GPIO13, GPIO14 and GPIO15 low */
omap_set_gpio_dataout(14, 0);
omap_set_gpio_dataout(15, 0);
DBGLEAVE(1);
}
static unsigned long innovator1610_panel_get_caps(void)
static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -124,26 +106,22 @@ struct lcd_panel innovator1610_panel = {
static int innovator1610_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&innovator1610_panel);
return 0;
}
static int innovator1610_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int innovator1610_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int innovator1610_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
#include <linux/module.h>
#include <linux/delay.h>
#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
#include <asm/arch/omapfb.h>
#include <asm/arch/lcd_lph8923.h>
#include <linux/spi/spi.h>
#include <asm/arch/mcspi.h>
#include "../../cbus/tahvo.h"
/* #define OMAPFB_DBG 1 */
#include "debug.h"
#define LPH8923_MODULE_NAME "lcd_lph8923"
#define LPH8923_VER_BUGGY 1
#define LPH8923_VER_NON_BUGGY 3
struct {
int enabled;
int version;
u8 display_id[3];
unsigned int saved_bklight_level;
unsigned long hw_guard_end; /* next value of jiffies
when we can issue the
next sleep in/out command */
unsigned long hw_guard_wait; /* max guard time in jiffies */
struct omapfb_device *fbdev;
struct spi_device *spi;
} lph8923;
#define LPH8923_CMD_READ_DISP_ID 0x04
#define LPH8923_CMD_READ_RED 0x06
#define LPH8923_CMD_READ_GREEN 0x07
#define LPH8923_CMD_READ_BLUE 0x08
#define LPH8923_CMD_READ_DISP_STATUS 0x09
#define LPH8923_CMD_SLEEP_IN 0x10
#define LPH8923_CMD_SLEEP_OUT 0x11
#define LPH8923_CMD_DISP_OFF 0x28
#define LPH8923_CMD_DISP_ON 0x29
static struct lcd_panel lph8923_panel;
#define LPH8923_SPEED_HZ 12000000
static int lph8923_spi_probe(struct spi_device *spi)
{
DBGENTER(1);
spi->dev.power.power_state = PMSG_ON;
spi->mode = SPI_MODE_0;
spi->bits_per_word = 9;
spi_setup(spi);
DBGPRINT(1, "spi %p\n", spi);
lph8923.spi = spi;
omapfb_register_panel(&lph8923_panel);
return 0;
}
static int lph8923_spi_remove(struct spi_device *spi)
{
DBGENTER(1);
lph8923.spi = NULL;
return 0;
}
static struct spi_driver lph8923_spi_driver = {
.driver = {
.name = LPH8923_MODULE_NAME,
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = lph8923_spi_probe,
.remove = __devexit_p(lph8923_spi_remove),
};
static int lph8923_drv_init(void)
{
spi_register_driver(&lph8923_spi_driver);
return 0;
}
module_init(lph8923_drv_init);
static void lph8923_drv_cleanup(void)
{
spi_unregister_driver(&lph8923_spi_driver);
}
module_exit(lph8923_drv_cleanup);
static void set_spi_data_width(int width)
{
if (lph8923.spi->bits_per_word != width) {
lph8923.spi->bits_per_word = width;
spi_setup(lph8923.spi);
}
}
static void lph8923_read(int cmd, u8 *buf, int len)
{
struct spi_message m;
struct spi_transfer t;
u16 w;
BUG_ON(lph8923.spi == NULL);
spi_message_init(&m);
m.spi = lph8923.spi;
if (len > 1) {
cmd <<= 1;
set_spi_data_width(10);
} else
set_spi_data_width(9);
w = cmd;
t.cs_change = len ? 1 : 0;
t.tx_buf = &w;
t.rx_buf = NULL;
t.len = 2;
spi_message_add_tail(&t, &m);
spi_sync(m.spi, &m);
if (!len)
return;
spi_message_init(&m);
m.spi = lph8923.spi;
t.cs_change = 0;
t.tx_buf = NULL;
t.rx_buf = buf;
t.len = len;
set_spi_data_width(8);
spi_message_add_tail(&t, &m);
spi_sync(m.spi, &m);
}
static void lph8923_write(int cmd, const u8 *buf, int len)
{
struct spi_message m;
struct spi_transfer t;
u16 w;
int i;
BUG_ON(lph8923.spi == NULL);
spi_message_init(&m);
m.spi = lph8923.spi;
set_spi_data_width(9);
t.cs_change = 0;
w = cmd;
t.tx_buf = &w;
t.rx_buf = NULL;
t.len = 2;
spi_message_add_tail(&t, &m);
spi_sync(m.spi, &m);
if (!len)
return;
t.tx_buf = &w;
for (i = 0; i < len; i++) {
spi_message_init(&m);
m.spi = lph8923.spi;
spi_message_add_tail(&t, &m);
w = buf[i] | (1 << 8);
spi_sync(m.spi, &m);
}
}
static inline void lph8923_cmd(int cmd)
{
lph8923_write(cmd, NULL, 0);
}
struct cmd_data {
u8 cmd;
u8 len;
const u8 *data;
} __attribute__ ((packed));;
static const struct cmd_data init_cmds_buggy_lph8923[] = {
{ 0xb0, 1, "\x08" },
{ 0xb1, 2, "\x0b\x1c" },
{ 0xb2, 4, "\x00\x00\x00\x00" },
{ 0xb3, 4, "\x00\x00\x00\x00" },
{ 0xb4, 1, "\x87" },
{ 0xb5, 4, "\x37\x07\x37\x07" },
{ 0xb6, 2, "\x64\x24" },
{ 0xb7, 1, "\x90" },
{ 0xb8, 3, "\x10\x11\x20" },
{ 0xb9, 2, "\x31\x02" },
{ 0xba, 3, "\x04\xa3\x9d" },
{ 0xbb, 4, "\x15\xb2\x8c\x00" },
{ 0xc2, 3, "\x02\x00\x00" },
};
static const struct cmd_data init_cmds_non_buggy_lph8923[] = {
{ 0xc2, 3, "\x02\x00\x00" },
};
static inline void lph8923_set_16bit_mode(void)
{
lph8923_write(0x3a, "\x50", 1);
}
static void lph8923_send_init_string(void)
{
int c;
const struct cmd_data *cd;
switch (lph8923.version) {
case LPH8923_VER_BUGGY:
c = sizeof(init_cmds_buggy_lph8923)/sizeof(init_cmds_buggy_lph8923[0]);
cd = init_cmds_buggy_lph8923;
break;
case LPH8923_VER_NON_BUGGY:
default:
c = sizeof(init_cmds_non_buggy_lph8923)/sizeof(init_cmds_non_buggy_lph8923[0]);
cd = init_cmds_non_buggy_lph8923;
break;
}
while (c--) {
lph8923_write(cd->cmd, cd->data, cd->len);
cd++;
}
lph8923_set_16bit_mode();
}
static void hw_guard_start(int guard_msec)
{
lph8923.hw_guard_wait = msecs_to_jiffies(guard_msec);
lph8923.hw_guard_end = jiffies + lph8923.hw_guard_wait;
}
static void hw_guard_wait(void)
{
unsigned long wait = lph8923.hw_guard_end - jiffies;
if ((long)wait > 0 && wait <= lph8923.hw_guard_wait) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(wait);
}
}
static void lph8923_set_sleep_mode(int on)
{
int cmd, sleep_time = 5;
if (on)
cmd = LPH8923_CMD_SLEEP_IN;
else
cmd = LPH8923_CMD_SLEEP_OUT;
hw_guard_wait();
lph8923_cmd(cmd);
hw_guard_start(120);
/* When we enable the panel, it seems we _have_ to sleep
* 120 ms before sending the init string */
if (!on)
sleep_time = 120;
msleep(sleep_time);
}
static void lph8923_set_display_state(int enabled)
{
int cmd = enabled ? LPH8923_CMD_DISP_ON : LPH8923_CMD_DISP_OFF;
lph8923_cmd(cmd);
}
static void lph8923_detect(void)
{
lph8923_read(LPH8923_CMD_READ_DISP_ID, lph8923.display_id, 3);
printk(KERN_INFO "Moscow display id: %02x%02x%02x\n",
lph8923.display_id[0], lph8923.display_id[1],
lph8923.display_id[2]);
if (lph8923.display_id[0] == 0x45) {
lph8923.version = LPH8923_VER_NON_BUGGY;
printk(KERN_INFO "Non-buggy Moscow detected\n");
return;
} else {
lph8923.version = LPH8923_VER_BUGGY;
printk(KERN_INFO "Buggy Moscow detected\n");
}
}
static int lph8923_enabled(void)
{
u32 disp_status;
int enabled;
lph8923_read(LPH8923_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
disp_status = __be32_to_cpu(disp_status);
enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
DBGPRINT(1, ": panel %senabled by bootloader (status 0x%04x)\n",
enabled ? "" : "not ", disp_status);
return enabled;
}
static int lph8923_panel_init(struct omapfb_device *fbdev)
{
lph8923.fbdev = fbdev;
lph8923.enabled = 1;
lph8923_detect();
if (lph8923.version == LPH8923_VER_NON_BUGGY)
lph8923.enabled = lph8923_enabled();
else
/* We can't be sure, but assume the bootloader
* enabled it already */
lph8923.enabled = 1;
return 0;
}
static void lph8923_panel_cleanup(void)
{
}
static int lph8923_panel_set_bklight_level(unsigned int level)
{
if (level > tahvo_get_max_backlight_level())
return -EINVAL;
if (!lph8923.enabled) {
lph8923.saved_bklight_level = level;
return 0;
}
tahvo_set_backlight_level(level);
return 0;
}
static unsigned int lph8923_panel_get_bklight_level(void)
{
return tahvo_get_backlight_level();
}
static unsigned int lph8923_panel_get_bklight_max(void)
{
return tahvo_get_max_backlight_level();
}
static int lph8923_panel_enable(void)
{
if (lph8923.enabled)
return 0;
lph8923_set_sleep_mode(0);
lph8923.enabled = 1;
lph8923_send_init_string();
lph8923_set_display_state(1);
lph8923_panel_set_bklight_level(lph8923.saved_bklight_level);
return 0;
}
static void lph8923_panel_disable(void)
{
if (!lph8923.enabled)
return;
lph8923.saved_bklight_level = lph8923_panel_get_bklight_level();
lph8923_panel_set_bklight_level(0);
lph8923_set_display_state(0);
lph8923_set_sleep_mode(1);
lph8923.enabled = 0;
}
static unsigned long lph8923_panel_get_caps(void)
{
return OMAPFB_CAPS_SET_BACKLIGHT;
}
static u16 read_first_pixel(void)
{
u8 b;
u16 pixel;
lph8923_read(LPH8923_CMD_READ_RED, &b, 1);
pixel = (b >> 1) << 11;
lph8923_read(LPH8923_CMD_READ_GREEN, &b, 1);
pixel |= b << 5;
lph8923_read(LPH8923_CMD_READ_BLUE, &b, 1);
pixel |= (b >> 1);
return pixel;
}
static int lph8923_panel_test(int test_num)
{
static const u16 test_values[4] = {
0x0000, 0xffff, 0xaaaa, 0x5555,
};
int i;
if (test_num != LCD_LPH8923_TEST_RGB_LINES)
return LCD_LPH8923_TEST_INVALID;
for (i = 0; i < ARRAY_SIZE(test_values); i++) {
int delay;
unsigned long tmo;
omapfb_write_first_pixel(lph8923.fbdev, test_values[i]);
tmo = jiffies + msecs_to_jiffies(100);
delay = msecs_to_jiffies(25);
while (1) {
u16 pixel;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(delay);
pixel = read_first_pixel();
if (pixel == test_values[i])
break;
if (time_after(jiffies, tmo)) {
printk(KERN_ERR "Moscow RGB I/F test failed: "
"expecting %04x, got %04x\n",
test_values[i], pixel);
return LCD_LPH8923_TEST_FAILED;
}
delay = msecs_to_jiffies(10);
}
}
return 0;
}
static struct lcd_panel lph8923_panel = {
.name = "lph8923",
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.data_lines = 16,
.x_res = 800,
.y_res = 480,
.pixel_clock = 21940,
.hsw = 50,
.hfp = 20,
.hbp = 15,
.vsw = 2,
.vfp = 1,
.vbp = 3,
.init = lph8923_panel_init,
.cleanup = lph8923_panel_cleanup,
.enable = lph8923_panel_enable,
.disable = lph8923_panel_disable,
.get_caps = lph8923_panel_get_caps,
.set_bklight_level= lph8923_panel_set_bklight_level,
.get_bklight_level= lph8923_panel_get_bklight_level,
.get_bklight_max= lph8923_panel_get_bklight_max,
.run_test = lph8923_panel_test,
};
/*
* File: drivers/video/omap/lcd_mipid.c
*
* LCD driver for MIPI DBI-C / DCS compatible LCDs
*
* Copyright (C) 2006 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* 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, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <asm/arch/omapfb.h>
#include <asm/arch/lcd_mipid.h>
#include "../../cbus/tahvo.h"
#define MIPID_MODULE_NAME "lcd_mipid"
#define MIPID_CMD_READ_DISP_ID 0x04
#define MIPID_CMD_READ_RED 0x06
#define MIPID_CMD_READ_GREEN 0x07
#define MIPID_CMD_READ_BLUE 0x08
#define MIPID_CMD_READ_DISP_STATUS 0x09
#define MIPID_CMD_RDDSDR 0x0F
#define MIPID_CMD_SLEEP_IN 0x10
#define MIPID_CMD_SLEEP_OUT 0x11
#define MIPID_CMD_DISP_OFF 0x28
#define MIPID_CMD_DISP_ON 0x29
#define MIPID_VER_LPH8923 3
#define MIPID_VER_LS041Y3 4
#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
#define to_mipid_device(p) container_of(p, struct mipid_device, \
panel)
struct mipid_device {
int enabled;
int model;
int revision;
u8 display_id[3];
unsigned int saved_bklight_level;
unsigned long hw_guard_end; /* next value of jiffies
when we can issue the
next sleep in/out command */
unsigned long hw_guard_wait; /* max guard time in jiffies */
struct omapfb_device *fbdev;
struct spi_device *spi;
struct mutex mutex;
struct lcd_panel panel;
struct work_struct esd_work;
void (*esd_check)(struct mipid_device *m);
};
static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
int wlen, u8 *rbuf, int rlen)
{
struct spi_message m;
struct spi_transfer *x, xfer[4];
u16 w;
int r;
BUG_ON(md->spi == NULL);
spi_message_init(&m);
memset(xfer, 0, sizeof(xfer));
x = &xfer[0];
cmd &= 0xff;
x->tx_buf = &cmd;
x->bits_per_word= 9;
x->len = 2;
spi_message_add_tail(x, &m);
if (wlen) {
x++;
x->tx_buf = wbuf;
x->len = wlen;
x->bits_per_word= 9;
spi_message_add_tail(x, &m);
}
if (rlen) {
x++;
x->rx_buf = &w;
x->len = 1;
spi_message_add_tail(x, &m);
if (rlen > 1) {
/* Arrange for the extra clock before the first
* data bit.
*/
x->bits_per_word = 9;
x->len = 2;
x++;
x->rx_buf = &rbuf[1];
x->len = rlen - 1;
spi_message_add_tail(x, &m);
}
}
r = spi_sync(md->spi, &m);
if (r < 0)
dev_dbg(md->spi->dev, "spi_sync %d\n", r);
if (rlen)
rbuf[0] = w & 0xff;
}
static inline void mipid_cmd(struct mipid_device *md, int cmd)
{
mipid_transfer(md, cmd, NULL, 0, NULL, 0);
}
static inline void mipid_write(struct mipid_device *md,
int reg, const u8 *buf, int len)
{
mipid_transfer(md, reg, buf, len, NULL, 0);
}
static inline void mipid_read(struct mipid_device *md,
int reg, u8 *buf, int len)
{
mipid_transfer(md, reg, NULL, 0, buf, len);
}
static void set_data_lines(struct mipid_device *md, int data_lines)
{
u16 par;
switch (data_lines) {
case 16:
par = 0x150;
break;
case 18:
par = 0x160;
break;
case 24:
par = 0x170;
break;
}
mipid_write(md, 0x3a, (u8 *)&par, 2);
}
static void send_init_string(struct mipid_device *md)
{
u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
set_data_lines(md, md->panel.data_lines);
}
static void hw_guard_start(struct mipid_device *md, int guard_msec)
{
md->hw_guard_wait = msecs_to_jiffies(guard_msec);
md->hw_guard_end = jiffies + md->hw_guard_wait;
}
static void hw_guard_wait(struct mipid_device *md)
{
unsigned long wait = md->hw_guard_end - jiffies;
if ((long)wait > 0 && wait <= md->hw_guard_wait) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(wait);
}
}
static void set_sleep_mode(struct mipid_device *md, int on)
{
int cmd, sleep_time = 5;
if (on)
cmd = MIPID_CMD_SLEEP_IN;
else
cmd = MIPID_CMD_SLEEP_OUT;
hw_guard_wait(md);
mipid_cmd(md, cmd);
hw_guard_start(md, 120);
/* When we enable the panel, it seems we _have_ to sleep
* 120 ms before sending the init string */
if (!on)
sleep_time = 120;
msleep(sleep_time);
}
static void set_display_state(struct mipid_device *md, int enabled)
{
int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
mipid_cmd(md, cmd);
}
static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
{
struct mipid_device *md = to_mipid_device(panel);
if (level > tahvo_get_max_backlight_level())
return -EINVAL;
if (!md->enabled) {
md->saved_bklight_level = level;
return 0;
}
tahvo_set_backlight_level(level);
return 0;
}
static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
{
return tahvo_get_backlight_level();
}
static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
{
return tahvo_get_max_backlight_level();
}
static unsigned long mipid_get_caps(struct lcd_panel *panel)
{
return OMAPFB_CAPS_SET_BACKLIGHT;
}
static u16 read_first_pixel(struct mipid_device *md)
{
u16 pixel;
u8 red, green, blue;
mutex_lock(&md->mutex);
mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
mutex_unlock(&md->mutex);
switch (md->panel.data_lines) {
case 16:
pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
break;
case 24:
/* 24 bit -> 16 bit */
pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
(blue >> 3);
break;
default:
BUG();
}
return pixel;
}
static int mipid_run_test(struct lcd_panel *panel, int test_num)
{
struct mipid_device *md = to_mipid_device(panel);
static const u16 test_values[4] = {
0x0000, 0xffff, 0xaaaa, 0x5555,
};
int i;
if (test_num != MIPID_TEST_RGB_LINES)
return MIPID_TEST_INVALID;
for (i = 0; i < ARRAY_SIZE(test_values); i++) {
int delay;
unsigned long tmo;
omapfb_write_first_pixel(md->fbdev, test_values[i]);
tmo = jiffies + msecs_to_jiffies(100);
delay = 25;
while (1) {
u16 pixel;
msleep(delay);
pixel = read_first_pixel(md);
if (pixel == test_values[i])
break;
if (time_after(jiffies, tmo)) {
dev_err(&md->spi->dev,
"MIPI LCD RGB I/F test failed: "
"expecting %04x, got %04x\n",
test_values[i], pixel);
return MIPID_TEST_FAILED;
}
delay = 10;
}
}
return 0;
}
static void ls041y3_esd_recover(struct mipid_device *md)
{
dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
set_sleep_mode(md, 1);
set_sleep_mode(md, 0);
}
static void ls041y3_esd_check_mode1(struct mipid_device *md)
{
u8 state1, state2;
mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
set_sleep_mode(md, 0);
mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
state1, state2);
/* Each sleep out command will trigger a self diagnostic and flip
* Bit6 if the test passes.
*/
if (!((state1 ^ state2) & (1 << 6)))
ls041y3_esd_recover(md);
}
static void ls041y3_esd_check_mode2(struct mipid_device *md)
{
int i;
u8 rbuf[2];
static const struct {
int cmd;
int wlen;
u16 wbuf[3];
} *rd, rd_ctrl[7] = {
{ 0xb0, 4, { 0x0101, 0x01fe, } },
{ 0xb1, 4, { 0x01de, 0x0121, } },
{ 0xc2, 4, { 0x0100, 0x0100, } },
{ 0xbd, 2, { 0x0100, } },
{ 0xc2, 4, { 0x01fc, 0x0103, } },
{ 0xb4, 0, },
{ 0x00, 0, },
};
rd = rd_ctrl;
for (i = 0; i < 3; i++, rd++)
mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
udelay(10);
mipid_read(md, rd->cmd, rbuf, 2);
rd++;
for (i = 0; i < 3; i++, rd++) {
udelay(10);
mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
}
dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
if (rbuf[1] == 0x00)
ls041y3_esd_recover(md);
}
static void ls041y3_esd_check(struct mipid_device *md)
{
ls041y3_esd_check_mode1(md);
if (md->revision >= 0x88)
ls041y3_esd_check_mode2(md);
}
static void mipid_esd_start_check(struct mipid_device *md)
{
if (md->esd_check != NULL)
schedule_delayed_work(&md->esd_work, MIPID_ESD_CHECK_PERIOD);
}
static void mipid_esd_stop_check(struct mipid_device *md)
{
cancel_rearming_delayed_work(&md->esd_work);
}
static void mipid_esd_work(void *data)
{
struct mipid_device *md = data;
mutex_lock(&md->mutex);
md->esd_check(md);
mutex_unlock(&md->mutex);
mipid_esd_start_check(md);
}
static int mipid_enable(struct lcd_panel *panel)
{
struct mipid_device *md = to_mipid_device(panel);
mutex_lock(&md->mutex);
if (md->enabled) {
mutex_unlock(&md->mutex);
return 0;
}
set_sleep_mode(md, 0);
md->enabled = 1;
send_init_string(md);
set_display_state(md, 1);
mipid_set_bklight_level(panel, md->saved_bklight_level);
mipid_esd_start_check(md);
mutex_unlock(&md->mutex);
return 0;
}
static void mipid_disable(struct lcd_panel *panel)
{
struct mipid_device *md = to_mipid_device(panel);
/* A final ESD work might be called before returning,
* so do this without holding the lock. */
mipid_esd_stop_check(md);
mutex_lock(&md->mutex);
if (!md->enabled) {
mutex_unlock(&md->mutex);
return;
}
md->saved_bklight_level = mipid_get_bklight_level(panel);
mipid_set_bklight_level(panel, 0);
set_display_state(md, 0);
set_sleep_mode(md, 1);
md->enabled = 0;
mutex_unlock(&md->mutex);
}
static int panel_enabled(struct mipid_device *md)
{
u32 disp_status;
int enabled;
mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
disp_status = __be32_to_cpu(disp_status);
enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
dev_dbg(&md->spi->dev,
"LCD panel %s enabled by bootloader (status 0x%04x)\n",
enabled ? "" : "not ", disp_status);
return enabled;
}
static int mipid_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
struct mipid_device *md = to_mipid_device(panel);
md->fbdev = fbdev;
INIT_WORK(&md->esd_work, mipid_esd_work, md);
mutex_init(&md->mutex);
md->enabled = panel_enabled(md);
if (md->enabled)
mipid_esd_start_check(md);
else
md->saved_bklight_level = mipid_get_bklight_level(panel);
return 0;
}
static void mipid_cleanup(struct lcd_panel *panel)
{
struct mipid_device *md = to_mipid_device(panel);
mipid_esd_stop_check(md);
}
static struct lcd_panel mipid_panel = {
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.x_res = 800,
.y_res = 480,
.pixel_clock = 21940,
.hsw = 50,
.hfp = 20,
.hbp = 15,
.vsw = 2,
.vfp = 1,
.vbp = 3,
.init = mipid_init,
.cleanup = mipid_cleanup,
.enable = mipid_enable,
.disable = mipid_disable,
.get_caps = mipid_get_caps,
.set_bklight_level= mipid_set_bklight_level,
.get_bklight_level= mipid_get_bklight_level,
.get_bklight_max= mipid_get_bklight_max,
.run_test = mipid_run_test,
};
static int mipid_detect(struct mipid_device *md)
{
struct mipid_platform_data *pdata;
pdata = md->spi->dev.platform_data;
if (pdata == NULL) {
dev_err(&md->spi->dev, "missing platform data\n");
return -ENOENT;
}
mipid_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
md->display_id[0], md->display_id[1], md->display_id[2]);
switch (md->display_id[0]) {
case 0x45:
md->model = MIPID_VER_LPH8923;
md->panel.name = "lph8923";
break;
case 0x83:
md->model = MIPID_VER_LS041Y3;
md->panel.name = "ls041y3";
md->esd_check = ls041y3_esd_check;
break;
default:
md->panel.name = "unknown";
dev_err(&md->spi->dev, "invalid display ID\n");
return -ENODEV;
}
md->revision = md->display_id[1];
md->panel.data_lines = pdata->data_lines;
pr_info("omapfb: %s rev %02x LCD detected\n",
md->panel.name, md->revision);
return 0;
}
static int mipid_spi_probe(struct spi_device *spi)
{
struct mipid_device *md;
int r;
md = kzalloc(sizeof(*md), SLAB_KERNEL);
if (md == NULL) {
dev_err(&md->spi->dev, "out of memory\n");
return -ENOMEM;
}
spi->mode = SPI_MODE_1;
md->spi = spi;
dev_set_drvdata(&spi->dev, md);
md->panel = mipid_panel;
r = mipid_detect(md);
if (r < 0)
return r;
omapfb_register_panel(&md->panel);
return 0;
}
static int mipid_spi_remove(struct spi_device *spi)
{
struct mipid_device *md = dev_get_drvdata(&spi->dev);
mipid_disable(&md->panel);
kfree(md);
return 0;
}
static struct spi_driver mipid_spi_driver = {
.driver = {
.name = MIPID_MODULE_NAME,
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = mipid_spi_probe,
.remove = __devexit_p(mipid_spi_remove),
};
static int mipid_drv_init(void)
{
spi_register_driver(&mipid_spi_driver);
return 0;
}
module_init(mipid_drv_init);
static void mipid_drv_cleanup(void)
{
spi_unregister_driver(&mipid_spi_driver);
}
module_exit(mipid_drv_cleanup);
MODULE_DESCRIPTION("MIPI display driver");
MODULE_LICENSE("GPL");
......@@ -29,27 +29,17 @@
#include <asm/arch/mux.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
static int osk_panel_init(struct omapfb_device *fbdev)
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void osk_panel_cleanup(void)
static void osk_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int osk_panel_enable(void)
static int osk_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
/* configure PWL pin */
omap_cfg_reg(PWL);
......@@ -65,14 +55,11 @@ static int osk_panel_enable(void)
/* set GPIO2 high */
omap_set_gpio_dataout(2, 1);
DBGLEAVE(1);
return 0;
}
static void osk_panel_disable(void)
static void osk_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* Set PWL level to zero */
omap_writeb(0x00, OMAP16XX_PWL_ENABLE);
......@@ -81,11 +68,9 @@ static void osk_panel_disable(void)
/* set GPIO2 low */
omap_set_gpio_dataout(2, 0);
DBGLEAVE(1);
}
static unsigned long osk_panel_get_caps(void)
static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -116,26 +101,22 @@ struct lcd_panel osk_panel = {
static int osk_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&osk_panel);
return 0;
}
static int osk_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int osk_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -148,29 +148,23 @@ const unsigned short INIT_SCSTART[2] = { 0x00, 0x00 };
/* ----- end of epson_md_tft.h ----- */
#include "debug.h"
#include "../drivers/ssi/omap-uwire.h"
#define LCD_UWIRE_CS 0
static int p2_panel_init(struct omapfb_device *fbdev)
static int p2_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void p2_panel_cleanup(void)
static void p2_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int p2_panel_enable(void)
static int p2_panel_enable(struct lcd_panel *panel)
{
int i;
unsigned long value;
DBGENTER(1);
/* thwack the reset line */
omap_set_gpio_direction(19, 0);
......@@ -268,17 +262,14 @@ static int p2_panel_enable(void)
omap_set_gpio_direction(134, 0);
omap_set_gpio_dataout(134, 1);
DBGLEAVE(1);
return 0;
}
static void p2_panel_disable(void)
static void p2_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static unsigned long p2_panel_get_caps(void)
static unsigned long p2_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -308,26 +299,22 @@ struct lcd_panel p2_panel = {
static int p2_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&p2_panel);
return 0;
}
static int p2_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int p2_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int p2_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......
......@@ -29,37 +29,26 @@
#include <asm/arch/fpga.h>
#include <asm/arch/omapfb.h>
/* #define OMAPFB_DBG 1 */
#include "debug.h"
static int palmte_panel_init(struct omapfb_device *panel)
static int palmte_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void palmte_panel_cleanup(void)
static void palmte_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int palmte_panel_enable(void)
static int palmte_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void palmte_panel_disable(void)
static void palmte_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static unsigned long palmte_panel_get_caps(void)
static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
......@@ -92,26 +81,22 @@ struct lcd_panel palmte_panel = {
static int palmte_panel_probe(struct platform_device *pdev)
{
DBGENTER(1);
omapfb_register_panel(&palmte_panel);
return 0;
}
static int palmte_panel_remove(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
DBGENTER(1);
return 0;
}
static int palmte_panel_resume(struct platform_device *pdev)
{
DBGENTER(1);
return 0;
}
......@@ -138,3 +123,4 @@ static void palmte_panel_drv_cleanup(void)
module_init(palmte_panel_drv_init);
module_exit(palmte_panel_drv_cleanup);
#ifndef __LCD_LPH8923_H
#define __LCD_LPH8923_H
enum lcd_lph8923_test_num {
LCD_LPH8923_TEST_RGB_LINES,
};
enum lcd_lph8923_test_result {
LCD_LPH8923_TEST_SUCCESS,
LCD_LPH8923_TEST_INVALID,
LCD_LPH8923_TEST_FAILED,
};
#endif
#ifndef __LCD_MIPID_H
#define __LCD_MIPID_H
enum mipid_test_num {
MIPID_TEST_RGB_LINES,
};
enum mipid_test_result {
MIPID_TEST_SUCCESS,
MIPID_TEST_INVALID,
MIPID_TEST_FAILED,
};
#ifdef __KERNEL__
struct mipid_platform_data {
int nreset_gpio;
int data_lines;
void (*shutdown)(struct mipid_platform_data *pdata);
};
#endif
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment