Skip to content

Commit d189835

Browse files
committed
drm: xlnx: zynqmp_dpsub: Decouple DRM device from zynqmp_dpsub
To complete the decoupling of the DRM device from the zynqmp_dpsub, group all DRM-related structures in a zynqmp_dpsub_drm structure and allocate it separately from the zynqmp_dpsub. The DRM managed allocation of the drm_device now doesn't cover the zynqmp_dpsub anymore, so we need to register a cleanup action to release the zynqmp_dpsub when the drm_device is released. The will allow usage of the DisplayPort encoder as a standalone bridge, without registering a DRM device in this driver. Signed-off-by: Laurent Pinchart <[email protected]>
1 parent 074ef0c commit d189835

File tree

4 files changed

+99
-50
lines changed

4 files changed

+99
-50
lines changed

drivers/gpu/drm/xlnx/zynqmp_dpsub.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#include <linux/slab.h>
1919

2020
#include <drm/drm_atomic_helper.h>
21-
#include <drm/drm_drv.h>
22-
#include <drm/drm_managed.h>
2321
#include <drm/drm_modeset_helper.h>
2422
#include <drm/drm_module.h>
2523

@@ -36,14 +34,20 @@ static int __maybe_unused zynqmp_dpsub_suspend(struct device *dev)
3634
{
3735
struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
3836

39-
return drm_mode_config_helper_suspend(&dpsub->drm);
37+
if (!dpsub->drm)
38+
return 0;
39+
40+
return drm_mode_config_helper_suspend(&dpsub->drm->dev);
4041
}
4142

4243
static int __maybe_unused zynqmp_dpsub_resume(struct device *dev)
4344
{
4445
struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
4546

46-
return drm_mode_config_helper_resume(&dpsub->drm);
47+
if (!dpsub->drm)
48+
return 0;
49+
50+
return drm_mode_config_helper_resume(&dpsub->drm->dev);
4751
}
4852

4953
static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
@@ -138,12 +142,11 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
138142
return 0;
139143
}
140144

141-
static void zynqmp_dpsub_release(struct drm_device *drm, void *res)
145+
void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub)
142146
{
143-
struct zynqmp_dpsub *dpsub = res;
144-
145147
kfree(dpsub->disp);
146148
kfree(dpsub->dp);
149+
kfree(dpsub);
147150
}
148151

149152
static int zynqmp_dpsub_probe(struct platform_device *pdev)
@@ -152,14 +155,9 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
152155
int ret;
153156

154157
/* Allocate private data. */
155-
dpsub = devm_drm_dev_alloc(&pdev->dev, &zynqmp_dpsub_drm_driver,
156-
struct zynqmp_dpsub, drm);
157-
if (IS_ERR(dpsub))
158-
return PTR_ERR(dpsub);
159-
160-
ret = drmm_add_action(&dpsub->drm, zynqmp_dpsub_release, dpsub);
161-
if (ret < 0)
162-
return ret;
158+
dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL);
159+
if (!dpsub)
160+
return -ENOMEM;
163161

164162
dpsub->dev = &pdev->dev;
165163
platform_set_drvdata(pdev, dpsub);
@@ -204,14 +202,17 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
204202
clk_disable_unprepare(dpsub->apb_clk);
205203
err_mem:
206204
of_reserved_mem_device_release(&pdev->dev);
205+
if (!dpsub->drm)
206+
zynqmp_dpsub_release(dpsub);
207207
return ret;
208208
}
209209

210210
static int zynqmp_dpsub_remove(struct platform_device *pdev)
211211
{
212212
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
213213

214-
zynqmp_dpsub_drm_cleanup(dpsub);
214+
if (dpsub->drm)
215+
zynqmp_dpsub_drm_cleanup(dpsub);
215216

216217
zynqmp_disp_remove(dpsub);
217218
zynqmp_dp_remove(dpsub);
@@ -220,14 +221,20 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev)
220221
clk_disable_unprepare(dpsub->apb_clk);
221222
of_reserved_mem_device_release(&pdev->dev);
222223

224+
if (!dpsub->drm)
225+
zynqmp_dpsub_release(dpsub);
226+
223227
return 0;
224228
}
225229

