Skip to content

Commit 5616716

Browse files
committed
drm: xlnx: zynqmp_dpsub: Add support for live video input
Add partial live video support, with a single video input that bypasses blending. Skip registration of the DRM device in that case, but register the DRM bridge instead. The DRM device will be created by the driver for the display controller in the PL. Full live video mode with concurrent usage of the video and gfx inputs, and blending in the DPSUB video pipeline, is currently unsupported. Signed-off-by: Laurent Pinchart <[email protected]>
1 parent 51ae3bd commit 5616716

File tree

2 files changed

+80
-7
lines changed

2 files changed

+80
-7
lines changed

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <drm/drm_crtc.h>
1515
#include <drm/drm_device.h>
1616
#include <drm/drm_edid.h>
17+
#include <drm/drm_fourcc.h>
1718
#include <drm/drm_modes.h>
1819
#include <drm/drm_of.h>
1920

@@ -1271,6 +1272,55 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
12711272
zynqmp_dp_write(dp, ZYNQMP_DP_USER_DATA_COUNT_PER_LANE, reg);
12721273
}
12731274

1275+
/* -----------------------------------------------------------------------------
1276+
* DISP Configuration
1277+
*/
1278+
1279+
static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
1280+
struct drm_bridge_state *old_bridge_state)
1281+
{
1282+
enum zynqmp_dpsub_layer_id layer_id;
1283+
struct zynqmp_disp_layer *layer;
1284+
const struct drm_format_info *info;
1285+
1286+
if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
1287+
layer_id = ZYNQMP_DPSUB_LAYER_VID;
1288+
else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
1289+
layer_id = ZYNQMP_DPSUB_LAYER_GFX;
1290+
else
1291+
return;
1292+
1293+
layer = dp->dpsub->layers[layer_id];
1294+
1295+
/* TODO: Make the format configurable. */
1296+
info = drm_format_info(DRM_FORMAT_YUV422);
1297+
zynqmp_disp_layer_set_format(layer, info);
1298+
zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE);
1299+
1300+
if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)
1301+
zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255);
1302+
else
1303+
zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0);
1304+
1305+
zynqmp_disp_enable(dp->dpsub->disp);
1306+
}
1307+
1308+
static void zynqmp_dp_disp_disable(struct zynqmp_dp *dp,
1309+
struct drm_bridge_state *old_bridge_state)
1310+
{
1311+
struct zynqmp_disp_layer *layer;
1312+
1313+
if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
1314+
layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID];
1315+
else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
1316+
layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX];
1317+
else
1318+
return;
1319+
1320+
zynqmp_disp_disable(dp->dpsub->disp);
1321+
zynqmp_disp_layer_disable(layer);
1322+
}
1323+
12741324
/* -----------------------------------------------------------------------------
12751325
* DRM Bridge
12761326
*/
@@ -1355,6 +1405,8 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge,
13551405

13561406
pm_runtime_get_sync(dp->dev);
13571407

1408+
zynqmp_dp_disp_enable(dp, old_bridge_state);
1409+
13581410
/*
13591411
* Retrieve the CRTC mode and adjusted mode. This requires a little
13601412
* dance to go from the bridge to the encoder, to the connector and to
@@ -1428,6 +1480,9 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
14281480
ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
14291481
if (zynqmp_dpsub_audio_enabled(dp->dpsub))
14301482
zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
1483+
1484+
zynqmp_dp_disp_disable(dp, old_bridge_state);
1485+
14311486
pm_runtime_put_sync(dp->dev);
14321487
}
14331488

drivers/gpu/drm/xlnx/zynqmp_dpsub.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/slab.h>
2020

2121
#include <drm/drm_atomic_helper.h>
22+
#include <drm/drm_bridge.h>
2223
#include <drm/drm_modeset_helper.h>
2324
#include <drm/drm_module.h>
2425

@@ -174,11 +175,22 @@ static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub)
174175
}
175176

176177
/* Sanity checks. */
177-
if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) ||
178-
(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)))
179-
dev_warn(dpsub->dev, "live video unsupported, ignoring\n");
178+
if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) &&
179+
(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
180+
dev_err(dpsub->dev, "only one live video input is supported\n");
181+
return -EINVAL;
182+
}
180183

181-
dpsub->dma_enabled = true;
184+
if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) ||
185+
(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
186+
if (dpsub->vid_clk_from_ps) {
187+
dev_err(dpsub->dev,
188+
"live video input requires PL clock\n");
189+
return -EINVAL;
190+
}
191+
} else {
192+
dpsub->dma_enabled = true;
193+
}
182194

183195
if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO))
184196
dev_warn(dpsub->dev, "live audio unsupported, ignoring\n");
@@ -242,9 +254,13 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
242254
if (ret)
243255
goto err_dp;
244256

245-
ret = zynqmp_dpsub_drm_init(dpsub);
246-
if (ret)
247-
goto err_disp;
257+
if (dpsub->dma_enabled) {
258+
ret = zynqmp_dpsub_drm_init(dpsub);
259+
if (ret)
260+
goto err_disp;
261+
} else {
262+
drm_bridge_add(dpsub->bridge);
263+
}
248264

249265
dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed");
250266

@@ -270,6 +286,8 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev)
270286

271287
if (dpsub->drm)
272288
zynqmp_dpsub_drm_cleanup(dpsub);
289+
else
290+
drm_bridge_remove(dpsub->bridge);
273291

274292
zynqmp_disp_remove(dpsub);
275293
zynqmp_dp_remove(dpsub);

0 commit comments

Comments
 (0)