Commit 1b5151bd authored by Anatoliy Klymenko's avatar Anatoliy Klymenko Committed by Tomi Valkeinen

drm: xlnx: zynqmp_dpsub: Set input live format

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: default avatarAnatoliy Klymenko <anatoliy.klymenko@amd.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240416-dp-live-fmt-v4-6-c7f379b7168e@amd.com
parent 1836fd5e
...@@ -436,19 +436,29 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp, ...@@ -436,19 +436,29 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp,
const struct zynqmp_disp_format *fmt) const struct zynqmp_disp_format *fmt)
{ {
unsigned int i; unsigned int i;
u32 val; u32 val, reg;
val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT); layer->disp_fmt = fmt;
val &= zynqmp_disp_layer_is_video(layer) if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) {
? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK reg = ZYNQMP_DISP_AV_BUF_FMT;
: ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK; val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
val |= fmt->buf_fmt; val &= zynqmp_disp_layer_is_video(layer)
zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val); ? ~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, reg, val);
} 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++) { for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) {
unsigned int reg = zynqmp_disp_layer_is_video(layer) reg = zynqmp_disp_layer_is_video(layer)
? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i) ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i); : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]); zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
} }
...@@ -926,6 +936,31 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer, ...@@ -926,6 +936,31 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
return NULL; return NULL;
} }
/**
* zynqmp_disp_layer_find_live_format - Find format information for given
* media bus format
* @layer: The layer
* @drm_fmt: Media bus format to search
*
* Search display subsystem format information corresponding to the given media
* bus format @media_bus_format for the @layer, and return a pointer to the
* format descriptor.
*
* Return: A pointer to the format descriptor if found, NULL otherwise
*/
static const struct zynqmp_disp_format *
zynqmp_disp_layer_find_live_format(struct zynqmp_disp_layer *layer,
u32 media_bus_format)
{
unsigned int i;
for (i = 0; i < layer->info->num_formats; i++)
if (layer->info->formats[i].bus_fmt == media_bus_format)
return &layer->info->formats[i];
return NULL;
}
/** /**
* zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer * zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer
* @layer: The layer * @layer: The layer
...@@ -1040,6 +1075,9 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer) ...@@ -1040,6 +1075,9 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
* @layer: The layer * @layer: The layer
* @info: The format info * @info: The format info
* *
* NOTE: Use zynqmp_disp_layer_set_live_format() to set media bus format for
* live video layers.
*
* Set the format for @layer to @info. The layer must be disabled. * Set the format for @layer to @info. The layer must be disabled.
*/ */
void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
...@@ -1047,14 +1085,16 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, ...@@ -1047,14 +1085,16 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
{ {
unsigned int i; unsigned int i;
if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE))
return;
layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format);
if (WARN_ON(!layer->disp_fmt))
return;
layer->drm_fmt = info; layer->drm_fmt = info;
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
if (layer->mode == ZYNQMP_DPSUB_LAYER_LIVE)
return;
/* /*
* Set pconfig for each DMA channel to indicate they're part of a * Set pconfig for each DMA channel to indicate they're part of a
* video group. * video group.
...@@ -1074,6 +1114,32 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, ...@@ -1074,6 +1114,32 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
} }
} }
/**
* zynqmp_disp_layer_set_live_format - Set the live video layer format
* @layer: The layer
* @info: The format info
*
* NOTE: This function should not be used to set format for non-live video
* layer. Use zynqmp_disp_layer_set_format() instead.
*
* Set the display format for the live @layer. The layer must be disabled.
*/
void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
u32 media_bus_format)
{
if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE))
return;
layer->disp_fmt = zynqmp_disp_layer_find_live_format(layer,
media_bus_format);
if (WARN_ON(!layer->disp_fmt))
return;
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
layer->drm_fmt = drm_format_info(layer->disp_fmt->drm_fmt);
}
/** /**
* zynqmp_disp_layer_update - Update the layer framebuffer * zynqmp_disp_layer_update - Update the layer framebuffer
* @layer: The layer * @layer: The layer
......
...@@ -58,6 +58,8 @@ void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer); ...@@ -58,6 +58,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_disable(struct zynqmp_disp_layer *layer);
void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
const struct drm_format_info *info); const struct drm_format_info *info);
void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
u32 media_bus_format);
int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
struct drm_plane_state *state); struct drm_plane_state *state);
......
...@@ -1299,15 +1299,20 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, ...@@ -1299,15 +1299,20 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
struct drm_bridge_state *old_bridge_state) struct drm_bridge_state *old_bridge_state)
{ {
struct zynqmp_disp_layer *layer; struct zynqmp_disp_layer *layer;
const struct drm_format_info *info; struct drm_bridge_state *bridge_state;
u32 bus_fmt;
layer = zynqmp_dp_disp_connected_live_layer(dp); layer = zynqmp_dp_disp_connected_live_layer(dp);
if (!layer) if (!layer)
return; return;
/* TODO: Make the format configurable. */ bridge_state = drm_atomic_get_new_bridge_state(old_bridge_state->base.state,
info = drm_format_info(DRM_FORMAT_YUV422); old_bridge_state->bridge);
zynqmp_disp_layer_set_format(layer, info); if (WARN_ON(!bridge_state))
return;
bus_fmt = bridge_state->input_bus_cfg.format;
zynqmp_disp_layer_set_live_format(layer, bus_fmt);
zynqmp_disp_layer_enable(layer); zynqmp_disp_layer_enable(layer);
if (layer == dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]) if (layer == dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX])
......
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