97 lines
3.2 KiB
Diff
97 lines
3.2 KiB
Diff
|
From c50d2b2fc772468306a8b30159924f19edab4901 Mon Sep 17 00:00:00 2001
|
||
|
From: Eric Anholt <eric@anholt.net>
|
||
|
Date: Wed, 10 Feb 2016 16:17:29 -0800
|
||
|
Subject: [PATCH] drm/vc4: Add support for feeding DSI encoders from the pixel
|
||
|
valve.
|
||
|
|
||
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||
|
---
|
||
|
drivers/gpu/drm/vc4/vc4_crtc.c | 30 +++++++++++++++++-------------
|
||
|
drivers/gpu/drm/vc4/vc4_regs.h | 2 ++
|
||
|
2 files changed, 19 insertions(+), 13 deletions(-)
|
||
|
|
||
|
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
|
||
|
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
|
||
|
@@ -210,38 +210,40 @@ static u32 vc4_get_fifo_full_level(u32 f
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Returns the clock select bit for the connector attached to the
|
||
|
- * CRTC.
|
||
|
+ * Returns the encoder attached to the CRTC.
|
||
|
+ *
|
||
|
+ * VC4 can only scan out to one encoder at a type, while the DRM core
|
||
|
+ * allows drivers to push pixels to more than one encoder from the
|
||
|
+ * same CRTC.
|
||
|
*/
|
||
|
-static int vc4_get_clock_select(struct drm_crtc *crtc)
|
||
|
+static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc)
|
||
|
{
|
||
|
struct drm_connector *connector;
|
||
|
|
||
|
drm_for_each_connector(connector, crtc->dev) {
|
||
|
if (connector->state->crtc == crtc) {
|
||
|
- struct drm_encoder *encoder = connector->encoder;
|
||
|
- struct vc4_encoder *vc4_encoder =
|
||
|
- to_vc4_encoder(encoder);
|
||
|
-
|
||
|
- return vc4_encoder->clock_select;
|
||
|
+ return connector->encoder;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- return -1;
|
||
|
+ return NULL;
|
||
|
}
|
||
|
|
||
|
static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||
|
{
|
||
|
struct drm_device *dev = crtc->dev;
|
||
|
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||
|
+ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
|
||
|
+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
|
||
|
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
||
|
struct drm_crtc_state *state = crtc->state;
|
||
|
struct drm_display_mode *mode = &state->adjusted_mode;
|
||
|
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
|
||
|
u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
|
||
|
- u32 format = PV_CONTROL_FORMAT_24;
|
||
|
- bool debug_dump_regs = false;
|
||
|
- int clock_select = vc4_get_clock_select(crtc);
|
||
|
+ bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
|
||
|
+ vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
|
||
|
+ u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
|
||
|
+ bool debug_dump_regs = true;
|
||
|
|
||
|
if (debug_dump_regs) {
|
||
|
DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
|
||
|
@@ -289,6 +291,7 @@ static void vc4_crtc_mode_set_nofb(struc
|
||
|
|
||
|
CRTC_WRITE(PV_V_CONTROL,
|
||
|
PV_VCONTROL_CONTINUOUS |
|
||
|
+ (is_dsi ? PV_VCONTROL_DSI : 0) |
|
||
|
(interlace ? PV_VCONTROL_INTERLACE : 0));
|
||
|
|
||
|
CRTC_WRITE(PV_CONTROL,
|
||
|
@@ -298,7 +301,8 @@ static void vc4_crtc_mode_set_nofb(struc
|
||
|
PV_CONTROL_CLR_AT_START |
|
||
|
PV_CONTROL_TRIGGER_UNDERFLOW |
|
||
|
PV_CONTROL_WAIT_HSTART |
|
||
|
- VC4_SET_FIELD(clock_select, PV_CONTROL_CLK_SELECT) |
|
||
|
+ VC4_SET_FIELD(vc4_encoder->clock_select,
|
||
|
+ PV_CONTROL_CLK_SELECT) |
|
||
|
PV_CONTROL_FIFO_CLR |
|
||
|
PV_CONTROL_EN);
|
||
|
|
||
|
--- a/drivers/gpu/drm/vc4/vc4_regs.h
|
||
|
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
|
||
|
@@ -184,6 +184,8 @@
|
||
|
|
||
|
#define PV_V_CONTROL 0x04
|
||
|
# define PV_VCONTROL_INTERLACE BIT(4)
|
||
|
+# define PV_VCONTROL_DSI BIT(3)
|
||
|
+# define PV_VCONTROL_COMMAND BIT(2)
|
||
|
# define PV_VCONTROL_CONTINUOUS BIT(1)
|
||
|
# define PV_VCONTROL_VIDEN BIT(0)
|
||
|
|