[RFC] imx-drm: enable full hd dual lvds display (side-by-side)
Peter Seiderer
ps.report at gmx.net
Thu Feb 20 13:27:18 PST 2014
Enable support for a full hd (1920x1080) lcd display ([1]/[2]),
driven by two lvds channels (channel 0 pixels on the left side,
channel 1 pixels on the right side).
First configure two lvds channels with half display width:
lvds-channel at 0 {
fsl,data-mapping = "spwg";
fsl,data-width = <24>;
status = "okay";
display-timings {
native-mode = <&timing0>;
timing0: nlt-nl192108ac10-01d {
clock-frequency = <74590000>;
hactive = <960>;
vactive = <1080>;
};
};
};
lvds-channel at 1 {
fsl,data-mapping = "spwg";
fsl,data-width = <24>;
status = "okay";
display-timings {
native-mode = <&timing1>;
timing1: nlt-nl192108ac10-01d {
clock-frequency = <74590000>;
hactive = <960>;
vactive = <1080>;
};
};
};
Second force the frame buffer to the doubled default size as
calculated from the lvds-channel entries, see changes
in drivers/gpu/drm/drm_fb_helper.c.
Third let the lvds-channel at 1 memory start with half pitch offset,
see changes in drivers/staging/imx-drm/ipuv3-plane.c.
And last synchronize the two lvds channels (without the second half
of the display has an vertical offset by some pixels), see
changes in drivers/staging/imx-drm/ipu-v3/ipu-common.c
Tested with TQMa6Q module/starter kit STKa6x ([3]/[4]).
This is similar to the already existing imx-drm/ldb.txt option
'fsl,dual-channel' which is for displays with dual lvds where the
odd pixels are on channel 0 and the even pixels are on channel 1.
This (first implementation) is for requesting comments. Any
hints/suggestion on howto implement this feature the right
way (configurable, etc.)?
[1] http://www1.futureelectronics.com/doc/NEC%20DISPLAYS/NL192108AC10-01D.pdf
[2] http://www.nlt-technologies.co.jp/en/products/nl192108ac10-01d.html
[3] http://www.tq-group.com/en/products/product-details/prod/embedded-modul-tqma6x/extb/Main/productdetail
[4] http://www.tq-group.com/en/products/product-details/prod/starterkit-stka6x/extb/Main/productdetail
Signed-off-by: Peter Seiderer <ps.report at gmx.net>
---
drivers/gpu/drm/drm_fb_helper.c | 10 ++++++----
drivers/staging/imx-drm/ipu-v3/ipu-common.c | 6 ++++++
drivers/staging/imx-drm/ipuv3-plane.c | 7 +++++++
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d99df15..50d980d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -939,12 +939,14 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (desired_mode) {
if (gamma_size == 0)
gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
- if (desired_mode->hdisplay < sizes.fb_width)
- sizes.fb_width = desired_mode->hdisplay;
+ /* double the frame buffer horizontal size */
+ if (2 * desired_mode->hdisplay < sizes.fb_width)
+ sizes.fb_width = 2 * desired_mode->hdisplay;
if (desired_mode->vdisplay < sizes.fb_height)
sizes.fb_height = desired_mode->vdisplay;
- if (desired_mode->hdisplay > sizes.surface_width)
- sizes.surface_width = desired_mode->hdisplay;
+ /* double the frame buffer horizontal size */
+ if (2 * desired_mode->hdisplay > sizes.surface_width)
+ sizes.surface_width = 2 * desired_mode->hdisplay;
if (desired_mode->vdisplay > sizes.surface_height)
sizes.surface_height = desired_mode->vdisplay;
crtc_count++;
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index ca85d3d..05eb053 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -613,6 +613,7 @@ int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
{
unsigned long lock_flags;
u32 val;
+ u32 dval;
spin_lock_irqsave(&ipu->lock, lock_flags);
@@ -627,6 +628,11 @@ int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
val = ipu_cm_read(ipu, IPU_CONF);
val |= mask;
+
+ /* first disable DI0/DI1 to achieve a synchronous start of both lvds channels */
+ dval = val & (~(IPU_CONF_DI0_EN | IPU_CONF_DI1_EN));
+ ipu_cm_write(ipu, dval, IPU_CONF);
+
ipu_cm_write(ipu, val, IPU_CONF);
spin_unlock_irqrestore(&ipu->lock, lock_flags);
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
index 34b642a..8a44d5e 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -19,6 +19,7 @@
#include "ipu-v3/imx-ipu-v3.h"
#include "ipuv3-plane.h"
+#include "ipu-v3/ipu-prv.h"
#define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
@@ -80,6 +81,12 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
eba = cma_obj->paddr + fb->offsets[0] +
fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
+
+ /* start the second lvds output channel with half pitch offset */
+ if (ipu_plane->ipu_ch->num == 28) {
+ eba += fb->pitches[0] / 2;
+ }
+
ipu_cpmem_set_buffer(cpmem, 0, eba);
ipu_cpmem_set_buffer(cpmem, 1, eba);
--
1.8.1.4
More information about the dri-devel
mailing list