TX2 enable a DSI LCD

Hi all,
i want to enable a dsi lcd, From the L4T document, i see that L4T support panel-s-wuxga-8-0 defaultly. I modify some codes as following.

  1. Add some code to enable panel-s-wuxga-8-0 in file tegra186-quill-p3310-1000-c03-00-base.dts.

host1x {
nvdisplay@15200000 {
status = “okay”;
nvidia,dc-or-node = “/host1x/dsi”;
};
dsi {
status = “okay”;

panel-s-wuxga-8-0 {
status = “okay”;
};
};
};

  1. I do some modification in file panel-s-wuxga-8-0.dtsi about the lanes number and display-timings.

                             nvidia,dsi-instance = <DSI_INSTANCE_0>;
     		nvidia,dsi-n-data-lanes = <4>;
     		nvidia,dsi-pixel-format = <TEGRA_DSI_PIXEL_FORMAT_24BIT_P>;
     		nvidia,dsi-refresh-rate = <60>;
     		nvidia,dsi-video-data-type = <TEGRA_DSI_VIDEO_TYPE_VIDEO_MODE>;
     		nvidia,dsi-video-clock-mode = <TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS>;
     		nvidia,dsi-video-burst-mode = <TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END>;
     		nvidia,dsi-virtual-channel = <TEGRA_DSI_VIRTUAL_CHANNEL_0>;
     		nvidia,dsi-panel-reset = <TEGRA_DSI_ENABLE>;
     		nvidia,dsi-power-saving-suspend = <TEGRA_DSI_ENABLE>;
     		nvidia,dsi-ulpm-not-support = <TEGRA_DSI_ENABLE>;
     		nvidia,dsi-init-cmd = <TEGRA_DSI_DELAY_MS 160>,
     			<0x0 DSI_DCS_WRITE_0_PARAM DSI_DCS_EXIT_SLEEP_MODE 0x0 0x0>,
     			<TEGRA_DSI_SEND_FRAME 5>,
     			<TEGRA_DSI_DELAY_MS 200>,
     			<0x0 DSI_DCS_WRITE_0_PARAM DSI_DCS_SET_DISPLAY_ON 0x0 0x0>,
     			<TEGRA_DSI_DELAY_MS 200>;
     		nvidia,dsi-n-init-cmd = <6>;
     		nvidia,dsi-suspend-cmd = <0x0 DSI_DCS_WRITE_0_PARAM DSI_DCS_SET_DISPLAY_OFF 0x0 0x0>,
     					<0x0 DSI_DCS_WRITE_0_PARAM DSI_DCS_ENTER_SLEEP_MODE 0x0 0x0>,
     					<TEGRA_DSI_DELAY_MS 60>;
     		nvidia,dsi-n-suspend-cmd = <3>;
     		disp-default-out {
     			nvidia,out-type = <TEGRA_DC_OUT_DSI>;
     			nvidia,out-width = <62>;
     			nvidia,out-height = <110>;
     			nvidia,out-flags = <TEGRA_DC_OUT_CONTINUOUS_MODE TEGRA_DC_OUT_INITIALIZED_MODE>;
     			nvidia,out-xres = <720>;
     			nvidia,out-yres = <1280>;
     		};
     		display-timings {
     			720x1280-32 {
     				clock-frequency = <60192000>;
     				hactive = <720>;
     				vactive = <1280>;
     				hfront-porch = <10>;
     				hback-porch = <20>;
     				hsync-len = <10>;
     				vfront-porch = <10>;
     				vback-porch = <15>;
     				vsync-len = <15>;
     				nvidia,h-ref-to-sync = <2>;
     				nvidia,v-ref-to-sync = <1>;
     			};
     		};
    
  2. Then I modify the panel-s-wuxga-8-0.c and comment the codes in funciton “dsi_s_wuxga_8_0_regulator_get” as following,
    because if not, driver cant’t find the regulator “outp” and “outn”.i don’t know why driver can’t find the “outp” and “outn”.

