From c50d2b2fc772468306a8b30159924f19edab4901 Mon Sep 17 00:00:00 2001 From: Eric Anholt 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 --- 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)