Skip to content

Commit b0f0469

Browse files
Anatoliy Klymenkotomba
authored andcommitted
drm: xlnx: zynqmp_dpsub: Anounce supported input formats
DPSUB in bridge mode supports multiple input media bus formats. Announce the list of supported input media bus formats via drm_bridge.atomic_get_input_bus_fmts callback. Introduce a set of live input formats supported by DPSUB. Add safeguards to format list functions to prevent their misuse in the different layer modes contexts. Reviewed-by: Laurent Pinchart <[email protected]> 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 2e03666 commit b0f0469

File tree

3 files changed

+139
-4
lines changed

3 files changed

+139
-4
lines changed

drivers/gpu/drm/xlnx/zynqmp_disp.c

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/dma/xilinx_dpdma.h>
1919
#include <linux/dma-mapping.h>
2020
#include <linux/dmaengine.h>
21+
#include <linux/media-bus-format.h>
2122
#include <linux/module.h>
2223
#include <linux/of.h>
2324
#include <linux/platform_device.h>
@@ -77,12 +78,14 @@ enum zynqmp_dpsub_layer_mode {
7778
/**
7879
* struct zynqmp_disp_format - Display subsystem format information
7980
* @drm_fmt: DRM format (4CC)
81+
* @bus_fmt: Media bus format
8082
* @buf_fmt: AV buffer format
8183
* @swap: Flag to swap R & B for RGB formats, and U & V for YUV formats
8284
* @sf: Scaling factors for color components
8385
*/
8486
struct zynqmp_disp_format {
8587
u32 drm_fmt;
88+
u32 bus_fmt;
8689
u32 buf_fmt;
8790
bool swap;
8891
const u32 *sf;
@@ -182,6 +185,12 @@ static const u32 scaling_factors_565[] = {
182185
ZYNQMP_DISP_AV_BUF_5BIT_SF,
183186
};
184187

188+
static const u32 scaling_factors_666[] = {
189+
ZYNQMP_DISP_AV_BUF_6BIT_SF,
190+
ZYNQMP_DISP_AV_BUF_6BIT_SF,
191+
ZYNQMP_DISP_AV_BUF_6BIT_SF,
192+
};
193+
185194
static const u32 scaling_factors_888[] = {
186195
ZYNQMP_DISP_AV_BUF_8BIT_SF,
187196
ZYNQMP_DISP_AV_BUF_8BIT_SF,
@@ -364,6 +373,41 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = {
364373
},
365374
};
366375

376+
/* List of live video layer formats */
377+
static const struct zynqmp_disp_format avbuf_live_fmts[] = {
378+
{
379+
.drm_fmt = DRM_FORMAT_RGB565,
380+
.bus_fmt = MEDIA_BUS_FMT_RGB666_1X18,
381+
.buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 |
382+
ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
383+
.sf = scaling_factors_666,
384+
}, {
385+
.drm_fmt = DRM_FORMAT_RGB888,
386+
.bus_fmt = MEDIA_BUS_FMT_RGB888_1X24,
387+
.buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
388+
ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
389+
.sf = scaling_factors_888,
390+
}, {
391+
.drm_fmt = DRM_FORMAT_YUV422,
392+
.bus_fmt = MEDIA_BUS_FMT_UYVY8_1X16,
393+
.buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
394+
ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
395+
.sf = scaling_factors_888,
396+
}, {
397+
.drm_fmt = DRM_FORMAT_YUV444,
398+
.bus_fmt = MEDIA_BUS_FMT_VUY8_1X24,
399+
.buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
400+
ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
401+
.sf = scaling_factors_888,
402+
}, {
403+
.drm_fmt = DRM_FORMAT_P210,
404+
.bus_fmt = MEDIA_BUS_FMT_UYVY10_1X20,
405+
.buf_fmt = ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 |
406+
ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
407+
.sf = scaling_factors_101010,
408+
},
409+
};
410+
367411
static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
368412
{
369413
return readl(disp->avbuf.base + reg);
@@ -887,6 +931,11 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
887931
* @layer: The layer
888932
* @num_formats: Pointer to the returned number of formats
889933
*
934+
* NOTE: This function doesn't make sense for live video layers and will
935+
* always return an empty list in such cases. zynqmp_disp_live_layer_formats()
936+
* should be used to query a list of media bus formats supported by the live
937+
* video input layer.
938+
*
890939
* Return: A newly allocated u32 array that stores all the DRM formats
891940
* supported by the layer. The number of formats in the array is returned
892941
* through the num_formats argument.
@@ -897,10 +946,17 @@ u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
897946
unsigned int i;
898947
u32 *formats;
899948

949+
if (WARN_ON(!layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE)) {
950+
*num_formats = 0;
951+
return NULL;
952+
}
953+
900954
formats = kcalloc(layer->info->num_formats, sizeof(*formats),
901955
GFP_KERNEL);
902-
if (!formats)
956+
if (!formats) {
957+
*num_formats = 0;
903958
return NULL;
959+
}
904960

905961
for (i = 0; i < layer->info->num_formats; ++i)
906962
formats[i] = layer->info->formats[i].drm_fmt;
@@ -909,6 +965,43 @@ u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
909965
return formats;
910966
}
911967

968+
/**
969+
* zynqmp_disp_live_layer_formats - Return the media bus formats supported by
970+
* the live video layer
971+
* @layer: The layer
972+
* @num_formats: Pointer to the returned number of formats
973+
*
974+
* NOTE: This function should be used only for live video input layers.
975+
*
976+
* Return: A newly allocated u32 array of media bus formats supported by the
977+
* layer. The number of formats in the array is returned through the
978+
* @num_formats argument.
979+
*/
980+
u32 *zynqmp_disp_live_layer_formats(struct zynqmp_disp_layer *layer,
981+
unsigned int *num_formats)
982+
{
983+
unsigned int i;
984+
u32 *formats;
985+
986+
if (WARN_ON(layer->mode != ZYNQMP_DPSUB_LAYER_LIVE)) {
987+
*num_formats = 0;
988+
return NULL;
989+
}
990+
991+
formats = kcalloc(layer->info->num_formats, sizeof(*formats),
992+
GFP_KERNEL);
993+
if (!formats) {
994+
*num_formats = 0;
995+
return NULL;
996+
}
997+
998+
for (i = 0; i < layer->info->num_formats; ++i)
999+
formats[i] = layer->info->formats[i].bus_fmt;
1000+
1001+
*num_formats = layer->info->num_formats;
1002+
return formats;
1003+
}
1004+
9121005
/**
9131006
* zynqmp_disp_layer_enable - Enable a layer
9141007
* @layer: The layer
@@ -1131,6 +1224,11 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
11311224
.num_channels = 1,
11321225
},
11331226
};
1227+
static const struct zynqmp_disp_layer_info live_layer_info = {
1228+
.formats = avbuf_live_fmts,
1229+
.num_formats = ARRAY_SIZE(avbuf_live_fmts),
1230+
.num_channels = 0,
1231+
};
11341232

11351233
unsigned int i;
11361234
int ret;
@@ -1140,13 +1238,17 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
11401238

11411239
layer->id = i;
11421240
layer->disp = disp;
1143-
layer->info = &layer_info[i];
11441241
/*
11451242
* For now assume dpsub works in either live or non-live mode for both layers.
11461243
* Hybrid mode is not supported yet.
11471244
*/
1148-
layer->mode = disp->dpsub->dma_enabled ? ZYNQMP_DPSUB_LAYER_NONLIVE
1149-
: ZYNQMP_DPSUB_LAYER_LIVE;
1245+
if (disp->dpsub->dma_enabled) {
1246+
layer->mode = ZYNQMP_DPSUB_LAYER_NONLIVE;
1247+
layer->info = &layer_info[i];
1248+
} else {
1249+
layer->mode = ZYNQMP_DPSUB_LAYER_LIVE;
1250+
layer->info = &live_layer_info;
1251+
}
11501252

11511253
ret = zynqmp_disp_layer_request_dma(disp, layer);
11521254
if (ret)

drivers/gpu/drm/xlnx/zynqmp_disp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
5252

5353
u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
5454
unsigned int *num_formats);
55+
u32 *zynqmp_disp_live_layer_formats(struct zynqmp_disp_layer *layer,
56+
unsigned int *num_formats);
5557
void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer);
5658
void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
5759
void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/delay.h>
2323
#include <linux/device.h>
2424
#include <linux/io.h>
25+
#include <linux/media-bus-format.h>
2526
#include <linux/module.h>
2627
#include <linux/platform_device.h>
2728
#include <linux/pm_runtime.h>
@@ -1577,6 +1578,35 @@ static const struct drm_edid *zynqmp_dp_bridge_edid_read(struct drm_bridge *brid
15771578
return drm_edid_read_ddc(connector, &dp->aux.ddc);
15781579
}
15791580

