msm: 8960: Add Chimei MIPI-DSI WXGA panel driver to msm8960.
Add MIPI-DSI Chimei display driver to msm8960 for LiQUID platform.
Enable panel detection for multiple platforms support.
Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index a4242bf..99f97ab 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -150,6 +150,9 @@
PM8XXX_GPIO_DISABLE(6), /* Disable unused */
PM8XXX_GPIO_DISABLE(7), /* Disable NFC */
PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
+ /* External regulator shared by display and touchscreen on LiQUID */
+ PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
+ PM8XXX_GPIO_OUTPUT(21, 1), /* Backlight Enable */
PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
@@ -1034,11 +1037,11 @@
#endif
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-/* prim = 608 x 1024 x 4(bpp) x 3(pages) */
-#define MSM_FB_PRIM_BUF_SIZE 0x720000
+/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 3, 0x10000)
#else
-/* prim = 608 x 1024 x 4(bpp) x 2(pages) */
-#define MSM_FB_PRIM_BUF_SIZE 0x4C0000
+/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 2, 0x10000)
#endif
#ifdef CONFIG_FB_MSM_MIPI_DSI
@@ -1062,22 +1065,168 @@
#define MDP_VSYNC_GPIO 0
+#define TOSHIBA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define TOSHIBA_PANEL_NAME_LEN 24
+#define CHIMEI_PANEL_NAME "mipi_chimei_wxga"
+#define CHIMEI_PANEL_NAME_LEN 16
+
static struct resource msm_fb_resources[] = {
{
.flags = IORESOURCE_DMA,
}
};
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+static int msm_fb_detect_panel(const char *name)
+{
+ if (machine_is_msm8960_liquid()) {
+ if (!strncmp(name, CHIMEI_PANEL_NAME, CHIMEI_PANEL_NAME_LEN))
+ return 0;
+ } else {
+ if (!strncmp(name, TOSHIBA_PANEL_NAME, TOSHIBA_PANEL_NAME_LEN))
+ return 0;
+ }
+
+ pr_warning("%s: not supported '%s'", __func__, name);
+
+ return -ENODEV;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+ .detect_client = msm_fb_detect_panel,
+};
+#endif /* CONFIG_FB_MSM_MIPI_PANEL_DETECT */
+
static struct platform_device msm_fb_device = {
.name = "msm_fb",
.id = 0,
.num_resources = ARRAY_SIZE(msm_fb_resources),
.resource = msm_fb_resources,
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ .dev.platform_data = &msm_fb_pdata,
+#endif /* CONFIG_FB_MSM_MIPI_PANEL_DETECT */
};
static bool dsi_power_on;
-static int mipi_dsi_panel_power(int on)
+/**
+ * LiQUID panel on/off
+ *
+ * @param on
+ *
+ * @return int
+ */
+static int mipi_dsi_liquid_panel_power(int on)
+{
+ static struct regulator *reg_l2, *reg_ext_3p3v;
+ static int gpio21, gpio24, gpio43;
+ int rc;
+
+ pr_info("%s: on=%d\n", __func__, on);
+
+ gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
+ gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
+ gpio24 = PM8921_GPIO_PM_TO_SYS(24); /* Backlight PWM */
+
+ if (!dsi_power_on) {
+
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdda");
+ if (IS_ERR(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
+ "vdd_lvds_3p3v");
+ if (IS_ERR(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio21, "disp_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 21 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio43, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 43 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio24, "disp_backlight_pwm");
+ if (rc) {
+ pr_err("request gpio 24 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ dsi_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ /* set reset pin before power enable */
+ gpio_set_value_cansleep(gpio43, 0); /* disp disable (resx=0) */
+
+ gpio_set_value_cansleep(gpio21, 0); /* disp power enable_n */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 1); /* disp enable */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 0); /* disp enable */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 1); /* disp enable */
+ msleep(20);
+ } else {
+ gpio_set_value_cansleep(gpio43, 0);
+ gpio_set_value_cansleep(gpio21, 1);
+
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_cdp_panel_power(int on)
{
static struct regulator *reg_l8, *reg_l23, *reg_l2;
static int gpio43;
@@ -1227,6 +1376,20 @@
return 0;
}
+static int mipi_dsi_panel_power(int on)
+{
+ int ret;
+
+ pr_info("%s: on=%d\n", __func__, on);
+
+ if (machine_is_msm8960_liquid())
+ ret = mipi_dsi_liquid_panel_power(on);
+ else
+ ret = mipi_dsi_cdp_panel_power(on);
+
+ return ret;
+}
+
static struct mipi_dsi_platform_data mipi_dsi_pdata = {
.vsync_gpio = MDP_VSYNC_GPIO,
.dsi_power_save = mipi_dsi_panel_power,
@@ -1360,6 +1523,21 @@
}
};
+static int dsi2lvds_gpio[2] = {
+ 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
+ 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+ };
+
+static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
+ .gpio_num = dsi2lvds_gpio,
+};
+
+static struct platform_device mipi_dsi2lvds_bridge_device = {
+ .name = "mipi_tc358764",
+ .id = 0,
+ .dev.platform_data = &mipi_dsi2lvds_pdata,
+};
+
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
static struct resource hdmi_msm_resources[] = {
{
@@ -1442,6 +1620,14 @@
static void __init msm_fb_add_devices(void)
{
+ struct platform_device *ptr = NULL;
+
+ if (machine_is_msm8960_liquid())
+ ptr = &mipi_dsi2lvds_bridge_device;
+ else
+ ptr = &mipi_dsi_toshiba_panel_device;
+ platform_add_devices(&ptr, 1);
+
if (machine_is_msm8x60_rumi3()) {
msm_fb_register_device("mdp", NULL);
mipi_dsi_pdata.target_type = 1;
@@ -2875,7 +3061,6 @@
&msm_kgsl_2d0,
&msm_kgsl_2d1,
#endif
- &mipi_dsi_toshiba_panel_device,
#ifdef CONFIG_MSM_GEMINI
&msm8960_gemini_device,
#endif