Re: [PATCH v3 6/9] drm: xlnx: zynqmp_dpsub: Set input live format

2024-04-05 Thread Tomi Valkeinen

On 21/03/2024 22:43, Anatoliy Klymenko wrote:

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. Update zynqmp_disp_layer_set_format() API to fit
both live and non-live layer types.

Signed-off-by: Anatoliy Klymenko 
---
  drivers/gpu/drm/xlnx/zynqmp_disp.c | 66 +-
  drivers/gpu/drm/xlnx/zynqmp_disp.h |  2 +-
  drivers/gpu/drm/xlnx/zynqmp_dp.c   | 13 +---
  drivers/gpu/drm/xlnx/zynqmp_kms.c  |  2 +-
  4 files changed, 55 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 0c2b3f4bffa6..a385d22d428e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -436,19 +436,28 @@ static void zynqmp_disp_avbuf_set_format(struct 
zynqmp_disp *disp,
 const struct zynqmp_disp_format *fmt)
  {
unsigned int i;
-   u32 val;
+   u32 val, reg;
  
-	val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);

-   val &= zynqmp_disp_layer_is_video(layer)
-   ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
-   : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
-   val |= fmt->buf_fmt;
-   zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val);
+   layer->disp_fmt = fmt;
+   if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) {
+   reg = ZYNQMP_DISP_AV_BUF_FMT;
+   val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
+   val &= zynqmp_disp_layer_is_video(layer)
+   ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
+   : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
+   val |= fmt->buf_fmt;
+   } else {
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
+   : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+   val = fmt->buf_fmt;
+   }
+   zynqmp_disp_avbuf_write(disp, reg, val);


Just write the registers inside the above if-else blocks.

  
  	for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) {

-   unsigned int reg = zynqmp_disp_layer_is_video(layer)
-? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
-: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
+   : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
  
  		zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);

}
@@ -902,25 +911,33 @@ static void zynqmp_disp_audio_disable(struct zynqmp_disp 
*disp)
   */
  
  /**

- * zynqmp_disp_layer_find_format - Find format information for a DRM format
+ * zynqmp_disp_layer_find_format - Find format information for a DRM or media
+ * bus format
   * @layer: The layer
- * @drm_fmt: DRM format to search
+ * @drm_or_bus_format: DRM or media bus format
   *
   * Search display subsystem format information corresponding to the given DRM
- * format @drm_fmt for the @layer, and return a pointer to the format
- * descriptor.
+ * or media bus format @drm_or_bus_format for the @layer, and return a pointer
+ * to the format descriptor. Search key choice depends on @layer mode, for live
+ * layers search is done by zynqmp_disp_format.bus_fmt, and for non-live layers
+ * zynqmp_disp_format.drm_fmt is used.


Here also I recommend creating separate funcs for the fourcc and mbus 
versions. They are different types, even if they happen to fit into u32.



   *
   * Return: A pointer to the format descriptor if found, NULL otherwise
   */
  static const struct zynqmp_disp_format *
  zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
- u32 drm_fmt)
+ u32 drm_or_bus_format)
  {
unsigned int i;
+   const struct zynqmp_disp_format *disp_format;
  
  	for (i = 0; i < layer->info->num_formats; i++) {

-   if (layer->info->formats[i].drm_fmt == drm_fmt)
-   return >info->formats[i];
+   disp_format = >info->formats[i];
+   if ((layer->mode == ZYNQMP_DPSUB_LAYER_LIVE &&
+disp_format->bus_fmt == drm_or_bus_format) ||
+   (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE &&
+disp_format->drm_fmt == drm_or_bus_format))
+   return disp_format;
}
  
  	return NULL;

@@ -992,20 +1009,25 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer 
*layer)
  /**
   * zynqmp_disp_layer_set_format - Set the layer format
   * @layer: The layer
- * @info: The format info
+ * @drm_or_bus_format: DRM or media bus format
   *
   * Set the format for @layer to @info. The layer must be 

[PATCH v3 6/9] drm: xlnx: zynqmp_dpsub: Set input live format

2024-03-21 Thread Anatoliy Klymenko
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. Update zynqmp_disp_layer_set_format() API to fit
both live and non-live layer types.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c | 66 +-
 drivers/gpu/drm/xlnx/zynqmp_disp.h |  2 +-
 drivers/gpu/drm/xlnx/zynqmp_dp.c   | 13 +---
 drivers/gpu/drm/xlnx/zynqmp_kms.c  |  2 +-
 4 files changed, 55 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 0c2b3f4bffa6..a385d22d428e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -436,19 +436,28 @@ static void zynqmp_disp_avbuf_set_format(struct 
zynqmp_disp *disp,
 const struct zynqmp_disp_format *fmt)
 {
unsigned int i;
-   u32 val;
+   u32 val, reg;
 
-   val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
-   val &= zynqmp_disp_layer_is_video(layer)
-   ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
-   : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
-   val |= fmt->buf_fmt;
-   zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val);
+   layer->disp_fmt = fmt;
+   if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) {
+   reg = ZYNQMP_DISP_AV_BUF_FMT;
+   val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
+   val &= zynqmp_disp_layer_is_video(layer)
+   ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
+   : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
+   val |= fmt->buf_fmt;
+   } else {
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
+   : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+   val = fmt->buf_fmt;
+   }
+   zynqmp_disp_avbuf_write(disp, reg, val);
 
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) {
-   unsigned int reg = zynqmp_disp_layer_is_video(layer)
-? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
-: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
+   : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
 
zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
}
@@ -902,25 +911,33 @@ static void zynqmp_disp_audio_disable(struct zynqmp_disp 
*disp)
  */
 
 /**
- * zynqmp_disp_layer_find_format - Find format information for a DRM format
+ * zynqmp_disp_layer_find_format - Find format information for a DRM or media
+ * bus format
  * @layer: The layer
- * @drm_fmt: DRM format to search
+ * @drm_or_bus_format: DRM or media bus format
  *
  * Search display subsystem format information corresponding to the given DRM
- * format @drm_fmt for the @layer, and return a pointer to the format
- * descriptor.
+ * or media bus format @drm_or_bus_format for the @layer, and return a pointer
+ * to the format descriptor. Search key choice depends on @layer mode, for live
+ * layers search is done by zynqmp_disp_format.bus_fmt, and for non-live layers
+ * zynqmp_disp_format.drm_fmt is used.
  *
  * Return: A pointer to the format descriptor if found, NULL otherwise
  */
 static const struct zynqmp_disp_format *
 zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
- u32 drm_fmt)
+ u32 drm_or_bus_format)
 {
unsigned int i;
+   const struct zynqmp_disp_format *disp_format;
 
for (i = 0; i < layer->info->num_formats; i++) {
-   if (layer->info->formats[i].drm_fmt == drm_fmt)
-   return >info->formats[i];
+   disp_format = >info->formats[i];
+   if ((layer->mode == ZYNQMP_DPSUB_LAYER_LIVE &&
+disp_format->bus_fmt == drm_or_bus_format) ||
+   (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE &&
+disp_format->drm_fmt == drm_or_bus_format))
+   return disp_format;
}
 
return NULL;
@@ -992,20 +1009,25 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer 
*layer)
 /**
  * zynqmp_disp_layer_set_format - Set the layer format
  * @layer: The layer
- * @info: The format info
+ * @drm_or_bus_format: DRM or media bus format
  *
  * Set the format for @layer to @info. The layer must be disabled.
  */
 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
- const struct drm_format_info *info)
+ u32 drm_or_bus_format)
 {
unsigned int i;
 
-