aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiviu Dudau <Liviu.Dudau@arm.com>2016-06-01 10:00:15 -0400
committerLiviu Dudau <Liviu.Dudau@arm.com>2016-06-02 12:45:29 -0400
commit96ebb1f3ed4dca25c6f5d1868b0de61f9366612a (patch)
tree6fbf2d66455ae62f4f5afc4d67d060f700493c5e
parent38c8c22c12e99b70fc59ea7ef4d0bb24c11e5ddd (diff)
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: Liviu Dudau <Liviu.Dudau@arm.com>
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c45
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.h1
2 files changed, 29 insertions, 17 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 97326c3d7a3a..0813c2f06931 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -106,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
106 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); 106 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
107 struct drm_display_mode *m = &crtc->state->adjusted_mode; 107 struct drm_display_mode *m = &crtc->state->adjusted_mode;
108 struct videomode vm; 108 struct videomode vm;
109 unsigned int polarities, line_length, err; 109 unsigned int polarities, err;
110 110
111 vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay; 111 vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
112 vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end; 112 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)
122 if (m->flags & DRM_MODE_FLAG_PVSYNC) 122 if (m->flags & DRM_MODE_FLAG_PVSYNC)
123 polarities |= HDLCD_POLARITY_VSYNC; 123 polarities |= HDLCD_POLARITY_VSYNC;
124 124
125 line_length = crtc->primary->state->fb->pitches[0];
126
127 /* Allow max number of outstanding requests and largest burst size */ 125 /* Allow max number of outstanding requests and largest burst size */
128 hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS, 126 hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
129 HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16); 127 HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
130 128
131 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
132 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
133 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
134 hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1); 129 hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
135 hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1); 130 hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
136 hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1); 131 hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
137 hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1); 132 hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
133 hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
138 hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1); 134 hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
139 hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1); 135 hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
140 hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1); 136 hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
141 hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
142 hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities); 137 hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
143 138
144 err = hdlcd_set_pxl_fmt(crtc); 139 err = hdlcd_set_pxl_fmt(crtc);
@@ -153,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
153 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); 148 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
154 149
155 clk_prepare_enable(hdlcd->clk); 150 clk_prepare_enable(hdlcd->clk);
151 hdlcd_crtc_mode_set_nofb(crtc);
156 hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1); 152 hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
157 drm_crtc_vblank_on(crtc);
158} 153}
159 154
160static void hdlcd_crtc_disable(struct drm_crtc *crtc) 155static void hdlcd_crtc_disable(struct drm_crtc *crtc)
161{ 156{
162 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); 157 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
163 158
164 if (!crtc->primary->fb) 159 if (!crtc->state->active)
165 return; 160 return;
166 161
167 hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); 162 hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
168 clk_disable_unprepare(hdlcd->clk); 163 clk_disable_unprepare(hdlcd->clk);
169 drm_crtc_vblank_off(crtc);
170} 164}
171 165
172static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, 166static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -188,7 +182,6 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
188static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, 182static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
189 struct drm_crtc_state *state) 183 struct drm_crtc_state *state)
190{ 184{
191 struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
192 struct drm_pending_vblank_event *event = crtc->state->event; 185 struct drm_pending_vblank_event *event = crtc->state->event;
193 186
194 if (event) { 187 if (event) {
@@ -232,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
232static int hdlcd_plane_atomic_check(struct drm_plane *plane, 225static int hdlcd_plane_atomic_check(struct drm_plane *plane,
233 struct drm_plane_state *state) 226 struct drm_plane_state *state)
234{ 227{
228 u32 src_w, src_h;
229
230 src_w = state->src_w >> 16;
231 src_h = state->src_h >> 16;
232
233 /* we can't do any scaling of the plane source */
234 if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
235 return -EINVAL;
236
235 return 0; 237 return 0;
236} 238}
237 239
@@ -240,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
240{ 242{
241 struct hdlcd_drm_private *hdlcd; 243 struct hdlcd_drm_private *hdlcd;
242 struct drm_gem_cma_object *gem; 244 struct drm_gem_cma_object *gem;
245 unsigned int depth, bpp;
246 u32 src_w, src_h, dest_w, dest_h;
243 dma_addr_t scanout_start; 247 dma_addr_t scanout_start;
244 248
245 if (!plane->state->crtc || !plane->state->fb) 249 if (!plane->state->fb)
246 return; 250 return;
247 251
248 hdlcd = crtc_to_hdlcd_priv(plane->state->crtc); 252 drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
253 src_w = plane->state->src_w >> 16;
254 src_h = plane->state->src_h >> 16;
255 dest_w = plane->state->crtc_w;
256 dest_h = plane->state->crtc_h;
249 gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); 257 gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
250 scanout_start = gem->paddr; 258 scanout_start = gem->paddr + plane->state->fb->offsets[0] +
259 plane->state->crtc_y * plane->state->fb->pitches[0] +
260 plane->state->crtc_x * bpp / 8;
261
262 hdlcd = plane->dev->dev_private;
263 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
264 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
265 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
251 hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start); 266 hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
252} 267}
253 268
254static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = { 269static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
255 .prepare_fb = NULL,
256 .cleanup_fb = NULL,
257 .atomic_check = hdlcd_plane_atomic_check, 270 .atomic_check = hdlcd_plane_atomic_check,
258 .atomic_update = hdlcd_plane_atomic_update, 271 .atomic_update = hdlcd_plane_atomic_update,
259}; 272};
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index 922a1dc7cb88..e3950a071152 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -9,7 +9,6 @@ struct hdlcd_drm_private {
9 void __iomem *mmio; 9 void __iomem *mmio;
10 struct clk *clk; 10 struct clk *clk;
11 struct drm_fbdev_cma *fbdev; 11 struct drm_fbdev_cma *fbdev;
12 struct drm_framebuffer *fb;
13 struct drm_crtc crtc; 12 struct drm_crtc crtc;
14 struct drm_plane *plane; 13 struct drm_plane *plane;
15 struct drm_atomic_state *state; 14 struct drm_atomic_state *state;