Skip to content

Commit 1b5151b

Browse files
Anatoliy Klymenkotomba
authored andcommitted
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: Anatoliy Klymenko <[email protected]> Reviewed-by: Tomi Valkeinen <[email protected]> Signed-off-by: Tomi Valkeinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 1836fd5 commit 1b5151b

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

drivers/gpu/drm/xlnx/zynqmp_disp.c

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -436,19 +436,29 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp,
436436
const struct zynqmp_disp_format *fmt)
437437
{
438438
unsigned int i;
439-
u32 val;
439+
u32 val, reg;
440440

441-
val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
442-
val &= zynqmp_disp_layer_is_video(layer)
443-
? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
444-
: ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
445-
val |= fmt->buf_fmt;
446-
zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val);
441+
layer->disp_fmt = fmt;
442+
if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE) {
443+
reg = ZYNQMP_DISP_AV_BUF_FMT;
444+
val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
445+
val &= zynqmp_disp_layer_is_video(layer)
446+
? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
447+
: ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
448+
val |= fmt->buf_fmt;
449+
zynqmp_disp_avbuf_write(disp, reg, val);
450+
} else {
451+
reg = zynqmp_disp_layer_is_video(layer)
452+
? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
453+
: ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
454+
val = fmt->buf_fmt;
455+
zynqmp_disp_avbuf_write(disp, reg, val);
456+
}
447457

448458
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) {
449-
unsigned int reg = zynqmp_disp_layer_is_video(layer)
450-
? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
451-
: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
459+
reg = zynqmp_disp_layer_is_video(layer)
460+
? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
461+
: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
452462

453463
zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
454464
}
@@ -926,6 +936,31 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
926936
return NULL;
927937
}
928938

939+
/**
940+
* zynqmp_disp_layer_find_live_format - Find format information for given
941+
* media bus format
942+
* @layer: The layer
943+
* @drm_fmt: Media bus format to search
944+
*
945+
* Search display subsystem format information corresponding to the given media
946+
* bus format @media_bus_format for the @layer, and return a pointer to the
947+
* format descriptor.
948+
*
949+
* Return: A pointer to the format descriptor if found, NULL otherwise
950+
*/
951+
static const struct zynqmp_disp_format *
952+
zynqmp_disp_layer_find_live_format(struct zynqmp_disp_layer *layer,
953+
u32 media_bus_format)
954+
{
955+
unsigned int i;
956+
957+
for (i = 0; i < layer->info->num_formats; i++)
958+
if (layer->info->formats[i].bus_fmt == media_bus_format)
959+
return &layer->info->formats[i];
960+
961+
return NULL;
962+
}
963+
929964
/**
930965
* zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer
931966
* @layer: The layer
@@ -1040,21 +1075,26 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
10401075
* @layer: The layer
10411076
* @info: The format info
10421077
*
1078+
* NOTE: Use zynqmp_disp_layer_set_live_format() to set media bus format for
1079+
* live video layers.
1080+
*
10431081
* Set the format for @layer to @info. The layer must be disabled.
10441082
*/
10451083
void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
10461084
const struct drm_format_info *info)
10471085
{
10481086
unsigned int i;
10491087

1088+
if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_NONLIVE))
1089+
return;
1090+
10501091
layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format);
1092+
if (WARN_ON(!layer->disp_fmt))
1093+
return;
10511094
layer->drm_fmt = info;
10521095

10531096
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
10541097

1055-
if (layer->mode == ZYNQMP_DPSUB_LAYER_LIVE)
1056-
return;
1057-
10581098
/*
10591099
* Set pconfig for each DMA channel to indicate they're part of a
10601100
* video group.
@@ -1074,6 +1114,32 @@ void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
10741114
}
10751115
}
10761116

1117+
/**
1118+
* zynqmp_disp_layer_set_live_format - Set the live video layer format
1119+
* @layer: The layer
1120+
* @info: The format info
1121+
*
1122+
* NOTE: This function should not be used to set format for non-live video
1123+
* layer. Use zynqmp_disp_layer_set_format() instead.
1124+
*
1125+
* Set the display format for the live @layer. The layer must be disabled.
1126+
*/
1127+
void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
1128+
u32 media_bus_format)
1129+
{
1130+
if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE))
1131+
return;
1132+
1133+
layer->disp_fmt = zynqmp_disp_layer_find_live_format(layer,
1134+
media_bus_format);
1135+
if (WARN_ON(!layer->disp_fmt))
1136+
return;
1137+
1138+
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
1139+
1140+
layer->drm_fmt = drm_format_info(layer->disp_fmt->drm_fmt);
1141+
}
1142+
10771143
/**
10781144
* zynqmp_disp_layer_update - Update the layer framebuffer
10791145
* @layer: The layer

drivers/gpu/drm/xlnx/zynqmp_disp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer);
5858
void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
5959
void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
6060
const struct drm_format_info *info);
61+
void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
62+
u32 media_bus_format);
6163
int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
6264
struct drm_plane_state *state);
6365

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,15 +1299,20 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
12991299
struct drm_bridge_state *old_bridge_state)
13001300
{
13011301
struct zynqmp_disp_layer *layer;
1302-
const struct drm_format_info *info;
1302+
struct drm_bridge_state *bridge_state;
1303+
u32 bus_fmt;
13031304

13041305
layer = zynqmp_dp_disp_connected_live_layer(dp);
13051306
if (!layer)
13061307
return;
13071308

1308-
/* TODO: Make the format configurable. */
1309-
info = drm_format_info(DRM_FORMAT_YUV422);
1310-
zynqmp_disp_layer_set_format(layer, info);
1309+
bridge_state = drm_atomic_get_new_bridge_state(old_bridge_state->base.state,
1310+
old_bridge_state->bridge);
1311+
if (WARN_ON(!bridge_state))
1312+
return;
1313+
1314+
bus_fmt = bridge_state->input_bus_cfg.format;
1315+
zynqmp_disp_layer_set_live_format(layer, bus_fmt);
13111316
zynqmp_disp_layer_enable(layer);
13121317

13131318
if (layer == dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX])

0 commit comments

Comments
 (0)