Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a86773d1 authored by Eric Anholt's avatar Eric Anholt
Browse files

drm/vc4: Add support for feeding DSI encoders from the pixel valve.



We have to set a different pixel format, which tells the hardware to
use the pix_width field that's fed in sideband from the DSI encoder to
divide the "pixel" clock.

Signed-off-by: default avatarEric Anholt <eric@anholt.net>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161214194621.16499-6-eric@anholt.net
parent d17a1bb9
Loading
Loading
Loading
Loading
+19 −14
Original line number Diff line number Diff line
@@ -348,38 +348,40 @@ static u32 vc4_get_fifo_full_level(u32 format)
}

/*
 * 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 time, 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 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
	u32 format = PV_CONTROL_FORMAT_24;
	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 = false;
	int clock_select = vc4_get_clock_select(crtc);

	if (debug_dump_regs) {
		DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
@@ -435,17 +437,19 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
		 */
		CRTC_WRITE(PV_V_CONTROL,
			   PV_VCONTROL_CONTINUOUS |
			   (is_dsi ? PV_VCONTROL_DSI : 0) |
			   PV_VCONTROL_INTERLACE |
			   VC4_SET_FIELD(mode->htotal * pixel_rep / 2,
					 PV_VCONTROL_ODD_DELAY));
		CRTC_WRITE(PV_VSYNCD_EVEN, 0);
	} else {
		CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
		CRTC_WRITE(PV_V_CONTROL,
			   PV_VCONTROL_CONTINUOUS |
			   (is_dsi ? PV_VCONTROL_DSI : 0));
	}

	CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);


	CRTC_WRITE(PV_CONTROL,
		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
		   VC4_SET_FIELD(vc4_get_fifo_full_level(format),
@@ -454,7 +458,8 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
		   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);

+2 −0
Original line number Diff line number Diff line
@@ -190,6 +190,8 @@
# define PV_VCONTROL_ODD_DELAY_SHIFT		6
# define PV_VCONTROL_ODD_FIRST			BIT(5)
# 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)