diff options
Diffstat (limited to 'drivers/gpu/drm/arm/hdlcd_crtc.c')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 798a3cc480a2..1a3359c0f6cd 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <drm/drmP.h> | 12 | #include <drm/drmP.h> |
13 | #include <drm/drm_atomic.h> | ||
13 | #include <drm/drm_atomic_helper.h> | 14 | #include <drm/drm_atomic_helper.h> |
14 | #include <drm/drm_crtc.h> | 15 | #include <drm/drm_crtc.h> |
15 | #include <drm/drm_crtc_helper.h> | 16 | #include <drm/drm_crtc_helper.h> |
@@ -226,16 +227,33 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { | |||
226 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, | 227 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, |
227 | struct drm_plane_state *state) | 228 | struct drm_plane_state *state) |
228 | { | 229 | { |
229 | u32 src_w, src_h; | 230 | struct drm_rect clip = { 0 }; |
231 | struct drm_crtc_state *crtc_state; | ||
232 | u32 src_h = state->src_h >> 16; | ||
230 | 233 | ||
231 | src_w = state->src_w >> 16; | 234 | /* only the HDLCD_REG_FB_LINE_COUNT register has a limit */ |
232 | src_h = state->src_h >> 16; | 235 | if (src_h >= HDLCD_MAX_YRES) { |
236 | DRM_DEBUG_KMS("Invalid source width: %d\n", src_h); | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | if (!state->fb || !state->crtc) | ||
241 | return 0; | ||
233 | 242 | ||
234 | /* we can't do any scaling of the plane source */ | 243 | crtc_state = drm_atomic_get_existing_crtc_state(state->state, |
235 | if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) | 244 | state->crtc); |
245 | if (!crtc_state) { | ||
246 | DRM_DEBUG_KMS("Invalid crtc state\n"); | ||
236 | return -EINVAL; | 247 | return -EINVAL; |
248 | } | ||
237 | 249 | ||
238 | return 0; | 250 | clip.x2 = crtc_state->adjusted_mode.hdisplay; |
251 | clip.y2 = crtc_state->adjusted_mode.vdisplay; | ||
252 | |||
253 | return drm_plane_helper_check_state(state, &clip, | ||
254 | DRM_PLANE_HELPER_NO_SCALING, | ||
255 | DRM_PLANE_HELPER_NO_SCALING, | ||
256 | false, true); | ||
239 | } | 257 | } |
240 | 258 | ||
241 | static void hdlcd_plane_atomic_update(struct drm_plane *plane, | 259 | static void hdlcd_plane_atomic_update(struct drm_plane *plane, |
@@ -244,21 +262,20 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, | |||
244 | struct drm_framebuffer *fb = plane->state->fb; | 262 | struct drm_framebuffer *fb = plane->state->fb; |
245 | struct hdlcd_drm_private *hdlcd; | 263 | struct hdlcd_drm_private *hdlcd; |
246 | struct drm_gem_cma_object *gem; | 264 | struct drm_gem_cma_object *gem; |
247 | u32 src_w, src_h, dest_w, dest_h; | 265 | u32 src_x, src_y, dest_h; |
248 | dma_addr_t scanout_start; | 266 | dma_addr_t scanout_start; |
249 | 267 | ||
250 | if (!fb) | 268 | if (!fb) |
251 | return; | 269 | return; |
252 | 270 | ||
253 | src_w = plane->state->src_w >> 16; | 271 | src_x = plane->state->src.x1 >> 16; |
254 | src_h = plane->state->src_h >> 16; | 272 | src_y = plane->state->src.y1 >> 16; |
255 | dest_w = plane->state->crtc_w; | 273 | dest_h = drm_rect_height(&plane->state->dst); |
256 | dest_h = plane->state->crtc_h; | ||
257 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 274 | gem = drm_fb_cma_get_gem_obj(fb, 0); |
275 | |||
258 | scanout_start = gem->paddr + fb->offsets[0] + | 276 | scanout_start = gem->paddr + fb->offsets[0] + |
259 | plane->state->crtc_y * fb->pitches[0] + | 277 | src_y * fb->pitches[0] + |
260 | plane->state->crtc_x * | 278 | src_x * fb->format->cpp[0]; |
261 | fb->format->cpp[0]; | ||
262 | 279 | ||
263 | hdlcd = plane->dev->dev_private; | 280 | hdlcd = plane->dev->dev_private; |
264 | hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); | 281 | hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); |
@@ -305,7 +322,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm) | |||
305 | formats, ARRAY_SIZE(formats), | 322 | formats, ARRAY_SIZE(formats), |
306 | DRM_PLANE_TYPE_PRIMARY, NULL); | 323 | DRM_PLANE_TYPE_PRIMARY, NULL); |
307 | if (ret) { | 324 | if (ret) { |
308 | devm_kfree(drm->dev, plane); | ||
309 | return ERR_PTR(ret); | 325 | return ERR_PTR(ret); |
310 | } | 326 | } |
311 | 327 | ||
@@ -329,7 +345,6 @@ int hdlcd_setup_crtc(struct drm_device *drm) | |||
329 | &hdlcd_crtc_funcs, NULL); | 345 | &hdlcd_crtc_funcs, NULL); |
330 | if (ret) { | 346 | if (ret) { |
331 | hdlcd_plane_destroy(primary); | 347 | hdlcd_plane_destroy(primary); |
332 | devm_kfree(drm->dev, primary); | ||
333 | return ret; | 348 | return ret; |
334 | } | 349 | } |
335 | 350 | ||