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

drm: xlnx: zynqmp_dpsub: Manage DP and DISP allocations manually

The zynqmp_disp and zynqmp_dp structures are allocated with
drmm_kzalloc(). While this simplifies management of memory, it requires
a DRM device, which will not be available at probe time when the DP
bridge will be used standalone, with a DRM device in the PL. To prepare
for this, switch to manual allocation for zynqmp_disp and zynqmp_dp. The
cleanup still uses the DRM managed infrastructure, but one level up, at
the top level. This will be addressed separately.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

+57 -30
+22 -12
drivers/gpu/drm/xlnx/zynqmp_disp.c
··· 12 12 #include <drm/drm_fb_dma_helper.h> 13 13 #include <drm/drm_fourcc.h> 14 14 #include <drm/drm_framebuffer.h> 15 - #include <drm/drm_managed.h> 16 15 #include <drm/drm_plane.h> 17 16 18 17 #include <linux/clk.h> ··· 21 22 #include <linux/module.h> 22 23 #include <linux/of.h> 23 24 #include <linux/platform_device.h> 25 + #include <linux/slab.h> 24 26 25 27 #include "zynqmp_disp.h" 26 28 #include "zynqmp_disp_regs.h" ··· 1225 1225 * Initialization & Cleanup 1226 1226 */ 1227 1227 1228 - int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) 1228 + int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub) 1229 1229 { 1230 1230 struct platform_device *pdev = to_platform_device(dpsub->dev); 1231 1231 struct zynqmp_disp *disp; ··· 1233 1233 struct resource *res; 1234 1234 int ret; 1235 1235 1236 - disp = drmm_kzalloc(drm, sizeof(*disp), GFP_KERNEL); 1236 + disp = kzalloc(sizeof(*disp), GFP_KERNEL); 1237 1237 if (!disp) 1238 1238 return -ENOMEM; 1239 1239 1240 1240 disp->dev = &pdev->dev; 1241 1241 disp->dpsub = dpsub; 1242 1242 1243 - dpsub->disp = disp; 1244 - 1245 1243 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend"); 1246 1244 disp->blend.base = devm_ioremap_resource(disp->dev, res); 1247 - if (IS_ERR(disp->blend.base)) 1248 - return PTR_ERR(disp->blend.base); 1245 + if (IS_ERR(disp->blend.base)) { 1246 + ret = PTR_ERR(disp->blend.base); 1247 + goto error; 1248 + } 1249 1249 1250 1250 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf"); 1251 1251 disp->avbuf.base = devm_ioremap_resource(disp->dev, res); 1252 - if (IS_ERR(disp->avbuf.base)) 1253 - return PTR_ERR(disp->avbuf.base); 1252 + if (IS_ERR(disp->avbuf.base)) { 1253 + ret = PTR_ERR(disp->avbuf.base); 1254 + goto error; 1255 + } 1254 1256 1255 1257 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud"); 1256 1258 disp->audio.base = devm_ioremap_resource(disp->dev, res); 1257 - if (IS_ERR(disp->audio.base)) 1258 - return PTR_ERR(disp->audio.base); 1259 + if (IS_ERR(disp->audio.base)) { 1260 + ret = PTR_ERR(disp->audio.base); 1261 + goto error; 1262 + } 1259 1263 1260 1264 ret = zynqmp_disp_create_layers(disp); 1261 1265 if (ret) 1262 - return ret; 1266 + goto error; 1263 1267 1264 1268 layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID]; 1265 1269 dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align; 1266 1270 1271 + dpsub->disp = disp; 1272 + 1267 1273 return 0; 1274 + 1275 + error: 1276 + kfree(disp); 1277 + return ret; 1268 1278 } 1269 1279 1270 1280 void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub)
+1 -2
drivers/gpu/drm/xlnx/zynqmp_disp.h
··· 25 25 #define ZYNQMP_DISP_MAX_DMA_BIT 44 26 26 27 27 struct device; 28 - struct drm_device; 29 28 struct drm_format_info; 30 29 struct drm_plane_state; 31 30 struct platform_device; ··· 59 60 int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, 60 61 struct drm_plane_state *state); 61 62 62 - int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm); 63 + int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub); 63 64 void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub); 64 65 65 66 #endif /* _ZYNQMP_DISP_H_ */
+18 -12
drivers/gpu/drm/xlnx/zynqmp_dp.c
··· 14 14 #include <drm/drm_crtc.h> 15 15 #include <drm/drm_device.h> 16 16 #include <drm/drm_edid.h> 17 - #include <drm/drm_managed.h> 18 17 #include <drm/drm_modes.h> 19 18 #include <drm/drm_of.h> 20 19 ··· 26 27 #include <linux/pm_runtime.h> 27 28 #include <linux/phy/phy.h> 28 29 #include <linux/reset.h> 30 + #include <linux/slab.h> 29 31 30 32 #include "zynqmp_disp.h" 31 33 #include "zynqmp_dp.h" ··· 1610 1610 * Initialization & Cleanup 1611 1611 */ 1612 1612 1613 - int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) 1613 + int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) 1614 1614 { 1615 1615 struct platform_device *pdev = to_platform_device(dpsub->dev); 1616 1616 struct drm_bridge *bridge; ··· 1618 1618 struct resource *res; 1619 1619 int ret; 1620 1620 1621 - dp = drmm_kzalloc(drm, sizeof(*dp), GFP_KERNEL); 1621 + dp = kzalloc(sizeof(*dp), GFP_KERNEL); 1622 1622 if (!dp) 1623 1623 return -ENOMEM; 1624 1624 ··· 1628 1628 1629 1629 INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); 1630 1630 1631 - dpsub->dp = dp; 1632 - 1633 1631 /* Acquire all resources (IOMEM, IRQ and PHYs). */ 1634 1632 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp"); 1635 1633 dp->iomem = devm_ioremap_resource(dp->dev, res); 1636 - if (IS_ERR(dp->iomem)) 1637 - return PTR_ERR(dp->iomem); 1634 + if (IS_ERR(dp->iomem)) { 1635 + ret = PTR_ERR(dp->iomem); 1636 + goto err_free; 1637 + } 1638 1638 1639 1639 dp->irq = platform_get_irq(pdev, 0); 1640 - if (dp->irq < 0) 1641 - return dp->irq; 1640 + if (dp->irq < 0) { 1641 + ret = dp->irq; 1642 + goto err_free; 1643 + } 1642 1644 1643 1645 dp->reset = devm_reset_control_get(dp->dev, NULL); 1644 1646 if (IS_ERR(dp->reset)) { 1645 1647 if (PTR_ERR(dp->reset) != -EPROBE_DEFER) 1646 1648 dev_err(dp->dev, "failed to get reset: %ld\n", 1647 1649 PTR_ERR(dp->reset)); 1648 - return PTR_ERR(dp->reset); 1650 + ret = PTR_ERR(dp->reset); 1651 + goto err_free; 1649 1652 } 1650 1653 1651 1654 ret = zynqmp_dp_reset(dp, false); 1652 1655 if (ret < 0) 1653 - return ret; 1656 + goto err_free; 1654 1657 1655 1658 ret = zynqmp_dp_phy_probe(dp); 1656 1659 if (ret) ··· 1703 1700 if (ret < 0) 1704 1701 goto err_phy_exit; 1705 1702 1703 + dpsub->dp = dp; 1704 + 1706 1705 dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n", 1707 1706 dp->num_lanes); 1708 1707 ··· 1714 1709 zynqmp_dp_phy_exit(dp); 1715 1710 err_reset: 1716 1711 zynqmp_dp_reset(dp, true); 1717 - 1712 + err_free: 1713 + kfree(dp); 1718 1714 return ret; 1719 1715 } 1720 1716
+1 -2
drivers/gpu/drm/xlnx/zynqmp_dp.h
··· 12 12 #ifndef _ZYNQMP_DP_H_ 13 13 #define _ZYNQMP_DP_H_ 14 14 15 - struct drm_device; 16 15 struct platform_device; 17 16 struct zynqmp_dp; 18 17 struct zynqmp_dpsub; ··· 19 20 void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp); 20 21 void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp); 21 22 22 - int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm); 23 + int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub); 23 24 void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub); 24 25 25 26 #endif /* _ZYNQMP_DP_H_ */
+15 -2
drivers/gpu/drm/xlnx/zynqmp_dpsub.c
··· 15 15 #include <linux/of_reserved_mem.h> 16 16 #include <linux/platform_device.h> 17 17 #include <linux/pm_runtime.h> 18 + #include <linux/slab.h> 18 19 19 20 #include <drm/drm_atomic_helper.h> 20 21 #include <drm/drm_bridge_connector.h> ··· 248 247 return 0; 249 248 } 250 249 250 + static void zynqmp_dpsub_release(struct drm_device *drm, void *res) 251 + { 252 + struct zynqmp_dpsub *dpsub = res; 253 + 254 + kfree(dpsub->disp); 255 + kfree(dpsub->dp); 256 + } 257 + 251 258 static int zynqmp_dpsub_probe(struct platform_device *pdev) 252 259 { 253 260 struct zynqmp_dpsub *dpsub; ··· 266 257 struct zynqmp_dpsub, drm); 267 258 if (IS_ERR(dpsub)) 268 259 return PTR_ERR(dpsub); 260 + 261 + ret = drmm_add_action(&dpsub->drm, zynqmp_dpsub_release, dpsub); 262 + if (ret < 0) 263 + return ret; 269 264 270 265 dpsub->dev = &pdev->dev; 271 266 platform_set_drvdata(pdev, dpsub); ··· 289 276 * DP should be probed first so that the zynqmp_disp can set the output 290 277 * format accordingly. 291 278 */ 292 - ret = zynqmp_dp_probe(dpsub, &dpsub->drm); 279 + ret = zynqmp_dp_probe(dpsub); 293 280 if (ret) 294 281 goto err_pm; 295 282 296 - ret = zynqmp_disp_probe(dpsub, &dpsub->drm); 283 + ret = zynqmp_disp_probe(dpsub); 297 284 if (ret) 298 285 goto err_dp; 299 286