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

Commit 96ebb1f3 authored by Liviu Dudau's avatar Liviu Dudau
Browse files

drm: hdlcd: Cleanup the atomic plane operations



Harden the plane_check() code to drop attempts at scaling because
that is not supported. Make hdlcd_plane_atomic_update() set the pitch
and line length registers that correctly reflect the plane's values.
And make hdlcd_crtc_mode_set_nofb() a helper function for
hdlcd_crtc_enable() rather than an exposed hook.

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarLiviu Dudau <Liviu.Dudau@arm.com>
parent 38c8c22c
Loading
Loading
Loading
Loading
+29 −16
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
	struct drm_display_mode *m = &crtc->state->adjusted_mode;
	struct videomode vm;
	unsigned int polarities, line_length, err;
	unsigned int polarities, err;

	vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
	vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -122,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
	if (m->flags & DRM_MODE_FLAG_PVSYNC)
		polarities |= HDLCD_POLARITY_VSYNC;

	line_length = crtc->primary->state->fb->pitches[0];

	/* Allow max number of outstanding requests and largest burst size */
	hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
		    HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);

	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
	hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
	hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
	hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
	hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
	hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
	hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
	hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
	hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
	hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
	hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);

	err = hdlcd_set_pxl_fmt(crtc);
@@ -153,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

	clk_prepare_enable(hdlcd->clk);
	hdlcd_crtc_mode_set_nofb(crtc);
	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
	drm_crtc_vblank_on(crtc);
}

static void hdlcd_crtc_disable(struct drm_crtc *crtc)
{
	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

	if (!crtc->primary->fb)
	if (!crtc->state->active)
		return;

	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
	clk_disable_unprepare(hdlcd->clk);
	drm_crtc_vblank_off(crtc);
}

static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -188,7 +182,6 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
				    struct drm_crtc_state *state)
{
	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
	struct drm_pending_vblank_event *event = crtc->state->event;

	if (event) {
@@ -232,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
static int hdlcd_plane_atomic_check(struct drm_plane *plane,
				    struct drm_plane_state *state)
{
	u32 src_w, src_h;

	src_w = state->src_w >> 16;
	src_h = state->src_h >> 16;

	/* we can't do any scaling of the plane source */
	if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
		return -EINVAL;

	return 0;
}

@@ -240,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
{
	struct hdlcd_drm_private *hdlcd;
	struct drm_gem_cma_object *gem;
	unsigned int depth, bpp;
	u32 src_w, src_h, dest_w, dest_h;
	dma_addr_t scanout_start;

	if (!plane->state->crtc || !plane->state->fb)
	if (!plane->state->fb)
		return;

	hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
	drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
	src_w = plane->state->src_w >> 16;
	src_h = plane->state->src_h >> 16;
	dest_w = plane->state->crtc_w;
	dest_h = plane->state->crtc_h;
	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
	scanout_start = gem->paddr;
	scanout_start = gem->paddr + plane->state->fb->offsets[0] +
		plane->state->crtc_y * plane->state->fb->pitches[0] +
		plane->state->crtc_x * bpp / 8;

	hdlcd = plane->dev->dev_private;
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
	hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
}

static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
	.prepare_fb = NULL,
	.cleanup_fb = NULL,
	.atomic_check = hdlcd_plane_atomic_check,
	.atomic_update = hdlcd_plane_atomic_update,
};
+0 −1
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@ struct hdlcd_drm_private {
	void __iomem			*mmio;
	struct clk			*clk;
	struct drm_fbdev_cma		*fbdev;
	struct drm_framebuffer		*fb;
	struct drm_crtc			crtc;
	struct drm_plane		*plane;
	struct drm_atomic_state		*state;