mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
5e6d6c1c23
DSI dcs commands and mdp pixel stream share same dsi link. Add dcs command list to serialize sending dcs command and mdp pixel stream to avoid contention which may cause dsi controller to stall. Change-Id: Ie0e687f45be479d2137eb7b56b8d32040fba2044 Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> Conflicts: drivers/video/msm/mdp4.h Signed-off-by: Naseer Ahmed <naseer@codeaurora.org>
651 lines
15 KiB
C
651 lines
15 KiB
C
/* Copyright (c) 2010-2012, Code Aurora Forum. 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.
|
|
*
|
|
*/
|
|
|
|
#ifdef CONFIG_SPI_QUP
|
|
#include <linux/spi/spi.h>
|
|
#endif
|
|
#include <linux/leds.h>
|
|
#include "msm_fb.h"
|
|
#include "mipi_dsi.h"
|
|
#include "mipi_novatek.h"
|
|
#include "mdp4.h"
|
|
|
|
|
|
static struct mipi_dsi_panel_platform_data *mipi_novatek_pdata;
|
|
|
|
static struct dsi_buf novatek_tx_buf;
|
|
static struct dsi_buf novatek_rx_buf;
|
|
static int mipi_novatek_lcd_init(void);
|
|
|
|
static int wled_trigger_initialized;
|
|
|
|
#define MIPI_DSI_NOVATEK_SPI_DEVICE_NAME "dsi_novatek_3d_panel_spi"
|
|
#define HPCI_FPGA_READ_CMD 0x84
|
|
#define HPCI_FPGA_WRITE_CMD 0x04
|
|
|
|
#ifdef CONFIG_SPI_QUP
|
|
static struct spi_device *panel_3d_spi_client;
|
|
|
|
static void novatek_fpga_write(uint8 addr, uint16 value)
|
|
{
|
|
char tx_buf[32];
|
|
int rc;
|
|
struct spi_message m;
|
|
struct spi_transfer t;
|
|
u8 data[4] = {0x0, 0x0, 0x0, 0x0};
|
|
|
|
if (!panel_3d_spi_client) {
|
|
pr_err("%s panel_3d_spi_client is NULL\n", __func__);
|
|
return;
|
|
}
|
|
data[0] = HPCI_FPGA_WRITE_CMD;
|
|
data[1] = addr;
|
|
data[2] = ((value >> 8) & 0xFF);
|
|
data[3] = (value & 0xFF);
|
|
|
|
memset(&t, 0, sizeof t);
|
|
memset(tx_buf, 0, sizeof tx_buf);
|
|
t.tx_buf = data;
|
|
t.len = 4;
|
|
spi_setup(panel_3d_spi_client);
|
|
spi_message_init(&m);
|
|
spi_message_add_tail(&t, &m);
|
|
|
|
rc = spi_sync(panel_3d_spi_client, &m);
|
|
if (rc)
|
|
pr_err("%s: SPI transfer failed\n", __func__);
|
|
|
|
return;
|
|
}
|
|
|
|
static void novatek_fpga_read(uint8 addr)
|
|
{
|
|
char tx_buf[32];
|
|
int rc;
|
|
struct spi_message m;
|
|
struct spi_transfer t;
|
|
struct spi_transfer rx;
|
|
char rx_value[2];
|
|
u8 data[4] = {0x0, 0x0};
|
|
|
|
if (!panel_3d_spi_client) {
|
|
pr_err("%s panel_3d_spi_client is NULL\n", __func__);
|
|
return;
|
|
}
|
|
|
|
data[0] = HPCI_FPGA_READ_CMD;
|
|
data[1] = addr;
|
|
|
|
memset(&t, 0, sizeof t);
|
|
memset(tx_buf, 0, sizeof tx_buf);
|
|
memset(&rx, 0, sizeof rx);
|
|
memset(rx_value, 0, sizeof rx_value);
|
|
t.tx_buf = data;
|
|
t.len = 2;
|
|
rx.rx_buf = rx_value;
|
|
rx.len = 2;
|
|
spi_setup(panel_3d_spi_client);
|
|
spi_message_init(&m);
|
|
spi_message_add_tail(&t, &m);
|
|
spi_message_add_tail(&rx, &m);
|
|
|
|
rc = spi_sync(panel_3d_spi_client, &m);
|
|
if (rc)
|
|
pr_err("%s: SPI transfer failed\n", __func__);
|
|
else
|
|
pr_info("%s: rx_value = 0x%x, 0x%x\n", __func__,
|
|
rx_value[0], rx_value[1]);
|
|
|
|
return;
|
|
}
|
|
|
|
static int __devinit panel_3d_spi_probe(struct spi_device *spi)
|
|
{
|
|
panel_3d_spi_client = spi;
|
|
return 0;
|
|
}
|
|
static int __devexit panel_3d_spi_remove(struct spi_device *spi)
|
|
{
|
|
panel_3d_spi_client = NULL;
|
|
return 0;
|
|
}
|
|
static struct spi_driver panel_3d_spi_driver = {
|
|
.probe = panel_3d_spi_probe,
|
|
.remove = __devexit_p(panel_3d_spi_remove),
|
|
.driver = {
|
|
.name = "dsi_novatek_3d_panel_spi",
|
|
.owner = THIS_MODULE,
|
|
}
|
|
};
|
|
|
|
#else
|
|
|
|
static void novatek_fpga_write(uint8 addr, uint16 value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static void novatek_fpga_read(uint8 addr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/* novatek blue panel */
|
|
|
|
#ifdef NOVETAK_COMMANDS_UNUSED
|
|
static char display_config_cmd_mode1[] = {
|
|
/* TYPE_DCS_LWRITE */
|
|
0x2A, 0x00, 0x00, 0x01,
|
|
0x3F, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
static char display_config_cmd_mode2[] = {
|
|
/* DTYPE_DCS_LWRITE */
|
|
0x2B, 0x00, 0x00, 0x01,
|
|
0xDF, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
static char display_config_cmd_mode3_666[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0x3A, 0x66, 0x15, 0x80 /* 666 Packed (18-bits) */
|
|
};
|
|
|
|
static char display_config_cmd_mode3_565[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0x3A, 0x55, 0x15, 0x80 /* 565 mode */
|
|
};
|
|
|
|
static char display_config_321[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0x66, 0x2e, 0x15, 0x00 /* Reg 0x66 : 2E */
|
|
};
|
|
|
|
static char display_config_323[] = {
|
|
/* DTYPE_DCS_WRITE */
|
|
0x13, 0x00, 0x05, 0x00 /* Reg 0x13 < Set for Normal Mode> */
|
|
};
|
|
|
|
static char display_config_2lan[] = {
|
|
/* DTYPE_DCS_WRITE */
|
|
0x61, 0x01, 0x02, 0xff /* Reg 0x61 : 01,02 < Set for 2 Data Lane > */
|
|
};
|
|
|
|
static char display_config_exit_sleep[] = {
|
|
/* DTYPE_DCS_WRITE */
|
|
0x11, 0x00, 0x05, 0x80 /* Reg 0x11 < exit sleep mode> */
|
|
};
|
|
|
|
static char display_config_TE_ON[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0x35, 0x00, 0x15, 0x80
|
|
};
|
|
|
|
static char display_config_39H[] = {
|
|
/* DTYPE_DCS_WRITE */
|
|
0x39, 0x00, 0x05, 0x80
|
|
};
|
|
|
|
static char display_config_set_tear_scanline[] = {
|
|
/* DTYPE_DCS_LWRITE */
|
|
0x44, 0x00, 0x00, 0xff
|
|
};
|
|
|
|
static char display_config_set_twolane[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0xae, 0x03, 0x15, 0x80
|
|
};
|
|
|
|
static char display_config_set_threelane[] = {
|
|
/* DTYPE_DCS_WRITE1 */
|
|
0xae, 0x05, 0x15, 0x80
|
|
};
|
|
|
|
#else
|
|
|
|
static char sw_reset[2] = {0x01, 0x00}; /* DTYPE_DCS_WRITE */
|
|
static char enter_sleep[2] = {0x10, 0x00}; /* DTYPE_DCS_WRITE */
|
|
static char exit_sleep[2] = {0x11, 0x00}; /* DTYPE_DCS_WRITE */
|
|
static char display_off[2] = {0x28, 0x00}; /* DTYPE_DCS_WRITE */
|
|
static char display_on[2] = {0x29, 0x00}; /* DTYPE_DCS_WRITE */
|
|
|
|
|
|
|
|
static char rgb_888[2] = {0x3A, 0x77}; /* DTYPE_DCS_WRITE1 */
|
|
|
|
#if defined(NOVATEK_TWO_LANE)
|
|
static char set_num_of_lanes[2] = {0xae, 0x03}; /* DTYPE_DCS_WRITE1 */
|
|
#else /* 1 lane */
|
|
static char set_num_of_lanes[2] = {0xae, 0x01}; /* DTYPE_DCS_WRITE1 */
|
|
#endif
|
|
/* commands by Novatke */
|
|
static char novatek_f4[2] = {0xf4, 0x55}; /* DTYPE_DCS_WRITE1 */
|
|
static char novatek_8c[16] = { /* DTYPE_DCS_LWRITE */
|
|
0x8C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x08, 0x08, 0x00, 0x30, 0xC0, 0xB7, 0x37};
|
|
static char novatek_ff[2] = {0xff, 0x55 }; /* DTYPE_DCS_WRITE1 */
|
|
|
|
static char set_width[5] = { /* DTYPE_DCS_LWRITE */
|
|
0x2A, 0x00, 0x00, 0x02, 0x1B}; /* 540 - 1 */
|
|
static char set_height[5] = { /* DTYPE_DCS_LWRITE */
|
|
0x2B, 0x00, 0x00, 0x03, 0xBF}; /* 960 - 1 */
|
|
#endif
|
|
|
|
static char led_pwm2[2] = {0x53, 0x24}; /* DTYPE_DCS_WRITE1 */
|
|
static char led_pwm3[2] = {0x55, 0x00}; /* DTYPE_DCS_WRITE1 */
|
|
|
|
static struct dsi_cmd_desc novatek_video_on_cmds[] = {
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 50,
|
|
sizeof(sw_reset), sw_reset},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 10,
|
|
sizeof(exit_sleep), exit_sleep},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 10,
|
|
sizeof(display_on), display_on},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(set_num_of_lanes), set_num_of_lanes},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(rgb_888), rgb_888},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(led_pwm2), led_pwm2},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(led_pwm3), led_pwm3},
|
|
};
|
|
|
|
static struct dsi_cmd_desc novatek_cmd_on_cmds[] = {
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 50,
|
|
sizeof(sw_reset), sw_reset},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 10,
|
|
sizeof(exit_sleep), exit_sleep},
|
|
{DTYPE_DCS_WRITE, 1, 0, 0, 10,
|
|
sizeof(display_on), display_on},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 50,
|
|
sizeof(novatek_f4), novatek_f4},
|
|
{DTYPE_DCS_LWRITE, 1, 0, 0, 50,
|
|
sizeof(novatek_8c), novatek_8c},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 50,
|
|
sizeof(novatek_ff), novatek_ff},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(set_num_of_lanes), set_num_of_lanes},
|
|
{DTYPE_DCS_LWRITE, 1, 0, 0, 50,
|
|
sizeof(set_width), set_width},
|
|
{DTYPE_DCS_LWRITE, 1, 0, 0, 50,
|
|
sizeof(set_height), set_height},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 10,
|
|
sizeof(rgb_888), rgb_888},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 1,
|
|
sizeof(led_pwm2), led_pwm2},
|
|
{DTYPE_DCS_WRITE1, 1, 0, 0, 1,
|
|
sizeof(led_pwm3), led_pwm3},
|
|
};
|
|
|
|
static struct dsi_cmd_desc novatek_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 char manufacture_id[2] = {0x04, 0x00}; /* DTYPE_DCS_READ */
|
|
|
|
static struct dsi_cmd_desc novatek_manufacture_id_cmd = {
|
|
DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(manufacture_id), manufacture_id};
|
|
|
|
static uint32 mipi_novatek_manufacture_id(struct msm_fb_data_type *mfd)
|
|
{
|
|
struct dsi_buf *rp, *tp;
|
|
struct dsi_cmd_desc *cmd;
|
|
uint32 *lp;
|
|
|
|
tp = &novatek_tx_buf;
|
|
rp = &novatek_rx_buf;
|
|
cmd = &novatek_manufacture_id_cmd;
|
|
mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
|
|
lp = (uint32 *)rp->data;
|
|
pr_info("%s: manufacture_id=%x\n", __func__, *lp);
|
|
return *lp;
|
|
}
|
|
|
|
static int fpga_addr;
|
|
static int fpga_access_mode;
|
|
static bool support_3d;
|
|
|
|
static void mipi_novatek_3d_init(int addr, int mode)
|
|
{
|
|
fpga_addr = addr;
|
|
fpga_access_mode = mode;
|
|
}
|
|
|
|
static void mipi_dsi_enable_3d_barrier(int mode)
|
|
{
|
|
void __iomem *fpga_ptr;
|
|
uint32_t ptr_value = 0;
|
|
|
|
if (!fpga_addr && support_3d) {
|
|
pr_err("%s: fpga_addr not set. Failed to enable 3D barrier\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
if (fpga_access_mode == FPGA_SPI_INTF) {
|
|
if (mode == LANDSCAPE)
|
|
novatek_fpga_write(fpga_addr, 1);
|
|
else if (mode == PORTRAIT)
|
|
novatek_fpga_write(fpga_addr, 3);
|
|
else
|
|
novatek_fpga_write(fpga_addr, 0);
|
|
|
|
mb();
|
|
novatek_fpga_read(fpga_addr);
|
|
} else if (fpga_access_mode == FPGA_EBI2_INTF) {
|
|
fpga_ptr = ioremap_nocache(fpga_addr, sizeof(uint32_t));
|
|
if (!fpga_ptr) {
|
|
pr_err("%s: FPGA ioremap failed."
|
|
"Failed to enable 3D barrier\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
ptr_value = readl_relaxed(fpga_ptr);
|
|
if (mode == LANDSCAPE)
|
|
writel_relaxed(((0xFFFF0000 & ptr_value) | 1),
|
|
fpga_ptr);
|
|
else if (mode == PORTRAIT)
|
|
writel_relaxed(((0xFFFF0000 & ptr_value) | 3),
|
|
fpga_ptr);
|
|
else
|
|
writel_relaxed((0xFFFF0000 & ptr_value),
|
|
fpga_ptr);
|
|
|
|
mb();
|
|
iounmap(fpga_ptr);
|
|
} else
|
|
pr_err("%s: 3D barrier not configured correctly\n",
|
|
__func__);
|
|
}
|
|
|
|
static int mipi_novatek_lcd_on(struct platform_device *pdev)
|
|
{
|
|
struct msm_fb_data_type *mfd;
|
|
struct mipi_panel_info *mipi;
|
|
struct msm_panel_info *pinfo;
|
|
|
|
mfd = platform_get_drvdata(pdev);
|
|
if (!mfd)
|
|
return -ENODEV;
|
|
if (mfd->key != MFD_KEY)
|
|
return -EINVAL;
|
|
|
|
pinfo = &mfd->panel_info;
|
|
if (pinfo->is_3d_panel)
|
|
support_3d = TRUE;
|
|
|
|
mipi = &mfd->panel_info.mipi;
|
|
|
|
if (mipi->mode == DSI_VIDEO_MODE) {
|
|
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
|
|
ARRAY_SIZE(novatek_video_on_cmds));
|
|
} else {
|
|
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
|
|
ARRAY_SIZE(novatek_cmd_on_cmds));
|
|
|
|
/* clean up ack_err_status */
|
|
mipi_dsi_cmd_bta_sw_trigger();
|
|
mipi_novatek_manufacture_id(mfd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mipi_novatek_lcd_off(struct platform_device *pdev)
|
|
{
|
|
struct msm_fb_data_type *mfd;
|
|
|
|
mfd = platform_get_drvdata(pdev);
|
|
|
|
if (!mfd)
|
|
return -ENODEV;
|
|
if (mfd->key != MFD_KEY)
|
|
return -EINVAL;
|
|
|
|
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
|
|
ARRAY_SIZE(novatek_display_off_cmds));
|
|
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_LED_TRIGGER(bkl_led_trigger);
|
|
|
|
static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
|
|
static struct dsi_cmd_desc backlight_cmd = {
|
|
DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
|
|
|
|
struct dcs_cmd_req cmdreq;
|
|
|
|
static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
|
|
{
|
|
|
|
if ((mipi_novatek_pdata->enable_wled_bl_ctrl)
|
|
&& (wled_trigger_initialized)) {
|
|
led_trigger_event(bkl_led_trigger, mfd->bl_level);
|
|
return;
|
|
}
|
|
|
|
led_pwm1[1] = (unsigned char)mfd->bl_level;
|
|
|
|
cmdreq.cmds = &backlight_cmd;
|
|
cmdreq.cmds_cnt = 1;
|
|
cmdreq.flags = 0;
|
|
cmdreq.rlen = 0;
|
|
cmdreq.cb = NULL;
|
|
|
|
mipi_dsi_cmdlist_put(&cmdreq);
|
|
}
|
|
|
|
static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev);
|
|
static int barrier_mode;
|
|
|
|
static int __devinit mipi_novatek_lcd_probe(struct platform_device *pdev)
|
|
{
|
|
struct msm_fb_data_type *mfd;
|
|
struct mipi_panel_info *mipi;
|
|
struct platform_device *current_pdev;
|
|
static struct mipi_dsi_phy_ctrl *phy_settings;
|
|
static char dlane_swap;
|
|
|
|
if (pdev->id == 0) {
|
|
mipi_novatek_pdata = pdev->dev.platform_data;
|
|
|
|
if (mipi_novatek_pdata
|
|
&& mipi_novatek_pdata->phy_ctrl_settings) {
|
|
phy_settings = (mipi_novatek_pdata->phy_ctrl_settings);
|
|
}
|
|
|
|
if (mipi_novatek_pdata
|
|
&& mipi_novatek_pdata->dlane_swap) {
|
|
dlane_swap = (mipi_novatek_pdata->dlane_swap);
|
|
}
|
|
|
|
if (mipi_novatek_pdata
|
|
&& mipi_novatek_pdata->fpga_3d_config_addr)
|
|
mipi_novatek_3d_init(mipi_novatek_pdata
|
|
->fpga_3d_config_addr, mipi_novatek_pdata->fpga_ctrl_mode);
|
|
|
|
/* create sysfs to control 3D barrier for the Sharp panel */
|
|
if (mipi_dsi_3d_barrier_sysfs_register(&pdev->dev)) {
|
|
pr_err("%s: Failed to register 3d Barrier sysfs\n",
|
|
__func__);
|
|
return -ENODEV;
|
|
}
|
|
barrier_mode = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
current_pdev = msm_fb_add_device(pdev);
|
|
|
|
if (current_pdev) {
|
|
mfd = platform_get_drvdata(current_pdev);
|
|
if (!mfd)
|
|
return -ENODEV;
|
|
if (mfd->key != MFD_KEY)
|
|
return -EINVAL;
|
|
|
|
mipi = &mfd->panel_info.mipi;
|
|
|
|
if (phy_settings != NULL)
|
|
mipi->dsi_phy_db = phy_settings;
|
|
|
|
if (dlane_swap)
|
|
mipi->dlane_swap = dlane_swap;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static struct platform_driver this_driver = {
|
|
.probe = mipi_novatek_lcd_probe,
|
|
.driver = {
|
|
.name = "mipi_novatek",
|
|
},
|
|
};
|
|
|
|
static struct msm_fb_panel_data novatek_panel_data = {
|
|
.on = mipi_novatek_lcd_on,
|
|
.off = mipi_novatek_lcd_off,
|
|
.set_backlight = mipi_novatek_set_backlight,
|
|
};
|
|
|
|
static ssize_t mipi_dsi_3d_barrier_read(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
return snprintf((char *)buf, sizeof(buf), "%u\n", barrier_mode);
|
|
}
|
|
|
|
static ssize_t mipi_dsi_3d_barrier_write(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf,
|
|
size_t count)
|
|
{
|
|
int ret = -1;
|
|
u32 data = 0;
|
|
|
|
if (sscanf((char *)buf, "%u", &data) != 1) {
|
|
dev_err(dev, "%s\n", __func__);
|
|
ret = -EINVAL;
|
|
} else {
|
|
barrier_mode = data;
|
|
if (data == 1)
|
|
mipi_dsi_enable_3d_barrier(LANDSCAPE);
|
|
else if (data == 2)
|
|
mipi_dsi_enable_3d_barrier(PORTRAIT);
|
|
else
|
|
mipi_dsi_enable_3d_barrier(0);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static struct device_attribute mipi_dsi_3d_barrier_attributes[] = {
|
|
__ATTR(enable_3d_barrier, 0664, mipi_dsi_3d_barrier_read,
|
|
mipi_dsi_3d_barrier_write),
|
|
};
|
|
|
|
static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(mipi_dsi_3d_barrier_attributes); i++)
|
|
if (device_create_file(dev, mipi_dsi_3d_barrier_attributes + i))
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
for (; i >= 0 ; i--)
|
|
device_remove_file(dev, mipi_dsi_3d_barrier_attributes + i);
|
|
pr_err("%s: Unable to create interface\n", __func__);
|
|
|
|
return -ENODEV;
|
|
}
|
|
|
|
static int ch_used[3];
|
|
|
|
int mipi_novatek_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;
|
|
|
|
ret = mipi_novatek_lcd_init();
|
|
if (ret) {
|
|
pr_err("mipi_novatek_lcd_init() failed with ret %u\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
pdev = platform_device_alloc("mipi_novatek", (panel << 8)|channel);
|
|
if (!pdev)
|
|
return -ENOMEM;
|
|
|
|
novatek_panel_data.panel_info = *pinfo;
|
|
|
|
ret = platform_device_add_data(pdev, &novatek_panel_data,
|
|
sizeof(novatek_panel_data));
|
|
if (ret) {
|
|
printk(KERN_ERR
|
|
"%s: platform_device_add_data failed!\n", __func__);
|
|
goto err_device_put;
|
|
}
|
|
|
|
ret = platform_device_add(pdev);
|
|
if (ret) {
|
|
printk(KERN_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 mipi_novatek_lcd_init(void)
|
|
{
|
|
#ifdef CONFIG_SPI_QUP
|
|
int ret;
|
|
ret = spi_register_driver(&panel_3d_spi_driver);
|
|
|
|
if (ret) {
|
|
pr_err("%s: spi register failed: rc=%d\n", __func__, ret);
|
|
platform_driver_unregister(&this_driver);
|
|
} else
|
|
pr_info("%s: SUCCESS (SPI)\n", __func__);
|
|
#endif
|
|
|
|
led_trigger_register_simple("bkl_trigger", &bkl_led_trigger);
|
|
pr_info("%s: SUCCESS (WLED TRIGGER)\n", __func__);
|
|
wled_trigger_initialized = 1;
|
|
|
|
mipi_dsi_buf_alloc(&novatek_tx_buf, DSI_BUF_SIZE);
|
|
mipi_dsi_buf_alloc(&novatek_rx_buf, DSI_BUF_SIZE);
|
|
|
|
return platform_driver_register(&this_driver);
|
|
}
|