1454 lines
35 KiB
C
1454 lines
35 KiB
C
/* Copyright (c) 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 <linux/init.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/bootmem.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/gpio.h>
|
|
#include <asm/mach-types.h>
|
|
#include <asm/io.h>
|
|
#include <mach/msm_bus_board.h>
|
|
#include <mach/msm_memtypes.h>
|
|
#include <mach/board.h>
|
|
#include <mach/gpiomux.h>
|
|
#include <mach/socinfo.h>
|
|
#include <mach/rpc_pmapp.h>
|
|
#include "devices.h"
|
|
#include "board-msm7627a.h"
|
|
|
|
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
|
|
#define MSM_FB_SIZE 0x4BF000
|
|
#define MSM7x25A_MSM_FB_SIZE 0x1C2000
|
|
#define MSM8x25_MSM_FB_SIZE 0x5FA000
|
|
#else
|
|
#define MSM_FB_SIZE 0x32A000
|
|
#define MSM7x25A_MSM_FB_SIZE 0x12C000
|
|
#define MSM8x25_MSM_FB_SIZE 0x3FC000
|
|
#endif
|
|
|
|
/*
|
|
* Reserve enough v4l2 space for a double buffered full screen
|
|
* res image (864x480x1.5x2)
|
|
*/
|
|
#define MSM_V4L2_VIDEO_OVERLAY_BUF_SIZE 1244160
|
|
|
|
static unsigned fb_size = MSM_FB_SIZE;
|
|
static int __init fb_size_setup(char *p)
|
|
{
|
|
fb_size = memparse(p, NULL);
|
|
return 0;
|
|
}
|
|
|
|
early_param("fb_size", fb_size_setup);
|
|
|
|
static uint32_t lcdc_truly_gpio_initialized;
|
|
static struct regulator_bulk_data regs_truly_lcdc[] = {
|
|
{ .supply = "rfrx1", .min_uV = 1800000, .max_uV = 1800000 },
|
|
};
|
|
|
|
#define SKU3_LCDC_GPIO_DISPLAY_RESET 90
|
|
#define SKU3_LCDC_GPIO_SPI_MOSI 19
|
|
#define SKU3_LCDC_GPIO_SPI_CLK 20
|
|
#define SKU3_LCDC_GPIO_SPI_CS0_N 21
|
|
#define SKU3_LCDC_LCD_CAMERA_LDO_2V8 35 /*LCD_CAMERA_LDO_2V8*/
|
|
#define SKU3_LCDC_LCD_CAMERA_LDO_1V8 34 /*LCD_CAMERA_LDO_1V8*/
|
|
#define SKU3_1_LCDC_LCD_CAMERA_LDO_1V8 58 /*LCD_CAMERA_LDO_1V8*/
|
|
|
|
static struct regulator *gpio_reg_2p85v_sku3, *gpio_reg_1p8v_sku3;
|
|
|
|
static uint32_t lcdc_truly_gpio_table[] = {
|
|
19,
|
|
20,
|
|
21,
|
|
89,
|
|
90,
|
|
};
|
|
|
|
static char *lcdc_gpio_name_table[5] = {
|
|
"spi_mosi",
|
|
"spi_clk",
|
|
"spi_cs",
|
|
"gpio_bkl_en",
|
|
"gpio_disp_reset",
|
|
};
|
|
|
|
static char lcdc_splash_is_enabled(void);
|
|
static int lcdc_truly_gpio_init(void)
|
|
{
|
|
int i;
|
|
int rc = 0;
|
|
|
|
if (!lcdc_truly_gpio_initialized) {
|
|
for (i = 0; i < ARRAY_SIZE(lcdc_truly_gpio_table); i++) {
|
|
rc = gpio_request(lcdc_truly_gpio_table[i],
|
|
lcdc_gpio_name_table[i]);
|
|
if (rc < 0) {
|
|
pr_err("Error request gpio %s\n",
|
|
lcdc_gpio_name_table[i]);
|
|
goto truly_gpio_fail;
|
|
}
|
|
rc = gpio_tlmm_config(GPIO_CFG(lcdc_truly_gpio_table[i],
|
|
0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
|
|
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("Error config lcdc gpio:%d\n",
|
|
lcdc_truly_gpio_table[i]);
|
|
goto truly_gpio_fail;
|
|
}
|
|
if (lcdc_splash_is_enabled())
|
|
rc = gpio_direction_output(
|
|
lcdc_truly_gpio_table[i], 1);
|
|
else
|
|
rc = gpio_direction_output(
|
|
lcdc_truly_gpio_table[i], 0);
|
|
if (rc < 0) {
|
|
pr_err("Error direct lcdc gpio:%d\n",
|
|
lcdc_truly_gpio_table[i]);
|
|
goto truly_gpio_fail;
|
|
}
|
|
}
|
|
|
|
lcdc_truly_gpio_initialized = 1;
|
|
}
|
|
|
|
return rc;
|
|
|
|
truly_gpio_fail:
|
|
for (; i >= 0; i--) {
|
|
pr_err("Freeing GPIO: %d", lcdc_truly_gpio_table[i]);
|
|
gpio_free(lcdc_truly_gpio_table[i]);
|
|
}
|
|
|
|
lcdc_truly_gpio_initialized = 0;
|
|
return rc;
|
|
}
|
|
|
|
|
|
void sku3_lcdc_power_init(void)
|
|
{
|
|
int rc = 0;
|
|
u32 socinfo = socinfo_get_platform_type();
|
|
|
|
/* LDO_EXT2V8 */
|
|
if (gpio_request(SKU3_LCDC_LCD_CAMERA_LDO_2V8, "lcd_camera_ldo_2v8")) {
|
|
pr_err("failed to request gpio lcd_camera_ldo_2v8\n");
|
|
return;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(GPIO_CFG(SKU3_LCDC_LCD_CAMERA_LDO_2V8, 0,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s:unable to enable lcd_camera_ldo_2v8!\n", __func__);
|
|
goto fail_gpio2;
|
|
}
|
|
|
|
/* LDO_EVT1V8 */
|
|
if (socinfo == 0x0B) {
|
|
if (gpio_request(SKU3_LCDC_LCD_CAMERA_LDO_1V8,
|
|
"lcd_camera_ldo_1v8")) {
|
|
pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
|
|
goto fail_gpio1;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(GPIO_CFG(SKU3_LCDC_LCD_CAMERA_LDO_1V8, 0,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: unable to enable lcdc_camera_ldo_1v8!\n",
|
|
__func__);
|
|
goto fail_gpio1;
|
|
}
|
|
} else if (socinfo == 0x0F || machine_is_msm8625_qrd7()) {
|
|
if (gpio_request(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
|
|
"lcd_camera_ldo_1v8")) {
|
|
pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
|
|
goto fail_gpio1;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(GPIO_CFG(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8,
|
|
0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: unable to enable lcdc_camera_ldo_1v8!\n",
|
|
__func__);
|
|
goto fail_gpio1;
|
|
}
|
|
}
|
|
|
|
if (socinfo == 0x0B)
|
|
gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_1V8);
|
|
else if (socinfo == 0x0F || machine_is_msm8625_qrd7())
|
|
gpio_free(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8);
|
|
|
|
gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_2V8);
|
|
|
|
gpio_reg_2p85v_sku3 = regulator_get(&msm_lcdc_device.dev,
|
|
"lcd_vdd_sku3");
|
|
if (IS_ERR(gpio_reg_2p85v_sku3)) {
|
|
pr_err("%s:ext_2p85v regulator get failed", __func__);
|
|
regulator_put(gpio_reg_2p85v_sku3);
|
|
return;
|
|
}
|
|
|
|
gpio_reg_1p8v_sku3 = regulator_get(&msm_lcdc_device.dev,
|
|
"lcd_vddi_sku3");
|
|
if (IS_ERR(gpio_reg_1p8v_sku3)) {
|
|
pr_err("%s:ext_1p8v regulator get failed", __func__);
|
|
regulator_put(gpio_reg_1p8v_sku3);
|
|
return;
|
|
}
|
|
|
|
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_truly_lcdc),
|
|
regs_truly_lcdc);
|
|
if (rc)
|
|
pr_err("%s: could not get regulators: %d\n", __func__, rc);
|
|
|
|
rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_truly_lcdc),
|
|
regs_truly_lcdc);
|
|
if (rc)
|
|
pr_err("%s: could not set voltages: %d\n", __func__, rc);
|
|
|
|
return;
|
|
|
|
fail_gpio1:
|
|
if (socinfo == 0x0B)
|
|
gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_1V8);
|
|
else if (socinfo == 0x0F || machine_is_msm8625_qrd7())
|
|
gpio_free(SKU3_1_LCDC_LCD_CAMERA_LDO_1V8);
|
|
fail_gpio2:
|
|
gpio_free(SKU3_LCDC_LCD_CAMERA_LDO_2V8);
|
|
return;
|
|
}
|
|
|
|
int sku3_lcdc_power_onoff(int on)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (on) {
|
|
rc = regulator_enable(gpio_reg_2p85v_sku3);
|
|
if (rc < 0) {
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
rc = regulator_enable(gpio_reg_1p8v_sku3);
|
|
if (rc < 0) {
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = regulator_bulk_enable(ARRAY_SIZE(regs_truly_lcdc),
|
|
regs_truly_lcdc);
|
|
if (rc) {
|
|
pr_err("%s: could not enable regulators: %d\n",
|
|
__func__, rc);
|
|
return -EINVAL;
|
|
}
|
|
} else {
|
|
rc = regulator_disable(gpio_reg_2p85v_sku3);
|
|
if (rc < 0) {
|
|
pr_err("%s: reg disable failed\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
rc = regulator_disable(gpio_reg_1p8v_sku3);
|
|
if (rc < 0) {
|
|
pr_err("%s: reg disable failed\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = regulator_bulk_disable(ARRAY_SIZE(regs_truly_lcdc),
|
|
regs_truly_lcdc);
|
|
if (rc) {
|
|
pr_err("%s: could not disable regulators: %d\n",
|
|
__func__, rc);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int sku3_lcdc_power_save(int on)
|
|
{
|
|
int rc = 0;
|
|
static int cont_splash_done;
|
|
|
|
if (on) {
|
|
sku3_lcdc_power_onoff(1);
|
|
rc = lcdc_truly_gpio_init();
|
|
if (rc < 0) {
|
|
pr_err("%s(): Truly GPIO initializations failed",
|
|
__func__);
|
|
return rc;
|
|
}
|
|
|
|
if (lcdc_splash_is_enabled() && !cont_splash_done) {
|
|
cont_splash_done = 1;
|
|
return rc;
|
|
}
|
|
|
|
if (lcdc_truly_gpio_initialized) {
|
|
/*LCD reset*/
|
|
gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 1);
|
|
msleep(20);
|
|
gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 0);
|
|
msleep(20);
|
|
gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 1);
|
|
msleep(20);
|
|
}
|
|
} else {
|
|
/* pull down LCD IO to avoid current leakage */
|
|
gpio_set_value(SKU3_LCDC_GPIO_SPI_MOSI, 0);
|
|
gpio_set_value(SKU3_LCDC_GPIO_SPI_CLK, 0);
|
|
gpio_set_value(SKU3_LCDC_GPIO_SPI_CS0_N, 0);
|
|
gpio_set_value(SKU3_LCDC_GPIO_DISPLAY_RESET, 0);
|
|
|
|
sku3_lcdc_power_onoff(0);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static struct msm_panel_common_pdata lcdc_truly_panel_data = {
|
|
.panel_config_gpio = NULL,
|
|
.gpio_num = lcdc_truly_gpio_table,
|
|
};
|
|
|
|
static struct platform_device lcdc_truly_panel_device = {
|
|
.name = "lcdc_truly_hvga_ips3p2335_pt",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &lcdc_truly_panel_data,
|
|
}
|
|
};
|
|
|
|
static struct regulator_bulk_data regs_lcdc[] = {
|
|
{ .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
|
|
{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
|
|
};
|
|
static uint32_t lcdc_gpio_initialized;
|
|
|
|
static void lcdc_toshiba_gpio_init(void)
|
|
{
|
|
int rc = 0;
|
|
if (!lcdc_gpio_initialized) {
|
|
if (gpio_request(GPIO_SPI_CLK, "spi_clk")) {
|
|
pr_err("failed to request gpio spi_clk\n");
|
|
return;
|
|
}
|
|
if (gpio_request(GPIO_SPI_CS0_N, "spi_cs")) {
|
|
pr_err("failed to request gpio spi_cs0_N\n");
|
|
goto fail_gpio6;
|
|
}
|
|
if (gpio_request(GPIO_SPI_MOSI, "spi_mosi")) {
|
|
pr_err("failed to request gpio spi_mosi\n");
|
|
goto fail_gpio5;
|
|
}
|
|
if (gpio_request(GPIO_SPI_MISO, "spi_miso")) {
|
|
pr_err("failed to request gpio spi_miso\n");
|
|
goto fail_gpio4;
|
|
}
|
|
if (gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr")) {
|
|
pr_err("failed to request gpio_disp_pwr\n");
|
|
goto fail_gpio3;
|
|
}
|
|
if (gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en")) {
|
|
pr_err("failed to request gpio_bkl_en\n");
|
|
goto fail_gpio2;
|
|
}
|
|
pmapp_disp_backlight_init();
|
|
|
|
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_lcdc),
|
|
regs_lcdc);
|
|
if (rc) {
|
|
pr_err("%s: could not get regulators: %d\n",
|
|
__func__, rc);
|
|
goto fail_gpio1;
|
|
}
|
|
|
|
rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_lcdc),
|
|
regs_lcdc);
|
|
if (rc) {
|
|
pr_err("%s: could not set voltages: %d\n",
|
|
__func__, rc);
|
|
goto fail_vreg;
|
|
}
|
|
lcdc_gpio_initialized = 1;
|
|
}
|
|
return;
|
|
fail_vreg:
|
|
regulator_bulk_free(ARRAY_SIZE(regs_lcdc), regs_lcdc);
|
|
fail_gpio1:
|
|
gpio_free(GPIO_BACKLIGHT_EN);
|
|
fail_gpio2:
|
|
gpio_free(GPIO_DISPLAY_PWR_EN);
|
|
fail_gpio3:
|
|
gpio_free(GPIO_SPI_MISO);
|
|
fail_gpio4:
|
|
gpio_free(GPIO_SPI_MOSI);
|
|
fail_gpio5:
|
|
gpio_free(GPIO_SPI_CS0_N);
|
|
fail_gpio6:
|
|
gpio_free(GPIO_SPI_CLK);
|
|
lcdc_gpio_initialized = 0;
|
|
}
|
|
|
|
static uint32_t lcdc_gpio_table[] = {
|
|
GPIO_SPI_CLK,
|
|
GPIO_SPI_CS0_N,
|
|
GPIO_SPI_MOSI,
|
|
GPIO_DISPLAY_PWR_EN,
|
|
GPIO_BACKLIGHT_EN,
|
|
GPIO_SPI_MISO,
|
|
};
|
|
|
|
static void config_lcdc_gpio_table(uint32_t *table, int len, unsigned enable)
|
|
{
|
|
int n;
|
|
|
|
if (lcdc_gpio_initialized) {
|
|
/* All are IO Expander GPIOs */
|
|
for (n = 0; n < (len - 1); n++)
|
|
gpio_direction_output(table[n], 1);
|
|
}
|
|
}
|
|
|
|
static void lcdc_toshiba_config_gpios(int enable)
|
|
{
|
|
config_lcdc_gpio_table(lcdc_gpio_table,
|
|
ARRAY_SIZE(lcdc_gpio_table), enable);
|
|
}
|
|
|
|
static int msm_fb_lcdc_power_save(int on)
|
|
{
|
|
int rc = 0;
|
|
/* Doing the init of the LCDC GPIOs very late as they are from
|
|
an I2C-controlled IO Expander */
|
|
lcdc_toshiba_gpio_init();
|
|
|
|
if (lcdc_gpio_initialized) {
|
|
gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
|
|
gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
|
|
|
|
rc = on ? regulator_bulk_enable(
|
|
ARRAY_SIZE(regs_lcdc), regs_lcdc) :
|
|
regulator_bulk_disable(
|
|
ARRAY_SIZE(regs_lcdc), regs_lcdc);
|
|
|
|
if (rc)
|
|
pr_err("%s: could not %sable regulators: %d\n",
|
|
__func__, on ? "en" : "dis", rc);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int lcdc_toshiba_set_bl(int level)
|
|
{
|
|
int ret;
|
|
|
|
ret = pmapp_disp_backlight_set_brightness(level);
|
|
if (ret)
|
|
pr_err("%s: can't set lcd backlight!\n", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int msm_lcdc_power_save(int on)
|
|
{
|
|
int rc = 0;
|
|
if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
|
|
rc = sku3_lcdc_power_save(on);
|
|
else
|
|
rc = msm_fb_lcdc_power_save(on);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static struct lcdc_platform_data lcdc_pdata = {
|
|
.lcdc_gpio_config = NULL,
|
|
.lcdc_power_save = msm_lcdc_power_save,
|
|
};
|
|
|
|
static int lcd_panel_spi_gpio_num[] = {
|
|
GPIO_SPI_MOSI, /* spi_sdi */
|
|
GPIO_SPI_MISO, /* spi_sdoi */
|
|
GPIO_SPI_CLK, /* spi_clk */
|
|
GPIO_SPI_CS0_N, /* spi_cs */
|
|
};
|
|
|
|
static struct msm_panel_common_pdata lcdc_toshiba_panel_data = {
|
|
.panel_config_gpio = lcdc_toshiba_config_gpios,
|
|
.pmic_backlight = lcdc_toshiba_set_bl,
|
|
.gpio_num = lcd_panel_spi_gpio_num,
|
|
};
|
|
|
|
static struct platform_device lcdc_toshiba_panel_device = {
|
|
.name = "lcdc_toshiba_fwvga_pt",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &lcdc_toshiba_panel_data,
|
|
}
|
|
};
|
|
|
|
static struct resource msm_fb_resources[] = {
|
|
{
|
|
.flags = IORESOURCE_DMA,
|
|
}
|
|
};
|
|
|
|
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
|
|
static struct resource msm_v4l2_video_overlay_resources[] = {
|
|
{
|
|
.flags = IORESOURCE_DMA,
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#define LCDC_TOSHIBA_FWVGA_PANEL_NAME "lcdc_toshiba_fwvga_pt"
|
|
#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
|
|
|
|
static int msm_fb_detect_panel(const char *name)
|
|
{
|
|
int ret = -ENODEV;
|
|
|
|
if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
|
|
machine_is_msm8625_surf()) {
|
|
if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
|
|
!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
|
|
ret = 0;
|
|
} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
|
|
|| machine_is_msm8625_ffa()) {
|
|
if (!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
|
|
ret = 0;
|
|
} else if (machine_is_msm7627a_qrd1()) {
|
|
if (!strncmp(name, "mipi_video_truly_wvga", 21))
|
|
ret = 0;
|
|
} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
|
|
if (!strncmp(name, "lcdc_truly_hvga_ips3p2335_pt", 28))
|
|
ret = 0;
|
|
} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
|
|
machine_is_msm8625_evt() ||
|
|
machine_is_qrd_skud_prime()) {
|
|
if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
|
|
ret = 0;
|
|
}
|
|
|
|
#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
|
|
!defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
|
|
!defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
|
|
if (machine_is_msm7x27a_surf() ||
|
|
machine_is_msm7625a_surf() ||
|
|
machine_is_msm8625_surf()) {
|
|
if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
|
|
strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
|
|
PANEL_NAME_MAX_LEN)))
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mipi_truly_set_bl(int on)
|
|
{
|
|
gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static struct msm_fb_platform_data msm_fb_pdata = {
|
|
.detect_client = msm_fb_detect_panel,
|
|
};
|
|
|
|
static struct platform_device msm_fb_device = {
|
|
.name = "msm_fb",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(msm_fb_resources),
|
|
.resource = msm_fb_resources,
|
|
.dev = {
|
|
.platform_data = &msm_fb_pdata,
|
|
}
|
|
};
|
|
|
|
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
|
|
static struct platform_device msm_v4l2_video_overlay_device = {
|
|
.name = "msm_v4l2_overlay_pd",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(msm_v4l2_video_overlay_resources),
|
|
.resource = msm_v4l2_video_overlay_resources,
|
|
};
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_FB_MSM_MIPI_DSI
|
|
static int mipi_renesas_set_bl(int level)
|
|
{
|
|
int ret;
|
|
|
|
ret = pmapp_disp_backlight_set_brightness(level);
|
|
|
|
if (ret)
|
|
pr_err("%s: can't set lcd backlight!\n", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct msm_panel_common_pdata mipi_renesas_pdata = {
|
|
.pmic_backlight = mipi_renesas_set_bl,
|
|
};
|
|
|
|
|
|
static struct platform_device mipi_dsi_renesas_panel_device = {
|
|
.name = "mipi_renesas",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &mipi_renesas_pdata,
|
|
}
|
|
};
|
|
#endif
|
|
|
|
static int evb_backlight_control(int level, int mode)
|
|
{
|
|
|
|
int i = 0;
|
|
int remainder, ret = 0;
|
|
|
|
/* device address byte = 0x72 */
|
|
if (!mode) {
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
gpio_set_value(96, 0);
|
|
udelay(33);
|
|
gpio_set_value(96, 1);
|
|
udelay(67);
|
|
gpio_set_value(96, 0);
|
|
udelay(33);
|
|
gpio_set_value(96, 1);
|
|
udelay(67);
|
|
gpio_set_value(96, 0);
|
|
udelay(33);
|
|
gpio_set_value(96, 1);
|
|
udelay(67);
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
gpio_set_value(96, 0);
|
|
udelay(33);
|
|
gpio_set_value(96, 1);
|
|
udelay(67);
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
|
|
/* t-EOS and t-start */
|
|
gpio_set_value(96, 0);
|
|
ndelay(4200);
|
|
gpio_set_value(96, 1);
|
|
ndelay(9000);
|
|
|
|
/* data byte */
|
|
/* RFA = 0 */
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
|
|
/* Address bits */
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
|
|
/* Data bits */
|
|
for (i = 0; i < 5; i++) {
|
|
remainder = (level) & (16);
|
|
if (remainder) {
|
|
gpio_set_value(96, 0);
|
|
udelay(33);
|
|
gpio_set_value(96, 1);
|
|
udelay(67);
|
|
} else {
|
|
gpio_set_value(96, 0);
|
|
udelay(67);
|
|
gpio_set_value(96, 1);
|
|
udelay(33);
|
|
}
|
|
level = level << 1;
|
|
}
|
|
|
|
/* t-EOS */
|
|
gpio_set_value(96, 0);
|
|
ndelay(12000);
|
|
gpio_set_value(96, 1);
|
|
} else {
|
|
ret = pmapp_disp_backlight_set_brightness(level);
|
|
if (ret)
|
|
pr_err("%s: can't set lcd backlight!\n", __func__);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mipi_NT35510_rotate_panel(void)
|
|
{
|
|
int rotate = 0;
|
|
if (machine_is_msm8625_evt())
|
|
rotate = 1;
|
|
|
|
return rotate;
|
|
}
|
|
|
|
static struct msm_panel_common_pdata mipi_truly_pdata = {
|
|
.pmic_backlight = mipi_truly_set_bl,
|
|
};
|
|
|
|
static struct platform_device mipi_dsi_truly_panel_device = {
|
|
.name = "mipi_truly",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &mipi_truly_pdata,
|
|
}
|
|
};
|
|
|
|
static struct msm_panel_common_pdata mipi_NT35510_pdata = {
|
|
.backlight = evb_backlight_control,
|
|
.rotate_panel = mipi_NT35510_rotate_panel,
|
|
};
|
|
|
|
static struct platform_device mipi_dsi_NT35510_panel_device = {
|
|
.name = "mipi_NT35510",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &mipi_NT35510_pdata,
|
|
}
|
|
};
|
|
|
|
static struct msm_panel_common_pdata mipi_NT35516_pdata = {
|
|
.backlight = evb_backlight_control,
|
|
};
|
|
|
|
static struct platform_device mipi_dsi_NT35516_panel_device = {
|
|
.name = "mipi_truly_tft540960_1_e",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &mipi_NT35516_pdata,
|
|
}
|
|
};
|
|
|
|
static struct platform_device *msm_fb_devices[] __initdata = {
|
|
&msm_fb_device,
|
|
&lcdc_toshiba_panel_device,
|
|
#ifdef CONFIG_FB_MSM_MIPI_DSI
|
|
&mipi_dsi_renesas_panel_device,
|
|
#endif
|
|
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
|
|
&msm_v4l2_video_overlay_device,
|
|
#endif
|
|
};
|
|
|
|
static struct platform_device *qrd_fb_devices[] __initdata = {
|
|
&msm_fb_device,
|
|
&mipi_dsi_truly_panel_device,
|
|
};
|
|
|
|
static struct platform_device *qrd3_fb_devices[] __initdata = {
|
|
&msm_fb_device,
|
|
&lcdc_truly_panel_device,
|
|
};
|
|
|
|
static struct platform_device *evb_fb_devices[] __initdata = {
|
|
&msm_fb_device,
|
|
&mipi_dsi_NT35510_panel_device,
|
|
&mipi_dsi_NT35516_panel_device,
|
|
};
|
|
|
|
void __init msm_msm7627a_allocate_memory_regions(void)
|
|
{
|
|
void *addr;
|
|
unsigned long fb_size;
|
|
|
|
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
|
|
fb_size = MSM7x25A_MSM_FB_SIZE;
|
|
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|
|
|| machine_is_msm8625_evt()
|
|
|| machine_is_qrd_skud_prime())
|
|
fb_size = MSM8x25_MSM_FB_SIZE;
|
|
else
|
|
fb_size = MSM_FB_SIZE;
|
|
|
|
addr = alloc_bootmem_align(fb_size, 0x1000);
|
|
msm_fb_resources[0].start = __pa(addr);
|
|
msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;
|
|
pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", fb_size,
|
|
addr, __pa(addr));
|
|
|
|
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
|
|
fb_size = MSM_V4L2_VIDEO_OVERLAY_BUF_SIZE;
|
|
addr = alloc_bootmem_align(fb_size, 0x1000);
|
|
msm_v4l2_video_overlay_resources[0].start = __pa(addr);
|
|
msm_v4l2_video_overlay_resources[0].end =
|
|
msm_v4l2_video_overlay_resources[0].start + fb_size - 1;
|
|
pr_debug("allocating %lu bytes at %p (%lx physical) for v4l2\n",
|
|
fb_size, addr, __pa(addr));
|
|
#endif
|
|
|
|
}
|
|
|
|
static struct msm_panel_common_pdata mdp_pdata = {
|
|
.gpio = 97,
|
|
.mdp_rev = MDP_REV_303,
|
|
.cont_splash_enabled = 0x1,
|
|
};
|
|
|
|
static char lcdc_splash_is_enabled()
|
|
{
|
|
return mdp_pdata.cont_splash_enabled;
|
|
}
|
|
|
|
#define GPIO_LCDC_BRDG_PD 128
|
|
#define GPIO_LCDC_BRDG_RESET_N 129
|
|
#define GPIO_LCD_DSI_SEL 125
|
|
#define LCDC_RESET_PHYS 0x90008014
|
|
|
|
static void __iomem *lcdc_reset_ptr;
|
|
|
|
static unsigned mipi_dsi_gpio[] = {
|
|
GPIO_CFG(GPIO_LCDC_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_RESET_N */
|
|
GPIO_CFG(GPIO_LCDC_BRDG_PD, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* LCDC_BRDG_PD */
|
|
};
|
|
|
|
static unsigned lcd_dsi_sel_gpio[] = {
|
|
GPIO_CFG(GPIO_LCD_DSI_SEL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
|
|
GPIO_CFG_2MA),
|
|
};
|
|
|
|
enum {
|
|
DSI_SINGLE_LANE = 1,
|
|
DSI_TWO_LANES,
|
|
};
|
|
|
|
static int msm_fb_get_lane_config(void)
|
|
{
|
|
/* For MSM7627A SURF/FFA and QRD */
|
|
int rc = DSI_TWO_LANES;
|
|
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
|
|
rc = DSI_SINGLE_LANE;
|
|
pr_info("DSI_SINGLE_LANES\n");
|
|
} else {
|
|
pr_info("DSI_TWO_LANES\n");
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static int msm_fb_dsi_client_msm_reset(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
|
|
if (rc < 0) {
|
|
pr_err("failed to request lcd brdg reset_n\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_request(GPIO_LCDC_BRDG_PD, "lcdc_brdg_pd");
|
|
if (rc < 0) {
|
|
pr_err("failed to request lcd brdg pd\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
|
|
if (rc) {
|
|
pr_err("Failed to enable LCDC Bridge reset enable\n");
|
|
goto gpio_error;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(mipi_dsi_gpio[1], GPIO_CFG_ENABLE);
|
|
if (rc) {
|
|
pr_err("Failed to enable LCDC Bridge pd enable\n");
|
|
goto gpio_error2;
|
|
}
|
|
|
|
rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
|
|
rc |= gpio_direction_output(GPIO_LCDC_BRDG_PD, 1);
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
|
|
|
|
if (!rc) {
|
|
if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
|
|
|| machine_is_msm8625_surf()) {
|
|
lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
|
|
sizeof(uint32_t));
|
|
|
|
if (!lcdc_reset_ptr)
|
|
return 0;
|
|
}
|
|
return rc;
|
|
} else {
|
|
goto gpio_error;
|
|
}
|
|
|
|
gpio_error2:
|
|
pr_err("Failed GPIO bridge pd\n");
|
|
gpio_free(GPIO_LCDC_BRDG_PD);
|
|
|
|
gpio_error:
|
|
pr_err("Failed GPIO bridge reset\n");
|
|
gpio_free(GPIO_LCDC_BRDG_RESET_N);
|
|
return rc;
|
|
}
|
|
|
|
static int mipi_truly_sel_mode(int video_mode)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = gpio_request(GPIO_LCD_DSI_SEL, "lcd_dsi_sel");
|
|
if (rc < 0)
|
|
goto gpio_error;
|
|
|
|
rc = gpio_tlmm_config(lcd_dsi_sel_gpio[0], GPIO_CFG_ENABLE);
|
|
if (rc)
|
|
goto gpio_error;
|
|
|
|
rc = gpio_direction_output(GPIO_LCD_DSI_SEL, 1);
|
|
if (!rc) {
|
|
gpio_set_value_cansleep(GPIO_LCD_DSI_SEL, video_mode);
|
|
return rc;
|
|
} else {
|
|
goto gpio_error;
|
|
}
|
|
|
|
gpio_error:
|
|
pr_err("mipi_truly_sel_mode failed\n");
|
|
gpio_free(GPIO_LCD_DSI_SEL);
|
|
return rc;
|
|
}
|
|
|
|
static int msm_fb_dsi_client_qrd1_reset(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = gpio_request(GPIO_LCDC_BRDG_RESET_N, "lcdc_brdg_reset_n");
|
|
if (rc < 0) {
|
|
pr_err("failed to request lcd brdg reset_n\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_tlmm_config(mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("Failed to enable LCDC Bridge reset enable\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_direction_output(GPIO_LCDC_BRDG_RESET_N, 1);
|
|
if (rc < 0) {
|
|
pr_err("Failed GPIO bridge pd\n");
|
|
gpio_free(GPIO_LCDC_BRDG_RESET_N);
|
|
return rc;
|
|
}
|
|
|
|
mipi_truly_sel_mode(1);
|
|
|
|
return rc;
|
|
}
|
|
|
|
#define GPIO_QRD3_LCD_BRDG_RESET_N 85
|
|
#define GPIO_QRD3_LCD_BACKLIGHT_EN 96
|
|
#define GPIO_QRD3_LCD_EXT_2V85_EN 35
|
|
#define GPIO_QRD3_LCD_EXT_1V8_EN 40
|
|
|
|
static unsigned qrd3_mipi_dsi_gpio[] = {
|
|
GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL,
|
|
GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
|
|
GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL,
|
|
GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
|
|
GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL,
|
|
GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
|
|
GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_NO_PULL,
|
|
GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
|
|
};
|
|
|
|
static int msm_fb_dsi_client_qrd3_reset(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
|
|
if (rc < 0) {
|
|
pr_err("failed to request qrd3 lcd brdg reset_n\n");
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int msm_fb_dsi_client_reset(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (machine_is_msm7627a_qrd1())
|
|
rc = msm_fb_dsi_client_qrd1_reset();
|
|
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|
|
|| machine_is_msm8625_evt()
|
|
|| machine_is_qrd_skud_prime())
|
|
rc = msm_fb_dsi_client_qrd3_reset();
|
|
else
|
|
rc = msm_fb_dsi_client_msm_reset();
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
static struct regulator_bulk_data regs_dsi[] = {
|
|
{ .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
|
|
{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
|
|
};
|
|
|
|
static int dsi_gpio_initialized;
|
|
|
|
static int mipi_dsi_panel_msm_power(int on)
|
|
{
|
|
int rc = 0;
|
|
uint32_t lcdc_reset_cfg;
|
|
|
|
/* I2C-controlled GPIO Expander -init of the GPIOs very late */
|
|
if (unlikely(!dsi_gpio_initialized)) {
|
|
pmapp_disp_backlight_init();
|
|
|
|
rc = gpio_request(GPIO_DISPLAY_PWR_EN, "gpio_disp_pwr");
|
|
if (rc < 0) {
|
|
pr_err("failed to request gpio_disp_pwr\n");
|
|
return rc;
|
|
}
|
|
|
|
if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
|
|
|| machine_is_msm8625_surf()) {
|
|
rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
|
|
if (rc < 0) {
|
|
pr_err("failed to enable display pwr\n");
|
|
goto fail_gpio1;
|
|
}
|
|
|
|
rc = gpio_request(GPIO_BACKLIGHT_EN, "gpio_bkl_en");
|
|
if (rc < 0) {
|
|
pr_err("failed to request gpio_bkl_en\n");
|
|
goto fail_gpio1;
|
|
}
|
|
|
|
rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
|
|
if (rc < 0) {
|
|
pr_err("failed to enable backlight\n");
|
|
goto fail_gpio2;
|
|
}
|
|
}
|
|
|
|
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_dsi), regs_dsi);
|
|
if (rc) {
|
|
pr_err("%s: could not get regulators: %d\n",
|
|
__func__, rc);
|
|
goto fail_gpio2;
|
|
}
|
|
|
|
rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_dsi),
|
|
regs_dsi);
|
|
if (rc) {
|
|
pr_err("%s: could not set voltages: %d\n",
|
|
__func__, rc);
|
|
goto fail_vreg;
|
|
}
|
|
if (pmapp_disp_backlight_set_brightness(100))
|
|
pr_err("backlight set brightness failed\n");
|
|
|
|
dsi_gpio_initialized = 1;
|
|
}
|
|
if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
|
|
machine_is_msm8625_surf()) {
|
|
gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
|
|
gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
|
|
} else if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
|
|
|| machine_is_msm8625_ffa()) {
|
|
if (on) {
|
|
/* This line drives an active low pin on FFA */
|
|
rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, !on);
|
|
if (rc < 0)
|
|
pr_err("failed to set direction for "
|
|
"display pwr\n");
|
|
} else {
|
|
gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, !on);
|
|
rc = gpio_direction_input(GPIO_DISPLAY_PWR_EN);
|
|
if (rc < 0)
|
|
pr_err("failed to set direction for "
|
|
"display pwr\n");
|
|
}
|
|
}
|
|
|
|
if (on) {
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
|
|
|
|
if (machine_is_msm7x27a_surf() ||
|
|
machine_is_msm7625a_surf() ||
|
|
machine_is_msm8625_surf()) {
|
|
lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
|
|
rmb();
|
|
lcdc_reset_cfg &= ~1;
|
|
|
|
writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
|
|
msleep(20);
|
|
wmb();
|
|
lcdc_reset_cfg |= 1;
|
|
writel_relaxed(lcdc_reset_cfg, lcdc_reset_ptr);
|
|
msleep(20);
|
|
} else {
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
|
|
msleep(20);
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
|
|
msleep(20);
|
|
}
|
|
} else {
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 1);
|
|
}
|
|
|
|
rc = on ? regulator_bulk_enable(ARRAY_SIZE(regs_dsi), regs_dsi) :
|
|
regulator_bulk_disable(ARRAY_SIZE(regs_dsi), regs_dsi);
|
|
|
|
if (rc)
|
|
pr_err("%s: could not %sable regulators: %d\n",
|
|
__func__, on ? "en" : "dis", rc);
|
|
|
|
return rc;
|
|
fail_vreg:
|
|
regulator_bulk_free(ARRAY_SIZE(regs_dsi), regs_dsi);
|
|
fail_gpio2:
|
|
gpio_free(GPIO_BACKLIGHT_EN);
|
|
fail_gpio1:
|
|
gpio_free(GPIO_DISPLAY_PWR_EN);
|
|
dsi_gpio_initialized = 0;
|
|
return rc;
|
|
}
|
|
|
|
static int mipi_dsi_panel_qrd1_power(int on)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (!dsi_gpio_initialized) {
|
|
rc = gpio_request(QRD_GPIO_BACKLIGHT_EN, "gpio_bkl_en");
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
rc = gpio_tlmm_config(GPIO_CFG(QRD_GPIO_BACKLIGHT_EN, 0,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_direction_output(QRD_GPIO_BACKLIGHT_EN, 1);
|
|
if (rc < 0) {
|
|
pr_err("failed to enable backlight\n");
|
|
gpio_free(QRD_GPIO_BACKLIGHT_EN);
|
|
return rc;
|
|
}
|
|
dsi_gpio_initialized = 1;
|
|
}
|
|
|
|
gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
|
|
|
|
if (on) {
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
|
|
msleep(20);
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
|
|
msleep(20);
|
|
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
|
|
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int qrd3_dsi_gpio_initialized;
|
|
static struct regulator *gpio_reg_2p85v, *gpio_reg_1p8v;
|
|
|
|
static int mipi_dsi_panel_qrd3_power(int on)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (!qrd3_dsi_gpio_initialized) {
|
|
pmapp_disp_backlight_init();
|
|
rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
|
|
"qrd3_gpio_bkl_en");
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
qrd3_dsi_gpio_initialized = 1;
|
|
|
|
if (mdp_pdata.cont_splash_enabled) {
|
|
rc = gpio_tlmm_config(GPIO_CFG(
|
|
GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
|
|
GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
|
|
return rc;
|
|
}
|
|
rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN,
|
|
1);
|
|
if (rc < 0) {
|
|
pr_err("failed to enable backlight\n");
|
|
gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
|
|
return rc;
|
|
}
|
|
|
|
/*Configure LCD Bridge reset*/
|
|
rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0],
|
|
GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("Failed to enable LCD Bridge reset enable\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N,
|
|
1);
|
|
|
|
if (rc < 0) {
|
|
pr_err("Failed GPIO bridge Reset\n");
|
|
gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
|
|
return rc;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (on) {
|
|
rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
|
|
return rc;
|
|
}
|
|
rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
|
|
if (rc < 0) {
|
|
pr_err("failed to enable backlight\n");
|
|
gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
|
|
return rc;
|
|
}
|
|
/*Toggle Backlight GPIO*/
|
|
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
|
|
udelay(100);
|
|
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
|
|
udelay(430);
|
|
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
|
|
/* 1 wire mode starts from this low to high transition */
|
|
udelay(50);
|
|
|
|
/*Enable EXT_2.85 and 1.8 regulators*/
|
|
rc = regulator_enable(gpio_reg_2p85v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
rc = regulator_enable(gpio_reg_1p8v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
|
|
/*Configure LCD Bridge reset*/
|
|
rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
|
|
if (rc < 0) {
|
|
pr_err("Failed to enable LCD Bridge reset enable\n");
|
|
return rc;
|
|
}
|
|
|
|
rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
|
|
|
|
if (rc < 0) {
|
|
pr_err("Failed GPIO bridge Reset\n");
|
|
gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
|
|
return rc;
|
|
}
|
|
|
|
/*Toggle Bridge Reset GPIO*/
|
|
msleep(20);
|
|
gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
|
|
msleep(20);
|
|
gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
|
|
msleep(20);
|
|
|
|
} else {
|
|
gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
|
|
GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
|
|
GPIO_CFG_DISABLE);
|
|
|
|
gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0,
|
|
GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_DISABLE);
|
|
|
|
rc = regulator_disable(gpio_reg_2p85v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg disable failed\n", __func__);
|
|
rc = regulator_disable(gpio_reg_1p8v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg disable failed\n", __func__);
|
|
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static char mipi_dsi_splash_is_enabled(void);
|
|
static int mipi_dsi_panel_power(int on)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (machine_is_msm7627a_qrd1())
|
|
rc = mipi_dsi_panel_qrd1_power(on);
|
|
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|
|
|| machine_is_msm8625_evt()
|
|
|| machine_is_qrd_skud_prime())
|
|
rc = mipi_dsi_panel_qrd3_power(on);
|
|
else
|
|
rc = mipi_dsi_panel_msm_power(on);
|
|
return rc;
|
|
}
|
|
|
|
#define MDP_303_VSYNC_GPIO 97
|
|
|
|
#ifdef CONFIG_FB_MSM_MIPI_DSI
|
|
static struct mipi_dsi_platform_data mipi_dsi_pdata = {
|
|
.vsync_gpio = MDP_303_VSYNC_GPIO,
|
|
.dsi_power_save = mipi_dsi_panel_power,
|
|
.dsi_client_reset = msm_fb_dsi_client_reset,
|
|
.get_lane_config = msm_fb_get_lane_config,
|
|
.splash_is_enabled = mipi_dsi_splash_is_enabled,
|
|
};
|
|
#endif
|
|
|
|
static char mipi_dsi_splash_is_enabled(void)
|
|
{
|
|
return mdp_pdata.cont_splash_enabled;
|
|
}
|
|
|
|
static char prim_panel_name[PANEL_NAME_MAX_LEN];
|
|
static int __init prim_display_setup(char *param)
|
|
{
|
|
if (strnlen(param, PANEL_NAME_MAX_LEN))
|
|
strlcpy(prim_panel_name, param, PANEL_NAME_MAX_LEN);
|
|
return 0;
|
|
}
|
|
early_param("prim_display", prim_display_setup);
|
|
|
|
static int disable_splash;
|
|
|
|
void msm7x27a_set_display_params(char *prim_panel)
|
|
{
|
|
if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) {
|
|
strlcpy(msm_fb_pdata.prim_panel_name, prim_panel,
|
|
PANEL_NAME_MAX_LEN);
|
|
pr_debug("msm_fb_pdata.prim_panel_name %s\n",
|
|
msm_fb_pdata.prim_panel_name);
|
|
}
|
|
if (strnlen(msm_fb_pdata.prim_panel_name, PANEL_NAME_MAX_LEN)) {
|
|
if (strncmp((char *)msm_fb_pdata.prim_panel_name,
|
|
"mipi_cmd_nt35510_wvga",
|
|
strnlen("mipi_cmd_nt35510_wvga",
|
|
PANEL_NAME_MAX_LEN)) &&
|
|
strncmp((char *)msm_fb_pdata.prim_panel_name,
|
|
"mipi_video_nt35510_wvga",
|
|
strnlen("mipi_video_nt35510_wvga",
|
|
PANEL_NAME_MAX_LEN)))
|
|
disable_splash = 1;
|
|
}
|
|
}
|
|
|
|
void __init msm_fb_add_devices(void)
|
|
{
|
|
int rc = 0;
|
|
msm7x27a_set_display_params(prim_panel_name);
|
|
if (machine_is_msm7627a_qrd1()) {
|
|
platform_add_devices(qrd_fb_devices,
|
|
ARRAY_SIZE(qrd_fb_devices));
|
|
} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|
|
|| machine_is_msm8625_evt()
|
|
|| machine_is_qrd_skud_prime()) {
|
|
mipi_NT35510_pdata.bl_lock = 1;
|
|
mipi_NT35516_pdata.bl_lock = 1;
|
|
if (disable_splash)
|
|
mdp_pdata.cont_splash_enabled = 0x0;
|
|
|
|
platform_add_devices(evb_fb_devices,
|
|
ARRAY_SIZE(evb_fb_devices));
|
|
} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
|
|
if (machine_is_msm7627a_qrd3())
|
|
mdp_pdata.cont_splash_enabled = 0x0;
|
|
else
|
|
mdp_pdata.cont_splash_enabled = 0x1;
|
|
platform_add_devices(qrd3_fb_devices,
|
|
ARRAY_SIZE(qrd3_fb_devices));
|
|
} else {
|
|
mdp_pdata.cont_splash_enabled = 0x0;
|
|
platform_add_devices(msm_fb_devices,
|
|
ARRAY_SIZE(msm_fb_devices));
|
|
}
|
|
|
|
msm_fb_register_device("mdp", &mdp_pdata);
|
|
if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf() ||
|
|
machine_is_msm8625_surf() || machine_is_msm7627a_qrd3()
|
|
|| machine_is_msm8625_qrd7())
|
|
msm_fb_register_device("lcdc", &lcdc_pdata);
|
|
if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
|
|
sku3_lcdc_power_init();
|
|
#ifdef CONFIG_FB_MSM_MIPI_DSI
|
|
msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
|
|
#endif
|
|
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|
|
|| machine_is_msm8625_evt()
|
|
|| machine_is_qrd_skud_prime()) {
|
|
gpio_reg_2p85v = regulator_get(&mipi_dsi_device.dev,
|
|
"lcd_vdd");
|
|
if (IS_ERR(gpio_reg_2p85v))
|
|
pr_err("%s:ext_2p85v regulator get failed", __func__);
|
|
|
|
gpio_reg_1p8v = regulator_get(&mipi_dsi_device.dev,
|
|
"lcd_vddi");
|
|
if (IS_ERR(gpio_reg_1p8v))
|
|
pr_err("%s:ext_1p8v regulator get failed", __func__);
|
|
|
|
if (mdp_pdata.cont_splash_enabled) {
|
|
/*Enable EXT_2.85 and 1.8 regulators*/
|
|
rc = regulator_enable(gpio_reg_2p85v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
rc = regulator_enable(gpio_reg_1p8v);
|
|
if (rc < 0)
|
|
pr_err("%s: reg enable failed\n", __func__);
|
|
}
|
|
}
|
|
}
|