Program live video input format according to selected media bus format.

In the bridge mode of operation, DPSUB is connected to FPGA CRTC which
almost certainly supports a single media bus format as its output. Expect
this to be delivered via the new bridge atomic state. Program DPSUB
registers accordingly.

Signed-off-by: Anatoliy Klymenko <anatoliy.klyme...@amd.com>
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c      | 52 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/xlnx/zynqmp_disp.h      |  2 ++
 drivers/gpu/drm/xlnx/zynqmp_disp_regs.h |  8 ++---
 drivers/gpu/drm/xlnx/zynqmp_dp.c        | 13 ++++++---
 4 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index ee99aad915ba..1c3ffdee6b8e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -416,6 +416,34 @@ static bool zynqmp_disp_layer_is_video(const struct 
zynqmp_disp_layer *layer)
        return layer->id == ZYNQMP_DPSUB_LAYER_VID;
 }
 
+/**
+ * zynqmp_disp_avbuf_set_live_format - Set live input format for a layer
+ * @disp: Display controller
+ * @layer: The layer
+ * @fmt: The format information
+ *
+ * Set the live video input format for @layer to @fmt.
+ */
+static void zynqmp_disp_avbuf_set_live_format(struct zynqmp_disp *disp,
+                                             struct zynqmp_disp_layer *layer,
+                                             const struct zynqmp_disp_format 
*fmt)
+{
+       u32 reg, i;
+
+       reg = zynqmp_disp_layer_is_video(layer)
+           ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
+           : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+       zynqmp_disp_avbuf_write(disp, reg, fmt->buf_fmt);
+
+       for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; ++i) {
+               reg = zynqmp_disp_layer_is_video(layer)
+                   ? ZYNQMP_DISP_AV_BUF_LIVD_VID_COMP_SF(i)
+                   : ZYNQMP_DISP_AV_BUF_LIVD_GFX_COMP_SF(i);
+               zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
+       }
+       layer->disp_fmt = fmt;
+}
+
 /**
  * zynqmp_disp_avbuf_set_format - Set the input format for a layer
  * @disp: Display controller
@@ -979,6 +1007,30 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer 
*layer)
        zynqmp_disp_blend_layer_disable(layer->disp, layer);
 }
 
+/**
+ * zynqmp_disp_layer_set_live_format - Set live layer input format
+ * @layer: The layer
+ * @info: Input media bus format
+ *
+ * Set the live @layer input bus format. The layer must be disabled.
+ */
+void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
+                                      u32 bus_format)
+{
+       int i;
+       const struct zynqmp_disp_format *fmt;
+
+       for (i = 0; i < ARRAY_SIZE(avbuf_live_fmts); ++i) {
+               fmt = &avbuf_live_fmts[i];
+               if (fmt->bus_fmt == bus_format) {
+                       layer->disp_fmt = fmt;
+                       layer->drm_fmt = drm_format_info(fmt->drm_fmt);
+                       zynqmp_disp_avbuf_set_live_format(layer->disp, layer, 
fmt);
+                       return;
+               }
+       }
+}
+
 /**
  * zynqmp_disp_layer_set_format - Set the layer format
  * @layer: The layer
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp.h
index c2c8dd4896ba..f244b7d2346a 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -66,6 +66,8 @@ void zynqmp_disp_layer_enable(struct zynqmp_disp_layer 
*layer);
 void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
                                  const struct drm_format_info *info);
+void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
+                                      u32 bus_format);
 int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
                             struct drm_plane_state *state);
 
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
index f92a006d5070..fa3935384834 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
@@ -165,10 +165,10 @@
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10          0x2
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12          0x3
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK                GENMASK(2, 0)
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB         0x0
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444      0x1
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422      0x2
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY       0x3
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB         (0x0 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444      (0x1 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422      (0x2 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY       (0x3 << 4)
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK                GENMASK(5, 4)
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST                BIT(8)
 #define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY              0x400
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 9cb7ac9f3097..0d5dffd20ad1 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1281,7 +1281,8 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
 {
        enum zynqmp_dpsub_layer_id layer_id;
        struct zynqmp_disp_layer *layer;
-       const struct drm_format_info *info;
+       struct drm_bridge_state *bridge_state;
+       u32 bus_fmt;
 
        if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
                layer_id = ZYNQMP_DPSUB_LAYER_VID;
@@ -1291,10 +1292,14 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
                return;
 
        layer = dp->dpsub->layers[layer_id];
+       bridge_state = 
drm_atomic_get_new_bridge_state(old_bridge_state->base.state,
+                                                      
old_bridge_state->bridge);
+       if (bridge_state) {
+               bus_fmt = bridge_state->input_bus_cfg.format;
+               zynqmp_disp_layer_set_live_format(layer, bus_fmt);
+       } else
+               return;
 
-       /* TODO: Make the format configurable. */
-       info = drm_format_info(DRM_FORMAT_YUV422);
-       zynqmp_disp_layer_set_format(layer, info);
        zynqmp_disp_layer_enable(layer);
 
        if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)

-- 
2.25.1

Reply via email to