Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/imx: ipuv3-crtc: use drm managed resources

Use use drmm_crtc_alloc_with_planes() to align crtc memory lifetime
with the drm device. drm_crtc_cleanup() is called automatically before
the memory is freed.
Also use drmm_add_action_or_reset() to make sure IPU resources are
released automatically.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

+43 -71
+43 -71
drivers/gpu/drm/imx/ipuv3-crtc.c
··· 20 20 #include <drm/drm_atomic_helper.h> 21 21 #include <drm/drm_fb_cma_helper.h> 22 22 #include <drm/drm_gem_cma_helper.h> 23 + #include <drm/drm_managed.h> 23 24 #include <drm/drm_probe_helper.h> 24 25 #include <drm/drm_vblank.h> 25 26 ··· 164 163 165 164 static const struct drm_crtc_funcs ipu_crtc_funcs = { 166 165 .set_config = drm_atomic_helper_set_config, 167 - .destroy = drm_crtc_cleanup, 168 166 .page_flip = drm_atomic_helper_page_flip, 169 167 .reset = imx_drm_crtc_reset, 170 168 .atomic_duplicate_state = imx_drm_crtc_duplicate_state, ··· 322 322 .atomic_enable = ipu_crtc_atomic_enable, 323 323 }; 324 324 325 - static void ipu_put_resources(struct ipu_crtc *ipu_crtc) 325 + static void ipu_put_resources(struct drm_device *dev, void *ptr) 326 326 { 327 + struct ipu_crtc *ipu_crtc = ptr; 328 + 327 329 if (!IS_ERR_OR_NULL(ipu_crtc->dc)) 328 330 ipu_dc_put(ipu_crtc->dc); 329 331 if (!IS_ERR_OR_NULL(ipu_crtc->di)) 330 332 ipu_di_put(ipu_crtc->di); 331 333 } 332 334 333 - static int ipu_get_resources(struct ipu_crtc *ipu_crtc, 334 - struct ipu_client_platformdata *pdata) 335 + static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc, 336 + struct ipu_client_platformdata *pdata) 335 337 { 336 338 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 337 339 int ret; 338 340 339 341 ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); 340 - if (IS_ERR(ipu_crtc->dc)) { 341 - ret = PTR_ERR(ipu_crtc->dc); 342 - goto err_out; 343 - } 342 + if (IS_ERR(ipu_crtc->dc)) 343 + return PTR_ERR(ipu_crtc->dc); 344 + 345 + ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc); 346 + if (ret) 347 + return ret; 344 348 345 349 ipu_crtc->di = ipu_di_get(ipu, pdata->di); 346 - if (IS_ERR(ipu_crtc->di)) { 347 - ret = PTR_ERR(ipu_crtc->di); 348 - goto err_out; 349 - } 350 + if (IS_ERR(ipu_crtc->di)) 351 + return PTR_ERR(ipu_crtc->di); 350 352 351 353 return 0; 352 - err_out: 353 - ipu_put_resources(ipu_crtc); 354 - 355 - return ret; 356 354 } 357 355 358 - static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, 359 - struct ipu_client_platformdata *pdata, struct drm_device *drm) 356 + static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 360 357 { 361 - struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 362 - struct drm_crtc *crtc = &ipu_crtc->base; 358 + struct ipu_client_platformdata *pdata = dev->platform_data; 359 + struct ipu_soc *ipu = dev_get_drvdata(dev->parent); 360 + struct drm_device *drm = data; 361 + struct ipu_plane *primary_plane; 362 + struct ipu_crtc *ipu_crtc; 363 + struct drm_crtc *crtc; 363 364 int dp = -EINVAL; 364 365 int ret; 365 366 366 - ret = ipu_get_resources(ipu_crtc, pdata); 367 - if (ret) { 368 - dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", 369 - ret); 370 - return ret; 371 - } 372 - 373 367 if (pdata->dp >= 0) 374 368 dp = IPU_DP_FLOW_SYNC_BG; 375 - ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0, 376 - DRM_PLANE_TYPE_PRIMARY); 377 - if (IS_ERR(ipu_crtc->plane[0])) { 378 - ret = PTR_ERR(ipu_crtc->plane[0]); 379 - goto err_put_resources; 380 - } 369 + primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0, 370 + DRM_PLANE_TYPE_PRIMARY); 371 + if (IS_ERR(primary_plane)) 372 + return PTR_ERR(primary_plane); 381 373 374 + ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base, 375 + &primary_plane->base, NULL, 376 + &ipu_crtc_funcs, NULL); 377 + if (IS_ERR(ipu_crtc)) 378 + return PTR_ERR(ipu_crtc); 379 + 380 + ipu_crtc->dev = dev; 381 + ipu_crtc->plane[0] = primary_plane; 382 + 383 + crtc = &ipu_crtc->base; 382 384 crtc->port = pdata->of_node; 383 385 drm_crtc_helper_add(crtc, &ipu_helper_funcs); 384 - drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL, 385 - &ipu_crtc_funcs, NULL); 386 + 387 + ret = ipu_get_resources(drm, ipu_crtc, pdata); 388 + if (ret) { 389 + dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", 390 + ret); 391 + return ret; 392 + } 386 393 387 394 /* If this crtc is using the DP, add an overlay plane */ 388 395 if (pdata->dp >= 0 && pdata->dma[1] > 0) { ··· 406 399 "imx_drm", ipu_crtc); 407 400 if (ret < 0) { 408 401 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 409 - goto err_put_resources; 402 + return ret; 410 403 } 411 404 /* Only enable IRQ when we actually need it to trigger work. */ 412 405 disable_irq(ipu_crtc->irq); 413 406 414 407 return 0; 415 - 416 - err_put_resources: 417 - ipu_put_resources(ipu_crtc); 418 - 419 - return ret; 420 - } 421 - 422 - static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 423 - { 424 - struct ipu_client_platformdata *pdata = dev->platform_data; 425 - struct drm_device *drm = data; 426 - struct ipu_crtc *ipu_crtc; 427 - 428 - ipu_crtc = dev_get_drvdata(dev); 429 - memset(ipu_crtc, 0, sizeof(*ipu_crtc)); 430 - 431 - ipu_crtc->dev = dev; 432 - 433 - return ipu_crtc_init(ipu_crtc, pdata, drm); 434 - } 435 - 436 - static void ipu_drm_unbind(struct device *dev, struct device *master, 437 - void *data) 438 - { 439 - struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev); 440 - 441 - ipu_put_resources(ipu_crtc); 442 408 } 443 409 444 410 static const struct component_ops ipu_crtc_ops = { 445 411 .bind = ipu_drm_bind, 446 - .unbind = ipu_drm_unbind, 447 412 }; 448 413 449 414 static int ipu_drm_probe(struct platform_device *pdev) 450 415 { 451 416 struct device *dev = &pdev->dev; 452 - struct ipu_crtc *ipu_crtc; 453 417 int ret; 454 418 455 419 if (!dev->platform_data) ··· 429 451 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 430 452 if (ret) 431 453 return ret; 432 - 433 - ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL); 434 - if (!ipu_crtc) 435 - return -ENOMEM; 436 - 437 - dev_set_drvdata(dev, ipu_crtc); 438 454 439 455 return component_add(dev, &ipu_crtc_ops); 440 456 }