I can capture some signal at clock pin and data lane pins with high bandwidth oscilloscope. The lcd show nothing, but the backlight can be turned on and off.

Could you share your driver code?

As I know, outp and outn is from tps65132 and dts is set to disabled by default.

panel-s-wuxga-8-0.c listed as following

#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>

#include “…/dc.h”
#include “board.h”
#include “board-panel.h”

#define DSI_PANEL_RESET 1

static bool reg_requested;
static struct regulator *avdd_lcd_3v0;
static struct regulator *dvdd_lcd_1v8;
static struct regulator *vpp_lcd;
static struct regulator *vmm_lcd;
static struct device *dc_dev;
static u16 en_panel_rst;
static u16 en_backlight;
static u16 en_panel;
static bool vmm_vpp_fixed_regulators;

static int dsi_s_wuxga_8_0_regulator_get(struct device *dev)
{
int err = 0;

if (reg_requested)
	return 0;

avdd_lcd_3v0 = regulator_get(dev, "avdd_lcd");
if (IS_ERR_OR_NULL(avdd_lcd_3v0)) {
	pr_err("avdd_lcd regulator get failed\n");
	err = PTR_ERR(avdd_lcd_3v0);
	avdd_lcd_3v0 = NULL;
	goto fail;
}

dvdd_lcd_1v8 = regulator_get(dev, "dvdd_lcd");
if (IS_ERR_OR_NULL(dvdd_lcd_1v8)) {
	pr_err("dvdd_lcd_1v8 regulator get failed\n");
	err = PTR_ERR(dvdd_lcd_1v8);
	dvdd_lcd_1v8 = NULL;
	goto dvdd_lcd_fail;
}

/****
vpp_lcd = regulator_get(dev, “outp”);
if (IS_ERR_OR_NULL(vpp_lcd)) {
pr_err(“vpp_lcd regulator get failed\n”);
err = PTR_ERR(vpp_lcd);
vpp_lcd = NULL;
goto vpp_lcd_fail;
}

vmm_lcd = regulator_get(dev, "outn");
if (IS_ERR_OR_NULL(vmm_lcd)) {
	pr_err("vmm_lcd regulator get failed\n");
	err = PTR_ERR(vmm_lcd);
	vmm_lcd = NULL;
	goto vmm_lcd_fail;
}

reg_requested = true;
return 0;

vmm_lcd_fail:
if (vpp_lcd) {
regulator_put(vpp_lcd);
vpp_lcd = NULL;
}
vpp_lcd_fail:
if (dvdd_lcd_1v8) {
regulator_put(dvdd_lcd_1v8);
dvdd_lcd_1v8 = NULL;
}
*****/

dvdd_lcd_fail:
if (avdd_lcd_3v0) {
regulator_put(avdd_lcd_3v0);
avdd_lcd_3v0 = NULL;
}
fail:
return err;
}