1581+
static u32 *zynqmp_dp_bridge_default_bus_fmts(unsigned int *num_input_fmts)
1582+
{
1583+
u32 *formats = kzalloc(sizeof(*formats), GFP_KERNEL);
1584+
1585+
if (formats)
1586+
*formats = MEDIA_BUS_FMT_FIXED;
1587+
*num_input_fmts = !!formats;
1588+
1589+
return formats;
1590+
}
1591+
1592+
static u32 *
1593+
zynqmp_dp_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
1594+
struct drm_bridge_state *bridge_state,
1595+
struct drm_crtc_state *crtc_state,
1596+
struct drm_connector_state *conn_state,
1597+
u32 output_fmt,
1598+
unsigned int *num_input_fmts)
1599+
{
1600+
struct zynqmp_dp *dp = bridge_to_dp(bridge);
1601+
struct zynqmp_disp_layer *layer;
1602+
1603+
layer = zynqmp_dp_disp_connected_live_layer(dp);
1604+
if (layer)
1605+
return zynqmp_disp_live_layer_formats(layer, num_input_fmts);
1606+
else
1607+
return zynqmp_dp_bridge_default_bus_fmts(num_input_fmts);
1608+
}
1609+
15801610
static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = {
15811611
.attach = zynqmp_dp_bridge_attach,
15821612
.detach = zynqmp_dp_bridge_detach,
@@ -1589,6 +1619,7 @@ static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = {
15891619
.atomic_check = zynqmp_dp_bridge_atomic_check,
15901620
.detect = zynqmp_dp_bridge_detect,
15911621
.edid_read = zynqmp_dp_bridge_edid_read,
1622+
.atomic_get_input_bus_fmts = zynqmp_dp_bridge_get_input_bus_fmts,
15921623
};
15931624

15941625
/* -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)