Skip to content

Commit 6ca91bb

Browse files
committed
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 <[email protected]>
1 parent 5889ee5 commit 6ca91bb

File tree

5 files changed

+57
-30
lines changed

5 files changed

+57
-30
lines changed

drivers/gpu/drm/xlnx/zynqmp_disp.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <drm/drm_fb_dma_helper.h>
1313
#include <drm/drm_fourcc.h>
1414
#include <drm/drm_framebuffer.h>
15-
#include <drm/drm_managed.h>
1615
#include <drm/drm_plane.h>
1716

1817
#include <linux/clk.h>
@@ -22,6 +21,7 @@
2221
#include <linux/module.h>
2322
#include <linux/of.h>
2423
#include <linux/platform_device.h>
24+
#include <linux/slab.h>
2525

2626
#include "zynqmp_disp.h"
2727
#include "zynqmp_disp_regs.h"
@@ -1225,46 +1225,56 @@ int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
12251225
* Initialization & Cleanup
12261226
*/
12271227

1228-
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
1228+
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub)
12291229
{
12301230
struct platform_device *pdev = to_platform_device(dpsub->dev);
12311231
struct zynqmp_disp *disp;
12321232
struct zynqmp_disp_layer *layer;
12331233
struct resource *res;
12341234
int ret;
12351235

1236-
disp = drmm_kzalloc(drm, sizeof(*disp), GFP_KERNEL);
1236+
disp = kzalloc(sizeof(*disp), GFP_KERNEL);
12371237
if (!disp)
12381238
return -ENOMEM;
12391239

12401240
disp->dev = &pdev->dev;
12411241
disp->dpsub = dpsub;
12421242

1243-
dpsub->disp = disp;
1244-
12451243
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
12461244
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+
}
12491249

12501250
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
12511251
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+
}
12541256

12551257
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
12561258
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+
}
12591263

12601264
ret = zynqmp_disp_create_layers(disp);
12611265
if (ret)
1262-
return ret;
1266+
goto error;
12631267

12641268
layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID];
12651269
dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align;
12661270

1271+
dpsub->disp = disp;
1272+
12671273
return 0;
1274+
1275+
error:
1276+
kfree(disp);
1277+
return ret;
12681278
}
12691279

12701280
void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub)

drivers/gpu/drm/xlnx/zynqmp_disp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#define ZYNQMP_DISP_MAX_DMA_BIT 44
2626

2727
struct device;
28-
struct drm_device;
2928
struct drm_format_info;
3029
struct drm_plane_state;
3130
struct platform_device;
@@ -60,7 +59,7 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
6059
int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
6160
struct drm_plane_state *state);
6261

63-
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
62+
int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub);
6463
void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub);
6564

6665
#endif /* _ZYNQMP_DISP_H_ */

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <drm/drm_crtc.h>
1515
#include <drm/drm_device.h>
1616
#include <drm/drm_edid.h>
17-
#include <drm/drm_managed.h>
1817
#include <drm/drm_modes.h>
1918
#include <drm/drm_of.h>
2019

@@ -27,6 +26,7 @@
2726
#include <linux/pm_runtime.h>
2827
#include <linux/phy/phy.h>
2928
#include <linux/reset.h>
29+
#include <linux/slab.h>
3030

3131
#include "zynqmp_disp.h"
3232
#include "zynqmp_dp.h"
@@ -1610,15 +1610,15 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
16101610
* Initialization & Cleanup
16111611
*/
16121612

1613-
int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
1613+
int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
16141614
{
16151615
struct platform_device *pdev = to_platform_device(dpsub->dev);
16161616
struct drm_bridge *bridge;
16171617
struct zynqmp_dp *dp;
16181618
struct resource *res;
16191619
int ret;
16201620

1621-
dp = drmm_kzalloc(drm, sizeof(*dp), GFP_KERNEL);
1621+
dp = kzalloc(sizeof(*dp), GFP_KERNEL);
16221622
if (!dp)
16231623
return -ENOMEM;
16241624

@@ -1628,29 +1628,32 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
16281628

16291629
INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
16301630

1631-
dpsub->dp = dp;
1632-
16331631
/* Acquire all resources (IOMEM, IRQ and PHYs). */
16341632
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
16351633
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+
}
16381638