static int dsi_s_wuxga_8_0_enable(struct device *dev)
{
int err = 0;

err = tegra_panel_check_regulator_dt_support("s,wuxga-8-0",
	&panel_of);
if (err < 0) {
	pr_err("display regulator dt check failed\n");
	goto fail;
} else {
	vmm_vpp_fixed_regulators = panel_of.en_vmm_vpp_i2c_config;
}

err = dsi_s_wuxga_8_0_regulator_get(dev);
if (err < 0) {
	pr_err("dsi regulator get failed\n");
	goto fail;
}

err = tegra_panel_gpio_get_dt("s,wuxga-8-0", &panel_of);
if (err < 0) {
	pr_err("display gpio get failed\n");
	goto fail;
}

if (gpio_is_valid(panel_of.panel_gpio[TEGRA_GPIO_RESET]))
	en_panel_rst = panel_of.panel_gpio[TEGRA_GPIO_RESET];
else {
	pr_err("display reset gpio invalid\n");
	goto fail;
}

if (gpio_is_valid(panel_of.panel_gpio[TEGRA_GPIO_BL_ENABLE]))
	en_backlight = panel_of.panel_gpio[TEGRA_GPIO_BL_ENABLE];
else
	pr_err("display backlight enable gpio invalid\n");

if (gpio_is_valid(panel_of.panel_gpio[TEGRA_GPIO_PANEL_EN]))
	en_panel = panel_of.panel_gpio[TEGRA_GPIO_PANEL_EN];
else
	pr_err("display panel enable gpio invalid\n");

if (dvdd_lcd_1v8) {
	err = regulator_enable(dvdd_lcd_1v8);
	if (err < 0) {
		pr_err("dvdd_lcd regulator enable failed\n");
		goto fail;
	}
}

usleep_range(1000, 1500);

if (avdd_lcd_3v0) {
	err = regulator_enable(avdd_lcd_3v0);
	if (err < 0) {
		pr_err("avdd_lcd regulator enable failed\n");
		goto fail;
	}
}

usleep_range(3000, 3500);

if (gpio_is_valid(en_backlight))
	gpio_direction_output(en_backlight, 1);

if (en_panel)
	gpio_direction_output(en_panel, 1);

if (vpp_lcd) {
	err = regulator_enable(vpp_lcd);
	if (err < 0) {
		pr_err("vpp_lcd regulator enable failed\n");
		goto fail;
	}

	if (!vmm_vpp_fixed_regulators) {
		err = regulator_set_voltage(vpp_lcd, 5500000, 5500000);
		if (err < 0) {
			pr_err("vpp_lcd regulator failed changing voltage\n");
			goto fail;
		}
	}
}

usleep_range(2000, 2500);

if (vmm_lcd) {
	err = regulator_enable(vmm_lcd);
	if (err < 0) {
		pr_err("vmm_lcd regulator enable failed\n");
		goto fail;
	}

	if (!vmm_vpp_fixed_regulators) {
		err = regulator_set_voltage(vmm_lcd, 5500000, 5500000);
		if (err < 0) {
			pr_err("vmm_lcd regulator failed changing voltage\n");
			goto fail;
		}
	}
}

usleep_range(15000, 15500);

#if DSI_PANEL_RESET
if (!tegra_dc_initialized(dev)) {
err = gpio_direction_output(en_panel_rst, 1);
if (err < 0) {
pr_err(“setting display reset gpio value failed\n”);
goto fail;
}
err = gpio_direction_output(en_panel_rst, 0);
if (err < 0) {
pr_err(“setting display reset gpio value 0 failed\n”);
goto fail;
}
err = gpio_direction_output(en_panel_rst, 1);
if (err < 0) {
pr_err(“setting display reset gpio value 1 failed\n”);
goto fail;
}
}
#endif
dc_dev = dev;
return 0;
fail:
return err;
}

static int dsi_s_wuxga_8_0_disable(struct device dev)
{
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
pr_err(“ERROR! display reset gpio invalid\n”);

if (vmm_lcd)
	regulator_disable(vmm_lcd);

usleep_range(2000, 2500);

if (vpp_lcd)
	regulator_disable(vpp_lcd);

msleep(125);

if (gpio_is_valid(en_panel))
	gpio_direction_output(en_panel, 0);

if (gpio_is_valid(en_backlight))
            gpio_direction_output(en_backlight, 0);


if (avdd_lcd_3v0)
	regulator_disable(avdd_lcd_3v0);

msleep(780);

if (dvdd_lcd_1v8)
	regulator_disable(dvdd_lcd_1v8);

/* Min delay of 140ms required to avoid turning
 * the panel on too soon after power off */
msleep(140);

dc_dev = NULL;

return 0;

}

static int dsi_s_wuxga_8_0_postsuspend(void)
{
return 0;
}

