Commit 56167161 authored by Laurent Pinchart's avatar Laurent Pinchart

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent 51ae3bd4
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_modes.h> #include <drm/drm_modes.h>
#include <drm/drm_of.h> #include <drm/drm_of.h>
...@@ -1271,6 +1272,55 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp, ...@@ -1271,6 +1272,55 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
zynqmp_dp_write(dp, ZYNQMP_DP_USER_DATA_COUNT_PER_LANE, reg); zynqmp_dp_write(dp, ZYNQMP_DP_USER_DATA_COUNT_PER_LANE, reg);
} }
/* -----------------------------------------------------------------------------
* DISP Configuration
*/
static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
struct drm_bridge_state *old_bridge_state)
{
enum zynqmp_dpsub_layer_id layer_id;
struct zynqmp_disp_layer *layer;
const struct drm_format_info *info;
if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
layer_id = ZYNQMP_DPSUB_LAYER_VID;
else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
layer_id = ZYNQMP_DPSUB_LAYER_GFX;
else
return;
layer = dp->dpsub->layers[layer_id];
/* TODO: Make the format configurable. */
info = drm_format_info(DRM_FORMAT_YUV422);
zynqmp_disp_layer_set_format(layer, info);
zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE);
if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)
zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255);
else
zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0);
zynqmp_disp_enable(dp->dpsub->disp);
}
static void zynqmp_dp_disp_disable(struct zynqmp_dp *dp,
struct drm_bridge_state *old_bridge_state)
{
struct zynqmp_disp_layer *layer;
if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID];
else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX];
else
return;
zynqmp_disp_disable(dp->dpsub->disp);
zynqmp_disp_layer_disable(layer);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* DRM Bridge * DRM Bridge
*/ */
...@@ -1355,6 +1405,8 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge, ...@@ -1355,6 +1405,8 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge,
pm_runtime_get_sync(dp->dev); pm_runtime_get_sync(dp->dev);
zynqmp_dp_disp_enable(dp, old_bridge_state);
/* /*
* Retrieve the CRTC mode and adjusted mode. This requires a little * Retrieve the CRTC mode and adjusted mode. This requires a little
* dance to go from the bridge to the encoder, to the connector and to * 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, ...@@ -1428,6 +1480,9 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL); ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
if (zynqmp_dpsub_audio_enabled(dp->dpsub)) if (zynqmp_dpsub_audio_enabled(dp->dpsub))
zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0); zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
zynqmp_dp_disp_disable(dp, old_bridge_state);
pm_runtime_put_sync(dp->dev); pm_runtime_put_sync(dp->dev);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_modeset_helper.h> #include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h> #include <drm/drm_module.h>
...@@ -174,11 +175,22 @@ static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub) ...@@ -174,11 +175,22 @@ static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub)
} }
/* Sanity checks. */ /* Sanity checks. */
if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) || if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) &&
(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
dev_warn(dpsub->dev, "live video unsupported, ignoring\n"); dev_err(dpsub->dev, "only one live video input is supported\n");
return -EINVAL;
}
dpsub->dma_enabled = true; if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) ||
(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
if (dpsub->vid_clk_from_ps) {
dev_err(dpsub->dev,
"live video input requires PL clock\n");
return -EINVAL;
}
} else {
dpsub->dma_enabled = true;
}
if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO)) if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO))
dev_warn(dpsub->dev, "live audio unsupported, ignoring\n"); dev_warn(dpsub->dev, "live audio unsupported, ignoring\n");
...@@ -242,9 +254,13 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) ...@@ -242,9 +254,13 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_dp; goto err_dp;
ret = zynqmp_dpsub_drm_init(dpsub); if (dpsub->dma_enabled) {
if (ret) ret = zynqmp_dpsub_drm_init(dpsub);
goto err_disp; if (ret)
goto err_disp;
} else {
drm_bridge_add(dpsub->bridge);
}
dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed"); dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed");
...@@ -270,6 +286,8 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev) ...@@ -270,6 +286,8 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev)
if (dpsub->drm) if (dpsub->drm)
zynqmp_dpsub_drm_cleanup(dpsub); zynqmp_dpsub_drm_cleanup(dpsub);
else
drm_bridge_remove(dpsub->bridge);
zynqmp_disp_remove(dpsub); zynqmp_disp_remove(dpsub);
zynqmp_dp_remove(dpsub); zynqmp_dp_remove(dpsub);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment