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

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 <laurent.pinchart@ideasonboard.com>

+80 -7
+55
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_fourcc.h> 17 18 #include <drm/drm_modes.h> 18 19 #include <drm/drm_of.h> 19 20 ··· 1273 1272 } 1274 1273 1275 1274 /* ----------------------------------------------------------------------------- 1275 + * DISP Configuration 1276 + */ 1277 + 1278 + static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, 1279 + struct drm_bridge_state *old_bridge_state) 1280 + { 1281 + enum zynqmp_dpsub_layer_id layer_id; 1282 + struct zynqmp_disp_layer *layer; 1283 + const struct drm_format_info *info; 1284 + 1285 + if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) 1286 + layer_id = ZYNQMP_DPSUB_LAYER_VID; 1287 + else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) 1288 + layer_id = ZYNQMP_DPSUB_LAYER_GFX; 1289 + else 1290 + return; 1291 + 1292 + layer = dp->dpsub->layers[layer_id]; 1293 + 1294 + /* TODO: Make the format configurable. */ 1295 + info = drm_format_info(DRM_FORMAT_YUV422); 1296 + zynqmp_disp_layer_set_format(layer, info); 1297 + zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE); 1298 + 1299 + if (layer_id == ZYNQMP_DPSUB_LAYER_GFX) 1300 + zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255); 1301 + else 1302 + zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0); 1303 + 1304 + zynqmp_disp_enable(dp->dpsub->disp); 1305 + } 1306 + 1307 + static void zynqmp_dp_disp_disable(struct zynqmp_dp *dp, 1308 + struct drm_bridge_state *old_bridge_state) 1309 + { 1310 + struct zynqmp_disp_layer *layer; 1311 + 1312 + if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) 1313 + layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; 1314 + else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) 1315 + layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; 1316 + else 1317 + return; 1318 + 1319 + zynqmp_disp_disable(dp->dpsub->disp); 1320 + zynqmp_disp_layer_disable(layer); 1321 + } 1322 + 1323 + /* ----------------------------------------------------------------------------- 1276 1324 * DRM Bridge 1277 1325 */ 1278 1326 ··· 1405 1355 1406 1356 pm_runtime_get_sync(dp->dev); 1407 1357 1358 + zynqmp_dp_disp_enable(dp, old_bridge_state); 1359 + 1408 1360 /* 1409 1361 * Retrieve the CRTC mode and adjusted mode. This requires a little 1410 1362 * dance to go from the bridge to the encoder, to the connector and to ··· 1480 1428 ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL); 1481 1429 if (zynqmp_dpsub_audio_enabled(dp->dpsub)) 1482 1430 zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0); 1431 + 1432 + zynqmp_dp_disp_disable(dp, old_bridge_state); 1433 + 1483 1434 pm_runtime_put_sync(dp->dev); 1484 1435 } 1485 1436
+25 -7
drivers/gpu/drm/xlnx/zynqmp_dpsub.c
··· 19 19 #include <linux/slab.h> 20 20 21 21 #include <drm/drm_atomic_helper.h> 22 + #include <drm/drm_bridge.h> 22 23 #include <drm/drm_modeset_helper.h> 23 24 #include <drm/drm_module.h> 24 25 ··· 175 174 } 176 175 177 176 /* Sanity checks. */ 178 - if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) || 179 - (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) 180 - dev_warn(dpsub->dev, "live video unsupported, ignoring\n"); 177 + if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) && 178 + (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) { 179 + dev_err(dpsub->dev, "only one live video input is supported\n"); 180 + return -EINVAL; 181 + } 181 182 182 - dpsub->dma_enabled = true; 183 + if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) || 184 + (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) { 185 + if (dpsub->vid_clk_from_ps) { 186 + dev_err(dpsub->dev, 187 + "live video input requires PL clock\n"); 188 + return -EINVAL; 189 + } 190 + } else { 191 + dpsub->dma_enabled = true; 192 + } 183 193 184 194 if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO)) 185 195 dev_warn(dpsub->dev, "live audio unsupported, ignoring\n"); ··· 254 242 if (ret) 255 243 goto err_dp; 256 244 257 - ret = zynqmp_dpsub_drm_init(dpsub); 258 - if (ret) 259 - goto err_disp; 245 + if (dpsub->dma_enabled) { 246 + ret = zynqmp_dpsub_drm_init(dpsub); 247 + if (ret) 248 + goto err_disp; 249 + } else { 250 + drm_bridge_add(dpsub->bridge); 251 + } 260 252 261 253 dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed"); 262 254 ··· 286 270 287 271 if (dpsub->drm) 288 272 zynqmp_dpsub_drm_cleanup(dpsub); 273 + else 274 + drm_bridge_remove(dpsub->bridge); 289 275 290 276 zynqmp_disp_remove(dpsub); 291 277 zynqmp_dp_remove(dpsub);