Commit 3be0bf97 authored by Laurent Pinchart's avatar Laurent Pinchart

v4l: vsp1: Add support for multiple LIF instances

The VSP2-DL instance (present in the H3 ES2.0 and M3-N SoCs) has two LIF
instances. Adapt the driver infrastructure to support multiple LIFs.
Support for multiple display pipelines will be added separately.

The change to the entity routing table removes the ability to connect
the LIF output to the HGO or HGT histogram generators. This feature is
only available on Gen2 hardware, isn't supported by the rest of the
driver, and has no known use case, so this isn't an issue.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: default avatarKieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Acked-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent d455b45f
......@@ -41,11 +41,11 @@ struct vsp1_rwpf;
struct vsp1_sru;
struct vsp1_uds;
#define VSP1_MAX_LIF 2
#define VSP1_MAX_RPF 5
#define VSP1_MAX_UDS 3
#define VSP1_MAX_WPF 4
#define VSP1_HAS_LIF (1 << 0)
#define VSP1_HAS_LUT (1 << 1)
#define VSP1_HAS_SRU (1 << 2)
#define VSP1_HAS_BRU (1 << 3)
......@@ -61,6 +61,7 @@ struct vsp1_device_info {
const char *model;
unsigned int gen;
unsigned int features;
unsigned int lif_count;
unsigned int rpf_count;
unsigned int uds_count;
unsigned int wpf_count;
......@@ -84,7 +85,7 @@ struct vsp1_device {
struct vsp1_hgt *hgt;
struct vsp1_hsit *hsi;
struct vsp1_hsit *hst;
struct vsp1_lif *lif;
struct vsp1_lif *lif[VSP1_MAX_LIF];
struct vsp1_lut *lut;
struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
struct vsp1_sru *sru;
......
......@@ -181,7 +181,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
format.format.code);
format.pad = LIF_PAD_SINK;
ret = v4l2_subdev_call(&vsp1->lif->entity.subdev, pad, set_fmt, NULL,
ret = v4l2_subdev_call(&vsp1->lif[0]->entity.subdev, pad, set_fmt, NULL,
&format);
if (ret < 0)
return ret;
......@@ -599,15 +599,15 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
vsp1->bru->entity.sink = &vsp1->wpf[0]->entity;
vsp1->bru->entity.sink_pad = 0;
vsp1->wpf[0]->entity.sink = &vsp1->lif->entity;
vsp1->wpf[0]->entity.sink = &vsp1->lif[0]->entity;
vsp1->wpf[0]->entity.sink_pad = 0;
list_add_tail(&vsp1->bru->entity.list_pipe, &pipe->entities);
list_add_tail(&vsp1->wpf[0]->entity.list_pipe, &pipe->entities);
list_add_tail(&vsp1->lif->entity.list_pipe, &pipe->entities);
list_add_tail(&vsp1->lif[0]->entity.list_pipe, &pipe->entities);
pipe->bru = &vsp1->bru->entity;
pipe->lif = &vsp1->lif->entity;
pipe->lif = &vsp1->lif[0]->entity;
pipe->output = vsp1->wpf[0];
pipe->output->pipe = pipe;
pipe->frame_end = vsp1_du_pipeline_frame_end;
......
......@@ -168,10 +168,13 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
return ret;
}
if (vsp1->lif) {
ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
for (i = 0; i < vsp1->info->lif_count; ++i) {
if (!vsp1->lif[i])
continue;
ret = media_create_pad_link(&vsp1->wpf[i]->entity.subdev.entity,
RWPF_PAD_SOURCE,
&vsp1->lif->entity.subdev.entity,
&vsp1->lif[i]->entity.subdev.entity,
LIF_PAD_SINK, 0);
if (ret < 0)
return ret;
......@@ -334,18 +337,23 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
/*
* The LIF is only supported when used in conjunction with the DU, in
* The LIFs are only supported when used in conjunction with the DU, in
* which case the userspace API is disabled. If the userspace API is
* enabled skip the LIF, even when present.
* enabled skip the LIFs, even when present.
*/
if (vsp1->info->features & VSP1_HAS_LIF && !vsp1->info->uapi) {
vsp1->lif = vsp1_lif_create(vsp1);
if (IS_ERR(vsp1->lif)) {
ret = PTR_ERR(vsp1->lif);
goto done;
}
if (!vsp1->info->uapi) {
for (i = 0; i < vsp1->info->lif_count; ++i) {
struct vsp1_lif *lif;
lif = vsp1_lif_create(vsp1, i);
if (IS_ERR(lif)) {
ret = PTR_ERR(lif);
goto done;
}
list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities);
vsp1->lif[i] = lif;
list_add_tail(&lif->entity.list_dev, &vsp1->entities);
}
}
if (vsp1->info->features & VSP1_HAS_LUT) {
......@@ -638,8 +646,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
.model = "VSP1-D",
.gen = 2,
.features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LIF
| VSP1_HAS_LUT,
.features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LUT,
.lif_count = 1,
.rpf_count = 4,
.uds_count = 1,
.wpf_count = 1,
......@@ -672,8 +680,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPD_V2H,
.model = "VSP1V-D",
.gen = 2,
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
| VSP1_HAS_LIF,
.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT,
.lif_count = 1,
.rpf_count = 4,
.uds_count = 1,
.wpf_count = 1,
......@@ -721,7 +729,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
.model = "VSP2-D",
.gen = 3,
.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP,
.features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
.lif_count = 1,
.rpf_count = 5,
.wpf_count = 2,
.num_bru_inputs = 5,
......@@ -729,7 +738,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPD_V3,
.model = "VSP2-D",
.gen = 3,
.features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_LIF,
.features = VSP1_HAS_BRS | VSP1_HAS_BRU,
.lif_count = 1,
.rpf_count = 5,
.wpf_count = 1,
.num_bru_inputs = 5,
......@@ -737,7 +747,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
.model = "VSP2-DL",
.gen = 3,
.features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_LIF,
.features = VSP1_HAS_BRS | VSP1_HAS_BRU,
.lif_count = 2,
.rpf_count = 5,
.wpf_count = 2,
.num_bru_inputs = 5,
......
......@@ -468,7 +468,8 @@ static const struct vsp1_route vsp1_routes[] = {
{ VSP1_ENTITY_HGT, 0, 0, { 0, }, 0 },
VSP1_ENTITY_ROUTE(HSI),
VSP1_ENTITY_ROUTE(HST),
{ VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, }, VI6_DPR_NODE_LIF },
{ VSP1_ENTITY_LIF, 0, 0, { 0, }, 0 },
{ VSP1_ENTITY_LIF, 1, 0, { 0, }, 0 },
VSP1_ENTITY_ROUTE(LUT),
VSP1_ENTITY_ROUTE_RPF(0),
VSP1_ENTITY_ROUTE_RPF(1),
......
......@@ -30,7 +30,7 @@
static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
u32 reg, u32 data)
{
vsp1_dl_list_write(dl, reg, data);
vsp1_dl_list_write(dl, reg + lif->entity.index * VI6_LIF_OFFSET, data);
}
/* -----------------------------------------------------------------------------
......@@ -165,7 +165,7 @@ static const struct vsp1_entity_operations lif_entity_ops = {
* Initialization and Cleanup
*/
struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1, unsigned int index)
{
struct vsp1_lif *lif;
int ret;
......@@ -176,6 +176,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
lif->entity.ops = &lif_entity_ops;
lif->entity.type = VSP1_ENTITY_LIF;
lif->entity.index = index;
/*
* The LIF is never exposed to userspace, but media entity registration
......
......@@ -32,6 +32,6 @@ static inline struct vsp1_lif *to_lif(struct v4l2_subdev *subdev)
return container_of(subdev, struct vsp1_lif, entity.subdev);
}
struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1);
struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1, unsigned int index);
#endif /* __VSP1_LIF_H__ */
......@@ -351,7 +351,7 @@
#define VI6_DPR_NODE_HST 30
#define VI6_DPR_NODE_HSI 31
#define VI6_DPR_NODE_BRS_IN(n) (38 + (n))
#define VI6_DPR_NODE_LIF 55
#define VI6_DPR_NODE_LIF 55 /* Gen2 only */
#define VI6_DPR_NODE_WPF(n) (56 + (n))
#define VI6_DPR_NODE_UNUSED 63
......@@ -663,6 +663,8 @@
* LIF Control Registers
*/
#define VI6_LIF_OFFSET (-0x100)
#define VI6_LIF_CTRL 0x3b00
#define VI6_LIF_CTRL_OBTH_MASK (0x7ff << 16)
#define VI6_LIF_CTRL_OBTH_SHIFT 16
......
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