static int dsi_s_wuxga_8_0_bl_notify(struct device *dev, int brightness)
{
int cur_sd_brightness;
struct backlight_device *bl = NULL;
struct pwm_bl_data *pb = NULL;
bl = (struct backlight_device *)dev_get_drvdata(dev);
pb = (struct pwm_bl_data *)dev_get_drvdata(&bl->dev);

#ifdef CONFIG_TEGRA_NVDISPLAY
tegra_sd_check_prism_thresh(dc_dev, brightness);
#else
nvsd_check_prism_thresh(dc_dev, brightness);
#endif

cur_sd_brightness = atomic_read(&sd_brightness);
/* SD brightness is a percentage */
brightness = (brightness * cur_sd_brightness) / 255;

/* Apply any backlight response curve */
if (brightness > 255)
	pr_info("Error: Brightness > 255!\n");
else if (pb->bl_measured)
	brightness = pb->bl_measured[brightness];

return brightness;

}

static int dsi_s_wuxga_8_0_check_fb(struct device *dev,
struct fb_info *info)
{
struct platform_device *pdev = NULL;
pdev = to_platform_device(bus_find_device_by_name(
&platform_bus_type, NULL, “tegradc.0”));
return info->device == &pdev->dev;
}

static struct pwm_bl_data_dt_ops dsi_s_wuxga_8_0_pwm_bl_ops = {
.notify = dsi_s_wuxga_8_0_bl_notify,
.check_fb = dsi_s_wuxga_8_0_check_fb,
.blnode_compatible = “s,wuxga-8-0-bl”,
};
struct tegra_panel_ops dsi_s_wuxga_8_0_ops = {
.enable = dsi_s_wuxga_8_0_enable,
.disable = dsi_s_wuxga_8_0_disable,
.postsuspend = dsi_s_wuxga_8_0_postsuspend,
.pwm_bl_ops = &dsi_s_wuxga_8_0_pwm_bl_ops,
};

I modify the file “tegra186-quill-common.dtsi”, comment the “nvidia,panel-en-gpio” ,because i never use this pin, i only use the “panel-rst-gpio” and “panel-bl-en-gpio”.

                   dsi {	/* dsi@15300000 */
		nvidia,dsi-controller-vs = <DSI_VS_1>;
		status = "disabled";
		panel-s-wuxga-8-0 {
			status = "disabled";
			nvidia,panel-rst-gpio = <&tegra_main_gpio TEGRA_MAIN_GPIO(P, 3) 1>; /* PP3 */
			nvidia,panel-bl-pwm-gpio = <&tegra_aon_gpio TEGRA_AON_GPIO(U, 0) 1>; /* PU0 */
			nvidia,panel-bl-en-gpio = <&tegra_aon_gpio TEGRA_AON_GPIO(U, 3) 1>; /* PU3 */
		/*	nvidia,panel-en-gpio = <&gpio_i2c_0_77 4 1>;  tca9539 0x77 Pin 4 */

			nvidia,en-vmm-vpp-with-i2c-config;
			nvidia,default_color_space = <0>;
			disp-default-out {
				nvidia,out-parent-clk = "pll_d";
				nvidia,out-xres = <720>;
				nvidia,out-yres = <1280>;
                            };

I cannot tell which part is wrong. There is no enough information for me.

What I need to know is

  1. Whether outP and outN are needed for you? These two regulators are not enabled by default.
  2. If you already saw the error from Q1, I think it means display probing has started to checked DSI. Thus, please check if the power sequence is correct.

I don’t need outP and outN. If i don’t comment the codes about outP and outN in file “panel-s-wuxga-8-0.c”, this lcd panel can’t work, the backlight also can’t be turned on and off. I don’t make any other modification about the panel,except mentioned above.

Is there any error log? Do you follow the spec of your own panel?

NO error. The default config file is tegra18_defconfig,right?
I notice that kernel contain another config file “tegra_t186ref_gnu_linux_defconfig”, what is difference?

I don’t think you need to touch the defconfig for enabling DSI LCD. May I ask why do you need that?