tegrakernel/kernel/nvidia/drivers/video/tegra/dc/panel/panel-b-1440-1600-3-5.c

220 lines
5.4 KiB
C

/*
* panel-b-1440-1600-3-5.c: Panel driver for b-1440-1600-3-5 panel.
*
* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include "../dc_priv.h"
#include "board.h"
#include "board-panel.h"
#define PANEL_COMP_STRING "b,1440-1600-3-5"
static struct tegra_panel_instance panel_instance[] = {
{
{.panel_gpio = {-1, -1, -1, -1, -1, -1, -1},},
{NULL, NULL, NULL},
},
{
{.panel_gpio = {-1, -1, -1, -1, -1, -1, -1},},
{NULL, NULL, NULL},
},
};
static int dsi_b_1440_1600_3_5_enable(struct device *dev)
{
struct regulator *avdd_lcd_var;
struct regulator *avee_lcd_var;
struct regulator *vddi_lcd_var;
int err = 0;
int panel_id = 0;
u16 en_panel_rst = 0;
u16 en_backlight = 0;
bool vmm_vpp_fixed_regulators;
err = tegra_panel_get_panel_id(PANEL_COMP_STRING, dev->of_node,
&panel_id);
if (err) {
dev_err(dev, "panel-id not found on dt. Using default\n");
panel_id = 0;
}
err = tegra_panel_check_regulator_dt_support(PANEL_COMP_STRING,
&panel_instance[panel_id].panel_of);
if (err < 0) {
dev_err(dev, "display regulator dt check failed\n");
goto fail;
} else {
vmm_vpp_fixed_regulators = panel_of.en_vmm_vpp_i2c_config;
}
err = tegra_panel_regulator_get_dt(dev,
&panel_instance[panel_id].panel_reg);
if (err < 0) {
dev_err(dev, "dsi regulator get failed\n");
goto fail;
}
avdd_lcd_var = panel_instance[panel_id].panel_reg.avdd_lcd;
avee_lcd_var = panel_instance[panel_id].panel_reg.avee_lcd;
vddi_lcd_var = panel_instance[panel_id].panel_reg.vddi_lcd;
err = tegra_panel_gpio_get_dt("b,1440-1600-3-5",
&panel_instance[panel_id].panel_of);
if (err < 0) {
dev_err(dev, "display gpio get failed\n");
goto fail;
}
if (gpio_is_valid(panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_RESET]))
en_panel_rst = panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_RESET];
else {
dev_err(dev, "display reset gpio invalid\n");
goto fail;
}
if (gpio_is_valid(panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_BL_ENABLE]))
en_backlight = panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_BL_ENABLE];
else
dev_err(dev, "display backlight enable gpio invalid\n");
if (vddi_lcd_var) {
err = regulator_enable(vddi_lcd_var);
if (err < 0) {
dev_err(dev, "dvdd_lcd regulator enable failed\n");
goto fail;
}
}
usleep_range(1000, 1500);
if (avdd_lcd_var) {
err = regulator_enable(avdd_lcd_var);
if (err < 0) {
dev_err(dev, "avdd_lcd_var regulator enable failed\n");
goto fail;
}
if (!vmm_vpp_fixed_regulators) {
err = regulator_set_voltage(avdd_lcd_var,
5600000, 5600000);
if (err < 0) {
dev_err(dev,
"avdd_lcd_var failed changing voltage\n");
goto fail;
}
}
}
usleep_range(2000, 2500);
if (avee_lcd_var) {
err = regulator_enable(avee_lcd_var);
if (err < 0) {
dev_err(dev, "avee_lcd_var regulator enable failed\n");
goto fail;
}
if (!vmm_vpp_fixed_regulators) {
err = regulator_set_voltage(avee_lcd_var,
5600000, 5600000);
if (err < 0) {
dev_err(dev,
"avee_lcd_var failed changing voltage\n");
goto fail;
}
}
}
usleep_range(15000, 15500);
err = gpio_direction_output(en_panel_rst, 1);
if (err < 0) {
dev_err(dev, "setting display reset gpio value 1 failed\n");
goto fail;
}
mdelay(20);
if (gpio_is_valid(en_backlight))
gpio_direction_output(en_backlight, 1);
return 0;
fail:
return err;
}
static int dsi_b_1440_1600_3_5_disable(struct device *dev)
{
int err = 0;
struct regulator *avdd_lcd_var;
struct regulator *avee_lcd_var;
struct regulator *vddi_lcd_var;
int panel_id = 0;
u16 en_panel_rst = 0;
u16 en_backlight = 0;
err = tegra_panel_get_panel_id(PANEL_COMP_STRING, dev->of_node,
&panel_id);
if (err) {
dev_err(dev, "panel-id not found on dt. Using default\n");
panel_id = 0;
}
avdd_lcd_var = panel_instance[panel_id].panel_reg.avdd_lcd;
avee_lcd_var = panel_instance[panel_id].panel_reg.avee_lcd;
vddi_lcd_var = panel_instance[panel_id].panel_reg.vddi_lcd;
en_backlight = panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_BL_ENABLE];
en_panel_rst = panel_instance[panel_id].panel_of.panel_gpio[TEGRA_GPIO_RESET];
if (gpio_is_valid(en_panel_rst)) {
/* Wait for 50ms before triggering panel reset */
msleep(50);
gpio_set_value(en_panel_rst, 0);
usleep_range(500, 1000);
} else
dev_err(dev, "ERROR! display reset gpio invalid\n");
if (avee_lcd_var)
regulator_disable(avee_lcd_var);
usleep_range(2000, 2500);
if (avdd_lcd_var)
regulator_disable(avdd_lcd_var);
msleep(125);
if (vddi_lcd_var)
regulator_disable(vddi_lcd_var);
/* Min delay of 140ms required to avoid turning
* the panel on too soon after power off */
msleep(140);
return 0;
}
struct tegra_panel_ops dsi_b_1440_1600_3_5_ops = {
.enable = dsi_b_1440_1600_3_5_enable,
.disable = dsi_b_1440_1600_3_5_disable,
};