diff options
Diffstat (limited to 'drivers/gpu/drm/arm/hdlcd_crtc.c')
| -rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 86 | 
1 files changed, 48 insertions, 38 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index fef1b04c2aab..0813c2f06931 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -33,8 +33,17 @@   *   */ +static void hdlcd_crtc_cleanup(struct drm_crtc *crtc) +{ +	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); + +	/* stop the controller on cleanup */ +	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); +	drm_crtc_cleanup(crtc); +} +  static const struct drm_crtc_funcs hdlcd_crtc_funcs = { -	.destroy = drm_crtc_cleanup, +	.destroy = hdlcd_crtc_cleanup,  	.set_config = drm_atomic_helper_set_config,  	.page_flip = drm_atomic_helper_page_flip,  	.reset = drm_atomic_helper_crtc_reset, @@ -97,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; @@ -113,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); @@ -144,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; -	clk_disable_unprepare(hdlcd->clk);  	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); -	drm_crtc_vblank_off(crtc); +	clk_disable_unprepare(hdlcd->clk);  }  static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, @@ -179,20 +182,17 @@ 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); -	unsigned long flags; - -	if (crtc->state->event) { -		struct drm_pending_vblank_event *event = crtc->state->event; +	struct drm_pending_vblank_event *event = crtc->state->event; +	if (event) {  		crtc->state->event = NULL; -		event->pipe = drm_crtc_index(crtc); -		WARN_ON(drm_crtc_vblank_get(crtc) != 0); - -		spin_lock_irqsave(&crtc->dev->event_lock, flags); -		list_add_tail(&event->base.link, &hdlcd->event_list); -		spin_unlock_irqrestore(&crtc->dev->event_lock, flags); +		spin_lock_irq(&crtc->dev->event_lock); +		if (drm_crtc_vblank_get(crtc) == 0) +			drm_crtc_arm_vblank_event(crtc, event); +		else +			drm_crtc_send_vblank_event(crtc, event); +		spin_unlock_irq(&crtc->dev->event_lock);  	}  } @@ -225,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;  } @@ -233,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,  }; @@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)  	return plane;  } -void hdlcd_crtc_suspend(struct drm_crtc *crtc) -{ -	hdlcd_crtc_disable(crtc); -} - -void hdlcd_crtc_resume(struct drm_crtc *crtc) -{ -	hdlcd_crtc_enable(crtc); -} -  int hdlcd_setup_crtc(struct drm_device *drm)  {  	struct hdlcd_drm_private *hdlcd = drm->dev_private;  | 
