summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2019-11-12 13:04:19 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:58:21 +0800
commit3849ba0a44c88eead4fbb8f57de1d62b81772d9f (patch)
tree69b6f033f4f2f1066a82fc3feca1fc3e9ed0f391
parentf98fa2a052fc30e0fee448e60939600d79f6914b (diff)
gpu: imx: tcon: Add side-by-side support
This patch adds side-by-side support for tcon so that two tcons can participate in the dual display streams to work with pixel combiner to drive a high pixel rate display. Signed-off-by: Liu Ying <victor.liu@nxp.com>
-rw-r--r--drivers/gpu/drm/imx/dpu/dpu-crtc.c2
-rw-r--r--drivers/gpu/imx/dpu/dpu-tcon.c40
-rw-r--r--include/video/dpu.h3
3 files changed, 33 insertions, 12 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.c b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
index 79bcb78063c9..ae0e661e9429 100644
--- a/drivers/gpu/drm/imx/dpu/dpu-crtc.c
+++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
@@ -525,7 +525,7 @@ static void dpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
framegen_panic_displaymode(dpu_crtc->fg, FGDM__TEST);
- tcon_cfg_videomode(dpu_crtc->tcon, mode);
+ tcon_cfg_videomode(dpu_crtc->tcon, mode, false);
tcon_set_fmt(dpu_crtc->tcon, imx_crtc_state->bus_format);
constframe_framedimensions(dpu_crtc->pa_cf,
diff --git a/drivers/gpu/imx/dpu/dpu-tcon.c b/drivers/gpu/imx/dpu/dpu-tcon.c
index 199e6e55df15..aa5f45115bc2 100644
--- a/drivers/gpu/imx/dpu/dpu-tcon.c
+++ b/drivers/gpu/imx/dpu/dpu-tcon.c
@@ -118,11 +118,27 @@ void tcon_set_operation_mode(struct dpu_tcon *tcon)
}
EXPORT_SYMBOL_GPL(tcon_set_operation_mode);
-void tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m)
+void tcon_cfg_videomode(struct dpu_tcon *tcon,
+ struct drm_display_mode *m, bool side_by_side)
{
u32 val;
+ int hdisplay, hsync_start, hsync_end;
+ int vdisplay, vsync_start, vsync_end;
int y;
+ hdisplay = m->hdisplay;
+ vdisplay = m->vdisplay;
+ hsync_start = m->hsync_start;
+ vsync_start = m->vsync_start;
+ hsync_end = m->hsync_end;
+ vsync_end = m->vsync_end;
+
+ if (side_by_side) {
+ hdisplay /= 2;
+ hsync_start /= 2;
+ hsync_end /= 2;
+ }
+
/*
* TKT320590:
* Turn TCON into operation mode later after the first dumb frame is
@@ -133,22 +149,20 @@ void tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m)
dpu_tcon_write(tcon, TCON_CTRL, val);
/* dsp_control[0]: hsync */
- dpu_tcon_write(tcon, SPGPOSON(0), X(m->hsync_start));
+ dpu_tcon_write(tcon, SPGPOSON(0), X(hsync_start));
dpu_tcon_write(tcon, SPGMASKON(0), 0xffff);
- dpu_tcon_write(tcon, SPGPOSOFF(0), X(m->hsync_end));
+ dpu_tcon_write(tcon, SPGPOSOFF(0), X(hsync_end));
dpu_tcon_write(tcon, SPGMASKOFF(0), 0xffff);
dpu_tcon_write(tcon, SMXSIGS(0), 0x2);
dpu_tcon_write(tcon, SMXFCTTABLE(0), 0x1);
/* dsp_control[1]: vsync */
- dpu_tcon_write(tcon, SPGPOSON(1),
- X(m->hsync_start) | Y(m->vsync_start - 1));
+ dpu_tcon_write(tcon, SPGPOSON(1), X(hsync_start) | Y(vsync_start - 1));
dpu_tcon_write(tcon, SPGMASKON(1), 0x0);
- dpu_tcon_write(tcon, SPGPOSOFF(1),
- X(m->hsync_start) | Y(m->vsync_end - 1));
+ dpu_tcon_write(tcon, SPGPOSOFF(1), X(hsync_start) | Y(vsync_end - 1));
dpu_tcon_write(tcon, SPGMASKOFF(1), 0x0);
dpu_tcon_write(tcon, SMXSIGS(1), 0x3);
@@ -159,21 +173,27 @@ void tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m)
dpu_tcon_write(tcon, SPGPOSON(2), 0x0);
dpu_tcon_write(tcon, SPGMASKON(2), 0xffff);
- dpu_tcon_write(tcon, SPGPOSOFF(2), X(m->hdisplay));
+ dpu_tcon_write(tcon, SPGPOSOFF(2), X(hdisplay));
dpu_tcon_write(tcon, SPGMASKOFF(2), 0xffff);
/* vertical */
dpu_tcon_write(tcon, SPGPOSON(3), 0x0);
dpu_tcon_write(tcon, SPGMASKON(3), 0x7fff0000);
- dpu_tcon_write(tcon, SPGPOSOFF(3), Y(m->vdisplay));
+ dpu_tcon_write(tcon, SPGPOSOFF(3), Y(vdisplay));
dpu_tcon_write(tcon, SPGMASKOFF(3), 0x7fff0000);
dpu_tcon_write(tcon, SMXSIGS(2), 0x2c);
dpu_tcon_write(tcon, SMXFCTTABLE(2), 0x8);
/* dsp_control[3]: kachuck */
- y = m->vdisplay + 1;
+ y = vdisplay + 1;
+ /*
+ * If sync mode fixup is present, the kachuck signal from slave tcon
+ * should be one line later than the one from master tcon.
+ */
+ if (side_by_side && tcon_is_slave(tcon))
+ y++;
dpu_tcon_write(tcon, SPGPOSON(4), X(0x0) | Y(y));
dpu_tcon_write(tcon, SPGMASKON(4), 0x0);
diff --git a/include/video/dpu.h b/include/video/dpu.h
index ef0d70a591e2..ed9b65cacde7 100644
--- a/include/video/dpu.h
+++ b/include/video/dpu.h
@@ -553,7 +553,8 @@ void dpu_lb_put(struct dpu_layerblend *lb);
struct dpu_tcon;
int tcon_set_fmt(struct dpu_tcon *tcon, u32 bus_format);
void tcon_set_operation_mode(struct dpu_tcon *tcon);
-void tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m);
+void tcon_cfg_videomode(struct dpu_tcon *tcon,
+ struct drm_display_mode *m, bool side_by_side);
bool tcon_is_master(struct dpu_tcon *tcon);
bool tcon_is_slave(struct dpu_tcon *tcon);
struct dpu_tcon *dpu_tcon_get(struct dpu_soc *dpu, int id);