aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c47
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 20ebfb4fbdfa..c65116348281 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>
@@ -206,16 +207,33 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
206static int hdlcd_plane_atomic_check(struct drm_plane *plane, 207static int hdlcd_plane_atomic_check(struct drm_plane *plane,
207 struct drm_plane_state *state) 208 struct drm_plane_state *state)
208{ 209{
209 u32 src_w, src_h; 210 struct drm_rect clip = { 0 };
211 struct drm_crtc_state *crtc_state;
212 u32 src_h = state->src_h >> 16;
210 213
211 src_w = state->src_w >> 16; 214 /* only the HDLCD_REG_FB_LINE_COUNT register has a limit */
212 src_h = state->src_h >> 16; 215 if (src_h >= HDLCD_MAX_YRES) {
216 DRM_DEBUG_KMS("Invalid source width: %d\n", src_h);
217 return -EINVAL;
218 }
219
220 if (!state->fb || !state->crtc)
221 return 0;
213 222
214 /* we can't do any scaling of the plane source */ 223 crtc_state = drm_atomic_get_existing_crtc_state(state->state,
215 if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) 224 state->crtc);
225 if (!crtc_state) {
226 DRM_DEBUG_KMS("Invalid crtc state\n");
216 return -EINVAL; 227 return -EINVAL;
228 }
217 229
218 return 0; 230 clip.x2 = crtc_state->adjusted_mode.hdisplay;
231 clip.y2 = crtc_state->adjusted_mode.vdisplay;
232
233 return drm_plane_helper_check_state(state, &clip,
234 DRM_PLANE_HELPER_NO_SCALING,
235 DRM_PLANE_HELPER_NO_SCALING,
236 false, true);
219} 237}
220 238
221static void hdlcd_plane_atomic_update(struct drm_plane *plane, 239static void hdlcd_plane_atomic_update(struct drm_plane *plane,
@@ -224,21 +242,20 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
224 struct drm_framebuffer *fb = plane->state->fb; 242 struct drm_framebuffer *fb = plane->state->fb;
225 struct hdlcd_drm_private *hdlcd; 243 struct hdlcd_drm_private *hdlcd;
226 struct drm_gem_cma_object *gem; 244 struct drm_gem_cma_object *gem;
227 u32 src_w, src_h, dest_w, dest_h; 245 u32 src_x, src_y, dest_h;
228 dma_addr_t scanout_start; 246 dma_addr_t scanout_start;
229 247
230 if (!fb) 248 if (!fb)
231 return; 249 return;
232 250
233 src_w = plane->state->src_w >> 16; 251 src_x = plane->state->src.x1 >> 16;
234 src_h = plane->state->src_h >> 16; 252 src_y = plane->state->src.y1 >> 16;
235 dest_w = plane->state->crtc_w; 253 dest_h = drm_rect_height(&plane->state->dst);
236 dest_h = plane->state->crtc_h;
237 gem = drm_fb_cma_get_gem_obj(fb, 0); 254 gem = drm_fb_cma_get_gem_obj(fb, 0);
255
238 scanout_start = gem->paddr + fb->offsets[0] + 256 scanout_start = gem->paddr + fb->offsets[0] +
239 plane->state->crtc_y * fb->pitches[0] + 257 src_y * fb->pitches[0] +
240 plane->state->crtc_x * 258 src_x * fb->format->cpp[0];
241 fb->format->cpp[0];
242 259
243 hdlcd = plane->dev->dev_private; 260 hdlcd = plane->dev->dev_private;
244 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); 261 hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
@@ -285,7 +302,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
285 formats, ARRAY_SIZE(formats), 302 formats, ARRAY_SIZE(formats),
286 DRM_PLANE_TYPE_PRIMARY, NULL); 303 DRM_PLANE_TYPE_PRIMARY, NULL);
287 if (ret) { 304 if (ret) {
288 devm_kfree(drm->dev, plane);
289 return ERR_PTR(ret); 305 return ERR_PTR(ret);
290 } 306 }
291 307
@@ -309,7 +325,6 @@ int hdlcd_setup_crtc(struct drm_device *drm)
309 &hdlcd_crtc_funcs, NULL); 325 &hdlcd_crtc_funcs, NULL);
310 if (ret) { 326 if (ret) {
311 hdlcd_plane_destroy(primary); 327 hdlcd_plane_destroy(primary);
312 devm_kfree(drm->dev, primary);
313 return ret; 328 return ret;
314 } 329 }
315 330