The LCDIF driver fails at boot time because it cannot read display timings
from device tree. This is a fake error because the LCDIF DT node contains a
display device property which leads to the display driver that also provides
the timings.
This fake error case has been introduced by
commit
5443a75ed038 ("MLK-14283: dts: fix DE polarity for lcdif") and
commit
56412d6a83d8 ("MLK-13996: lcdif: Use DE polarity specified in DTS")
which fixed DE polarity panel differences for different boards.
This patch adds support for choosing a particular video mode from the ones
provided by the display driver, thus also fixing the DE polarity issue
initially fixed by the above mentioned 2 patches.
Signed-off-by: Cristina Ciocan <cristina-mihaela.ciocan@nxp.com>
- interrupts: Should contain lcdif interrupts
- display : phandle to display node (see below for details)
+Optional properties:
+- disp-dev: Display device driver name
+- disp-videomode: Display device video mode name; this is used if the panel
+ supports multiple video modes, in order to chose the right one (see below for
+ examples)
+
* display node
Required properties:
};
};
};
+
+Examples - optional properties:
+
+Snippet from imx7d-sdb-mipi-dsi.dts:
+
+&lcdif {
+ disp-dev = "mipi_dsi_samsung";
+ disp-videomode = "TRUULY-WVGA-SYNC-LOW";
+};
+
+&mipi_dsi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mipi_dsi_reset>;
+ lcd_panel = "TRULY-WVGA-TFT3P5581E";
+ resets = <&mipi_dsi_reset>;
+ status = "okay";
+};
+
+In the above example, the panel supports 2 video modes (snippet from
+drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c):
+
+#define ACTIVE_HIGH_NAME "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME "TRUULY-WVGA-SYNC-LOW"
+
+static struct fb_videomode truly_lcd_modedb[] = {
+ {
+ ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ 0x0,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ }, {
+ ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ },
+};
&lcdif {
disp-dev = "mipi_dsi_samsung";
+ disp-videomode = "TRUULY-WVGA-SYNC-LOW";
};
&mipi_dsi {
static int hx8363bl_brightness;
+#define ACTIVE_HIGH_NAME "TRUULY-WVGA-SYNC-HIGH"
+#define ACTIVE_LOW_NAME "TRUULY-WVGA-SYNC-LOW"
+
static struct fb_videomode truly_lcd_modedb[] = {
{
- "TRUULY-WVGA", 50, 480, 854, 41042,
- 40, 60,
- 3, 3,
- 8, 4,
- 0x0,
- FB_VMODE_NONINTERLACED,
- 0,
+ ACTIVE_HIGH_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ 0x0,
+ FB_VMODE_NONINTERLACED,
+ 0,
+ }, {
+ ACTIVE_LOW_NAME, 50, 480, 854, 41042,
+ 40, 60,
+ 3, 3,
+ 8, 4,
+ FB_SYNC_OE_LOW_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,
},
};
struct mxsfb_info *fbi;
};
+#define NAME_LEN 32
+
struct mxsfb_info {
struct fb_info *fb_info;
struct platform_device *pdev;
struct completion flip_complete;
int cur_blank;
int restore_blank;
- char disp_dev[32];
+ char disp_dev[NAME_LEN];
struct mxc_dispdrv_handle *dispdrv;
int id;
struct fb_var_screeninfo var;
struct pm_qos_request pm_qos_req;
+ char disp_videomode[NAME_LEN];
+
#ifdef CONFIG_FB_MXC_OVERLAY
struct mxsfb_layer overlay;
#endif
struct device_node *display_np;
struct device_node *timings_np;
struct display_timings *timings = NULL;
- const char *disp_dev;
+ const char *disp_dev, *disp_videomode;
u32 width;
int i;
int ret = 0;
ret = of_property_read_string(np, "disp-dev", &disp_dev);
if (!ret) {
memcpy(host->disp_dev, disp_dev, strlen(disp_dev));
+
+ if (!of_property_read_string(np, "disp-videomode",
+ &disp_videomode)) {
+ memcpy(host->disp_videomode, disp_videomode,
+ strlen(disp_videomode));
+ }
+
/* Timing is from encoder driver */
goto put_display_node;
}
memcpy(disp_dev, host->disp_dev, strlen(host->disp_dev));
disp_dev[strlen(host->disp_dev)] = '\0';
+ /* Use videomode name from dtb, if any given */
+ if (host->disp_videomode) {
+ setting.dft_mode_str = kmalloc(NAME_LEN, GFP_KERNEL);
+ if (setting.dft_mode_str) {
+ memset(setting.dft_mode_str, 0x0, NAME_LEN);
+ memcpy(setting.dft_mode_str, host->disp_videomode,
+ strlen(host->disp_videomode));
+ }
+ }
+
host->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
+
+ kfree(setting.dft_mode_str);
+
if (IS_ERR(host->dispdrv)) {
if (PTR_ERR(host->dispdrv) == -EPROBE_DEFER)
return PTR_ERR(host->dispdrv);