diff options
author | Liviu Dudau <Liviu.Dudau@arm.com> | 2016-06-01 10:00:15 -0400 |
---|---|---|
committer | Liviu Dudau <Liviu.Dudau@arm.com> | 2016-06-02 12:45:29 -0400 |
commit | 96ebb1f3ed4dca25c6f5d1868b0de61f9366612a (patch) | |
tree | 6fbf2d66455ae62f4f5afc4d67d060f700493c5e | |
parent | 38c8c22c12e99b70fc59ea7ef4d0bb24c11e5ddd (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.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_drv.h | 1 |
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 | ||
160 | static void hdlcd_crtc_disable(struct drm_crtc *crtc) | 155 | static 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 | ||
172 | static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, | 166 | static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, |
@@ -188,7 +182,6 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, | |||
188 | static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, | 182 | static 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 = { | |||
232 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, | 225 | static 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 | ||
254 | static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = { | 269 | static 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; |