16391639
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+
}
16421644

16431645
dp->reset = devm_reset_control_get(dp->dev, NULL);
16441646
if (IS_ERR(dp->reset)) {
16451647
if (PTR_ERR(dp->reset) != -EPROBE_DEFER)
16461648
dev_err(dp->dev, "failed to get reset: %ld\n",
16471649
PTR_ERR(dp->reset));
1648-
return PTR_ERR(dp->reset);
1650+
ret = PTR_ERR(dp->reset);
1651+
goto err_free;
16491652
}
16501653

16511654
ret = zynqmp_dp_reset(dp, false);
16521655
if (ret < 0)
1653-
return ret;
1656+
goto err_free;
16541657

16551658
ret = zynqmp_dp_phy_probe(dp);
16561659
if (ret)
@@ -1700,6 +1703,8 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
17001703
if (ret < 0)
17011704
goto err_phy_exit;
17021705

1706+
dpsub->dp = dp;
1707+
17031708
dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n",
17041709
dp->num_lanes);
17051710

@@ -1709,7 +1714,8 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
17091714
zynqmp_dp_phy_exit(dp);
17101715
err_reset:
17111716
zynqmp_dp_reset(dp, true);
1712-
1717+
err_free:
1718+
kfree(dp);
17131719
return ret;
17141720
}
17151721

drivers/gpu/drm/xlnx/zynqmp_dp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
#ifndef _ZYNQMP_DP_H_
1313
#define _ZYNQMP_DP_H_
1414

15-
struct drm_device;
1615
struct platform_device;
1716
struct zynqmp_dp;
1817
struct zynqmp_dpsub;
1918

2019
void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp);
2120
void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp);
2221

23-
int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
22+
int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub);
2423
void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub);
2524

2625
#endif /* _ZYNQMP_DP_H_ */

drivers/gpu/drm/xlnx/zynqmp_dpsub.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/of_reserved_mem.h>
1616
#include <linux/platform_device.h>
1717
#include <linux/pm_runtime.h>
18+
#include <linux/slab.h>
1819

1920
#include <drm/drm_atomic_helper.h>
2021
#include <drm/drm_bridge_connector.h>
@@ -247,6 +248,14 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
247248
return 0;
248249
}
249250

251+
static void zynqmp_dpsub_release(struct drm_device *drm, void *res)
252+
{
253+
struct zynqmp_dpsub *dpsub = res;
254+
255+
kfree(dpsub->disp);
256+
kfree(dpsub->dp);
257+
}
258+
250259
static int zynqmp_dpsub_probe(struct platform_device *pdev)
251260
{
252261
struct zynqmp_dpsub *dpsub;
@@ -258,6 +267,10 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
258267
if (IS_ERR(dpsub))
259268
return PTR_ERR(dpsub);
260269

270+
ret = drmm_add_action(&dpsub->drm, zynqmp_dpsub_release, dpsub);
271+
if (ret < 0)
272+
return ret;
273+
261274
dpsub->dev = &pdev->dev;
262275
platform_set_drvdata(pdev, dpsub);
263276

@@ -276,11 +289,11 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
276289
* DP should be probed first so that the zynqmp_disp can set the output
277290
* format accordingly.
278291
*/
279-
ret = zynqmp_dp_probe(dpsub, &dpsub->drm);
292+
ret = zynqmp_dp_probe(dpsub);
280293
if (ret)
281294
goto err_pm;
282295

283-
ret = zynqmp_disp_probe(dpsub, &dpsub->drm);
296+
ret = zynqmp_disp_probe(dpsub);
284297
if (ret)
285298
goto err_dp;
286299

0 commit comments

Comments
 (0)