226230
static void zynqmp_dpsub_shutdown(struct platform_device *pdev)
227231
{
228232
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
229233

230-
drm_atomic_helper_shutdown(&dpsub->drm);
234+
if (!dpsub->drm)
235+
return;
236+
237+
drm_atomic_helper_shutdown(&dpsub->drm->dev);
231238
}
232239

233240
static const struct of_device_id zynqmp_dpsub_of_match[] = {

drivers/gpu/drm/xlnx/zynqmp_dpsub.h

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@
1212
#ifndef _ZYNQMP_DPSUB_H_
1313
#define _ZYNQMP_DPSUB_H_
1414

15-
#include <drm/drm_crtc.h>
16-
#include <drm/drm_encoder.h>
17-
#include <drm/drm_plane.h>
18-
1915
struct clk;
2016
struct device;
2117
struct drm_bridge;
22-
struct drm_device;
2318
struct zynqmp_disp;
2419
struct zynqmp_disp_layer;
2520
struct zynqmp_dp;
21+
struct zynqmp_dpsub_drm;
2622

2723
#define ZYNQMP_DPSUB_NUM_LAYERS 2
2824

@@ -35,23 +31,19 @@ enum zynqmp_dpsub_format {
3531

3632
/**
3733
* struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem
38-
* @drm: The DRM/KMS device
3934
* @dev: The physical device
4035
* @apb_clk: The APB clock
4136
* @vid_clk: Video clock
4237
* @vid_clk_from_ps: True of the video clock comes from PS, false from PL
4338
* @aud_clk: Audio clock
4439
* @aud_clk_from_ps: True of the audio clock comes from PS, false from PL
45-
* @planes: The DRM planes
46-
* @crtc: The DRM CRTC
47-
* @encoder: The dummy DRM encoder
40+
* @drm: The DRM/KMS device data
4841
* @bridge: The DP encoder bridge
4942
* @disp: The display controller
5043
* @dp: The DisplayPort controller
5144
* @dma_align: DMA alignment constraint (must be a power of 2)
5245
*/
5346
struct zynqmp_dpsub {
54-
struct drm_device drm;
5547
struct device *dev;
5648

5749
struct clk *apb_clk;
@@ -60,9 +52,7 @@ struct zynqmp_dpsub {
6052
struct clk *aud_clk;
6153
bool aud_clk_from_ps;
6254

63-
struct drm_plane planes[ZYNQMP_DPSUB_NUM_LAYERS];
64-
struct drm_crtc crtc;
65-
struct drm_encoder encoder;
55+
struct zynqmp_dpsub_drm *drm;
6656
struct drm_bridge *bridge;
6757

6858
struct zynqmp_disp *disp;
@@ -75,4 +65,6 @@ struct zynqmp_dpsub {
7565
bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub);
7666
unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub *dpsub);
7767

68+
void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub);
69+
7870
#endif /* _ZYNQMP_DPSUB_H_ */

drivers/gpu/drm/xlnx/zynqmp_kms.c

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
static inline struct zynqmp_dpsub *to_zynqmp_dpsub(struct drm_device *drm)
4646
{
47-
return container_of(drm, struct zynqmp_dpsub, drm);
47+
return container_of(drm, struct zynqmp_dpsub_drm, dev)->dpsub;
4848
}
4949

5050
/* -----------------------------------------------------------------------------
@@ -146,9 +146,9 @@ static int zynqmp_dpsub_create_planes(struct zynqmp_dpsub *dpsub)
146146
unsigned int i;
147147
int ret;
148148

149-
for (i = 0; i < ARRAY_SIZE(dpsub->planes); i++) {
149+
for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++) {
150150
struct zynqmp_disp_layer *layer = dpsub->layers[i];
151-
struct drm_plane *plane = &dpsub->planes[i];
151+
struct drm_plane *plane = &dpsub->drm->planes[i];
152152
enum drm_plane_type type;
153153
unsigned int num_formats;
154154
u32 *formats;
@@ -160,7 +160,7 @@ static int zynqmp_dpsub_create_planes(struct zynqmp_dpsub *dpsub)
160160
/* Graphics layer is primary, and video layer is overlay. */
161161
type = i == ZYNQMP_DPSUB_LAYER_VID
162162
? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
163-
ret = drm_universal_plane_init(&dpsub->drm, plane, 0,
163+
ret = drm_universal_plane_init(&dpsub->drm->dev, plane, 0,
164164
&zynqmp_dpsub_plane_funcs,
165165
formats, num_formats,
166166
NULL, type, NULL);
@@ -184,7 +184,7 @@ static int zynqmp_dpsub_create_planes(struct zynqmp_dpsub *dpsub)
184184

185185
static inline struct zynqmp_dpsub *crtc_to_dpsub(struct drm_crtc *crtc)
186186
{
187-
return container_of(crtc, struct zynqmp_dpsub, crtc);
187+
return container_of(crtc, struct zynqmp_dpsub_drm, crtc)->dpsub;
188188
}
189189

190190
static void zynqmp_dpsub_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -312,11 +312,11 @@ static const struct drm_crtc_funcs zynqmp_dpsub_crtc_funcs = {
312312

313313
static int zynqmp_dpsub_create_crtc(struct zynqmp_dpsub *dpsub)
314314
{
315-
struct drm_plane *plane = &dpsub->planes[ZYNQMP_DPSUB_LAYER_GFX];
316-
struct drm_crtc *crtc = &dpsub->crtc;
315+
struct drm_plane *plane = &dpsub->drm->planes[ZYNQMP_DPSUB_LAYER_GFX];
316+
struct drm_crtc *crtc = &dpsub->drm->crtc;
317317
int ret;
318318

319-
ret = drm_crtc_init_with_planes(&dpsub->drm, crtc, plane,
319+
ret = drm_crtc_init_with_planes(&dpsub->drm->dev, crtc, plane,
320320
NULL, &zynqmp_dpsub_crtc_funcs, NULL);
321321
if (ret < 0)
322322
return ret;
@@ -331,11 +331,11 @@ static int zynqmp_dpsub_create_crtc(struct zynqmp_dpsub *dpsub)
331331

332332
static void zynqmp_dpsub_map_crtc_to_plane(struct zynqmp_dpsub *dpsub)
333333
{
334-
u32 possible_crtcs = drm_crtc_mask(&dpsub->crtc);
334+
u32 possible_crtcs = drm_crtc_mask(&dpsub->drm->crtc);
335335
unsigned int i;
336336

337-
for (i = 0; i < ARRAY_SIZE(dpsub->planes); i++)
338-
dpsub->planes[i].possible_crtcs = possible_crtcs;
337+
for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++)
338+
dpsub->drm->planes[i].possible_crtcs = possible_crtcs;
339339
}
340340

341341
/**
@@ -347,7 +347,7 @@ static void zynqmp_dpsub_map_crtc_to_plane(struct zynqmp_dpsub *dpsub)
347347
*/
348348
void zynqmp_dpsub_handle_vblank(struct zynqmp_dpsub *dpsub)
349349
{
350-
drm_crtc_handle_vblank(&dpsub->crtc);
350+
drm_crtc_handle_vblank(&dpsub->drm->crtc);
351351
}
352352

353353
/* -----------------------------------------------------------------------------
@@ -394,7 +394,7 @@ static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = {
394394

395395
DEFINE_DRM_GEM_DMA_FOPS(zynqmp_dpsub_drm_fops);
396396

397-
const struct drm_driver zynqmp_dpsub_drm_driver = {
397+
static const struct drm_driver zynqmp_dpsub_drm_driver = {
398398
.driver_features = DRIVER_MODESET | DRIVER_GEM |
399399
DRIVER_ATOMIC,
400400

@@ -411,7 +411,7 @@ const struct drm_driver zynqmp_dpsub_drm_driver = {
411411

412412
static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
413413
{
414-
struct drm_encoder *encoder = &dpsub->encoder;
414+
struct drm_encoder *encoder = &dpsub->drm->encoder;
415415
struct drm_connector *connector;
416416
int ret;
417417

@@ -427,8 +427,8 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
427427
zynqmp_dpsub_map_crtc_to_plane(dpsub);
428428

429429
/* Create the encoder and attach the bridge. */
430-
encoder->possible_crtcs |= drm_crtc_mask(&dpsub->crtc);
431-
drm_simple_encoder_init(&dpsub->drm, encoder, DRM_MODE_ENCODER_NONE);
430+
encoder->possible_crtcs |= drm_crtc_mask(&dpsub->drm->crtc);
431+
drm_simple_encoder_init(&dpsub->drm->dev, encoder, DRM_MODE_ENCODER_NONE);
432432

433433
ret = drm_bridge_attach(encoder, dpsub->bridge, NULL,
434434
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
@@ -438,7 +438,7 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
438438
}
439439

440440
/* Create the connector for the chain of bridges. */
441-
connector = drm_bridge_connector_init(&dpsub->drm, encoder);
441+
connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder);
442442
if (IS_ERR(connector)) {
443443
dev_err(dpsub->dev, "failed to created connector\n");
444444
return PTR_ERR(connector);
@@ -453,11 +453,39 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
453453
return 0;
454454
}
455455

456+
static void zynqmp_dpsub_drm_release(struct drm_device *drm, void *res)
457+
{
458+
struct zynqmp_dpsub_drm *dpdrm = res;
459+
460+
zynqmp_dpsub_release(dpdrm->dpsub);
461+
}
462+
456463
int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
457464
{
458-
struct drm_device *drm = &dpsub->drm;
465+
struct zynqmp_dpsub_drm *dpdrm;
466+
struct drm_device *drm;
459467
int ret;
460468

469+
/*
470+
* Allocate the drm_device and immediately add a cleanup action to
471+
* release the zynqmp_dpsub instance. If any of those operations fail,
472+
* dpsub->drm will remain NULL, which tells the caller that it must
473+
* cleanup manually.
474+
*/
475+
dpdrm = devm_drm_dev_alloc(dpsub->dev, &zynqmp_dpsub_drm_driver,
476+
struct zynqmp_dpsub_drm, dev);
477+
if (IS_ERR(dpdrm))
478+
return PTR_ERR(dpdrm);
479+
480+
dpdrm->dpsub = dpsub;
481+
drm = &dpdrm->dev;
482+
483+
ret = drmm_add_action(drm, zynqmp_dpsub_drm_release, dpdrm);
484+
if (ret < 0)
485+
return ret;
486+
487+
dpsub->drm = dpdrm;
488+
461489
/* Initialize mode config, vblank and the KMS poll helper. */
462490
ret = drmm_mode_config_init(drm);
463491
if (ret < 0)
@@ -498,7 +526,7 @@ int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
498526

499527
void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub)
500528
{
501-
struct drm_device *drm = &dpsub->drm;
529+
struct drm_device *drm = &dpsub->drm->dev;
502530

503531
drm_dev_unregister(drm);
504532
drm_atomic_helper_shutdown(drm);

drivers/gpu/drm/xlnx/zynqmp_kms.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,31 @@
1212
#ifndef _ZYNQMP_KMS_H_
1313
#define _ZYNQMP_KMS_H_
1414

15+
#include <drm/drm_crtc.h>
16+
#include <drm/drm_device.h>
17+
#include <drm/drm_encoder.h>
18+
#include <drm/drm_plane.h>
19+
20+
#include "zynqmp_dpsub.h"
21+
1522
struct zynqmp_dpsub;
1623

17-
extern const struct drm_driver zynqmp_dpsub_drm_driver;
24+
/**
25+
* struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem DRM/KMS data
26+
* @dpsub: Backpointer to the DisplayPort subsystem
27+
* @drm: The DRM/KMS device
28+
* @planes: The DRM planes
29+
* @crtc: The DRM CRTC
30+
* @encoder: The dummy DRM encoder
31+
*/
32+
struct zynqmp_dpsub_drm {
33+
struct zynqmp_dpsub *dpsub;
34+
35+
struct drm_device dev;
36+
struct drm_plane planes[ZYNQMP_DPSUB_NUM_LAYERS];
37+
struct drm_crtc crtc;
38+
struct drm_encoder encoder;
39+
};
1840

1941
void zynqmp_dpsub_handle_vblank(struct zynqmp_dpsub *dpsub);
2042

0 commit comments

Comments
 (0)