[media] v4l: vsp1: Configure device based on IP version

The IP version number carries enough information to identify the exact
device instance features. Drop the related DT properties and use the IP
version instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Laurent Pinchart 2015-12-05 20:17:10 -02:00 committed by Mauro Carvalho Chehab
parent 1517b03923
commit 5aa2eb3c86
11 changed files with 117 additions and 118 deletions

View File

@ -14,21 +14,6 @@ Required properties:
- interrupts: VSP interrupt specifier.
- clocks: A phandle + clock-specifier pair for the VSP functional clock.
- renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP.
- renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP.
Optional properties:
- renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP. Defaults
to 0 if not present.
- renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is
available.
- renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is
available.
- renesas,has-sru: Boolean, indicates that the Super Resolution Unit (SRU)
module is available.
Example: R8A7790 (R-Car H2) VSP1-S node
@ -37,10 +22,4 @@ Example: R8A7790 (R-Car H2) VSP1-S node
reg = <0 0xfe928000 0 0x8000>;
interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>;
renesas,has-lut;
renesas,has-sru;
renesas,#rpf = <5>;
renesas,#uds = <3>;
renesas,#wpf = <4>;
};

View File

@ -47,7 +47,8 @@ struct vsp1_uds;
#define VSP1_HAS_SRU (1 << 2)
#define VSP1_HAS_BRU (1 << 3)
struct vsp1_platform_data {
struct vsp1_device_info {
u32 version;
unsigned int features;
unsigned int rpf_count;
unsigned int uds_count;
@ -58,7 +59,7 @@ struct vsp1_platform_data {
struct vsp1_device {
struct device *dev;
struct vsp1_platform_data pdata;
const struct vsp1_device_info *info;
void __iomem *mmio;
struct clk *clock;

View File

@ -416,7 +416,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
bru->entity.type = VSP1_ENTITY_BRU;
ret = vsp1_entity_init(vsp1, &bru->entity,
vsp1->pdata.num_bru_inputs + 1);
vsp1->info->num_bru_inputs + 1);
if (ret < 0)
return ERR_PTR(ret);

View File

@ -285,7 +285,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
unsigned long flags;
int ret;
if (rpf_index >= vsp1->pdata.rpf_count)
if (rpf_index >= vsp1->info->rpf_count)
return -EINVAL;
rpf = vsp1->rpf[rpf_index];
@ -519,7 +519,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
if (!vsp1->bru || !vsp1->lif)
return -ENXIO;
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
struct vsp1_rwpf *rpf = vsp1->rpf[i];
ret = media_create_pad_link(&rpf->entity.subdev.entity,
@ -572,7 +572,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
pipe->frame_end = vsp1_drm_pipeline_frame_end;
/* The DRM pipeline is static, add entities manually. */
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
struct vsp1_rwpf *input = vsp1->rpf[i];
list_add_tail(&input->entity.list_pipe, &pipe->entities);

View File

@ -47,7 +47,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
unsigned int i;
u32 status;
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
struct vsp1_rwpf *wpf = vsp1->wpf[i];
struct vsp1_pipeline *pipe;
@ -153,7 +153,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
return ret;
}
if (vsp1->pdata.features & VSP1_HAS_LIF) {
if (vsp1->info->features & VSP1_HAS_LIF) {
ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
RWPF_PAD_SOURCE,
&vsp1->lif->entity.subdev.entity,
@ -162,7 +162,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
return ret;
}
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
struct vsp1_rwpf *rpf = vsp1->rpf[i];
ret = media_create_pad_link(&rpf->video->video.entity, 0,
@ -174,7 +174,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
return ret;
}
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
/* Connect the video device to the WPF. All connections are
* immutable except for the WPF0 source link if a LIF is
* present.
@ -182,7 +182,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
struct vsp1_rwpf *wpf = vsp1->wpf[i];
unsigned int flags = MEDIA_LNK_FL_ENABLED;
if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0)
if (!(vsp1->info->features & VSP1_HAS_LIF) || i != 0)
flags |= MEDIA_LNK_FL_IMMUTABLE;
ret = media_create_pad_link(&wpf->entity.subdev.entity,
@ -215,7 +215,7 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1)
media_device_unregister(&vsp1->media_dev);
media_device_cleanup(&vsp1->media_dev);
if (!vsp1->pdata.uapi)
if (!vsp1->info->uapi)
vsp1_drm_cleanup(vsp1);
}
@ -238,7 +238,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
* the pipeline is configured internally by the driver in that case, and
* its configuration can thus be trusted.
*/
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
vsp1->media_ops.link_validate = v4l2_subdev_link_validate;
vdev->mdev = mdev;
@ -250,7 +250,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
/* Instantiate all the entities. */
if (vsp1->pdata.features & VSP1_HAS_BRU) {
if (vsp1->info->features & VSP1_HAS_BRU) {
vsp1->bru = vsp1_bru_create(vsp1);
if (IS_ERR(vsp1->bru)) {
ret = PTR_ERR(vsp1->bru);
@ -276,7 +276,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
if (vsp1->pdata.features & VSP1_HAS_LIF) {
if (vsp1->info->features & VSP1_HAS_LIF) {
vsp1->lif = vsp1_lif_create(vsp1);
if (IS_ERR(vsp1->lif)) {
ret = PTR_ERR(vsp1->lif);
@ -286,7 +286,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities);
}
if (vsp1->pdata.features & VSP1_HAS_LUT) {
if (vsp1->info->features & VSP1_HAS_LUT) {
vsp1->lut = vsp1_lut_create(vsp1);
if (IS_ERR(vsp1->lut)) {
ret = PTR_ERR(vsp1->lut);
@ -296,7 +296,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities);
}
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
struct vsp1_rwpf *rpf;
rpf = vsp1_rpf_create(vsp1, i);
@ -308,7 +308,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
vsp1->rpf[i] = rpf;
list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
if (vsp1->pdata.uapi) {
if (vsp1->info->uapi) {
struct vsp1_video *video = vsp1_video_create(vsp1, rpf);
if (IS_ERR(video)) {
@ -320,7 +320,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
}
if (vsp1->pdata.features & VSP1_HAS_SRU) {
if (vsp1->info->features & VSP1_HAS_SRU) {
vsp1->sru = vsp1_sru_create(vsp1);
if (IS_ERR(vsp1->sru)) {
ret = PTR_ERR(vsp1->sru);
@ -330,7 +330,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities);
}
for (i = 0; i < vsp1->pdata.uds_count; ++i) {
for (i = 0; i < vsp1->info->uds_count; ++i) {
struct vsp1_uds *uds;
uds = vsp1_uds_create(vsp1, i);
@ -343,7 +343,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
list_add_tail(&uds->entity.list_dev, &vsp1->entities);
}
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
struct vsp1_rwpf *wpf;
wpf = vsp1_wpf_create(vsp1, i);
@ -355,7 +355,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
vsp1->wpf[i] = wpf;
list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
if (vsp1->pdata.uapi) {
if (vsp1->info->uapi) {
struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
if (IS_ERR(video)) {
@ -377,7 +377,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
/* Create links. */
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
ret = vsp1_uapi_create_links(vsp1);
else
ret = vsp1_drm_create_links(vsp1);
@ -387,7 +387,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
/* Register subdev nodes if the userspace API is enabled or initialize
* the DRM pipeline otherwise.
*/
if (vsp1->pdata.uapi) {
if (vsp1->info->uapi) {
vsp1->use_dl = false;
ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
} else {
@ -438,7 +438,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
int ret;
/* Reset any channel that might be running. */
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
ret = vsp1_reset_wpf(vsp1, i);
if (ret < 0)
return ret;
@ -447,10 +447,10 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) |
(8 << VI6_CLK_DCSWT_CSTRW_SHIFT));
for (i = 0; i < vsp1->pdata.rpf_count; ++i)
for (i = 0; i < vsp1->info->rpf_count; ++i)
vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED);
for (i = 0; i < vsp1->pdata.uds_count; ++i)
for (i = 0; i < vsp1->info->uds_count; ++i)
vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED);
@ -567,52 +567,75 @@ static const struct dev_pm_ops vsp1_pm_ops = {
* Platform Driver
*/
static int vsp1_parse_dt(struct vsp1_device *vsp1)
{
struct device_node *np = vsp1->dev->of_node;
struct vsp1_platform_data *pdata = &vsp1->pdata;
if (of_property_read_bool(np, "renesas,has-lif"))
pdata->features |= VSP1_HAS_LIF;
if (of_property_read_bool(np, "renesas,has-lut"))
pdata->features |= VSP1_HAS_LUT;
if (of_property_read_bool(np, "renesas,has-sru"))
pdata->features |= VSP1_HAS_SRU;
of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count);
of_property_read_u32(np, "renesas,#uds", &pdata->uds_count);
of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count);
if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) {
dev_err(vsp1->dev, "invalid number of RPF (%u)\n",
pdata->rpf_count);
return -EINVAL;
}
if (pdata->uds_count > VSP1_MAX_UDS) {
dev_err(vsp1->dev, "invalid number of UDS (%u)\n",
pdata->uds_count);
return -EINVAL;
}
if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) {
dev_err(vsp1->dev, "invalid number of WPF (%u)\n",
pdata->wpf_count);
return -EINVAL;
}
pdata->features |= VSP1_HAS_BRU;
pdata->num_bru_inputs = 4;
pdata->uapi = true;
return 0;
}
static const struct vsp1_device_info vsp1_device_infos[] = {
{
.version = VI6_IP_VERSION_MODEL_VSPS_H2,
.features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
.rpf_count = 5,
.uds_count = 3,
.wpf_count = 4,
.num_bru_inputs = 4,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPR_H2,
.features = VSP1_HAS_BRU | VSP1_HAS_SRU,
.rpf_count = 5,
.uds_count = 1,
.wpf_count = 4,
.num_bru_inputs = 4,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT,
.rpf_count = 4,
.uds_count = 1,
.wpf_count = 4,
.num_bru_inputs = 4,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPS_M2,
.features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
.rpf_count = 5,
.uds_count = 3,
.wpf_count = 4,
.num_bru_inputs = 4,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
.features = VSP1_HAS_LUT | VSP1_HAS_SRU,
.rpf_count = 1,
.uds_count = 1,
.wpf_count = 1,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
.features = VSP1_HAS_BRU,
.rpf_count = 5,
.wpf_count = 1,
.num_bru_inputs = 5,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
.features = VSP1_HAS_BRU | VSP1_HAS_LUT,
.rpf_count = 5,
.wpf_count = 1,
.num_bru_inputs = 5,
.uapi = true,
}, {
.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT,
.rpf_count = 5,
.wpf_count = 2,
.num_bru_inputs = 5,
},
};
static int vsp1_probe(struct platform_device *pdev)
{
struct vsp1_device *vsp1;
struct resource *irq;
struct resource *io;
unsigned int i;
u32 version;
int ret;
@ -625,10 +648,6 @@ static int vsp1_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&vsp1->entities);
INIT_LIST_HEAD(&vsp1->videos);
ret = vsp1_parse_dt(vsp1);
if (ret < 0)
return ret;
/* I/O, IRQ and clock resources */
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
@ -662,21 +681,21 @@ static int vsp1_probe(struct platform_device *pdev)
version = vsp1_read(vsp1, VI6_IP_VERSION);
clk_disable_unprepare(vsp1->clock);
dev_dbg(&pdev->dev, "IP version 0x%08x\n", version);
switch (version & VI6_IP_VERSION_MODEL_MASK) {
case VI6_IP_VERSION_MODEL_VSPD_GEN3:
vsp1->pdata.num_bru_inputs = 5;
vsp1->pdata.uapi = false;
break;
case VI6_IP_VERSION_MODEL_VSPI_GEN3:
case VI6_IP_VERSION_MODEL_VSPBD_GEN3:
case VI6_IP_VERSION_MODEL_VSPBC_GEN3:
vsp1->pdata.features &= ~VSP1_HAS_BRU;
break;
for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
if ((version & VI6_IP_VERSION_MODEL_MASK) ==
vsp1_device_infos[i].version) {
vsp1->info = &vsp1_device_infos[i];
break;
}
}
if (!vsp1->info) {
dev_err(&pdev->dev, "unsupported IP version 0x%08x\n", version);
return -ENXIO;
}
dev_dbg(&pdev->dev, "IP version 0x%08x\n", version);
/* Instanciate entities */
ret = vsp1_create_entities(vsp1);
if (ret < 0) {

View File

@ -45,7 +45,7 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
if (!streaming)
return 0;
if (!entity->vsp1->pdata.uapi || !entity->subdev.ctrl_handler)
if (!entity->vsp1->info->uapi || !entity->subdev.ctrl_handler)
return 0;
ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);

View File

@ -368,7 +368,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
* pipelines twice, first to set them all to the stopping state, and
* then to wait for the stop to complete.
*/
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
struct vsp1_rwpf *wpf = vsp1->wpf[i];
struct vsp1_pipeline *pipe;
@ -385,7 +385,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
spin_unlock_irqrestore(&pipe->irqlock, flags);
}
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
struct vsp1_rwpf *wpf = vsp1->wpf[i];
struct vsp1_pipeline *pipe;
@ -409,7 +409,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
unsigned int i;
/* Resume pipeline all running pipelines. */
for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
for (i = 0; i < vsp1->info->wpf_count; ++i) {
struct vsp1_rwpf *wpf = vsp1->wpf[i];
struct vsp1_pipeline *pipe;

View File

@ -151,12 +151,12 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
(fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
: VI6_RPF_ALPH_SEL_ASEL_FIXED));
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
mutex_lock(rpf->ctrls.lock);
vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val);
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
mutex_unlock(rpf->ctrls.lock);
vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);

View File

@ -151,12 +151,12 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
/* Take the control handler lock to ensure that the CTRL0 value won't be
* changed behind our back by a set control operation.
*/
if (sru->entity.vsp1->pdata.uapi)
if (sru->entity.vsp1->info->uapi)
mutex_lock(sru->ctrls.lock);
ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
& (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0);
if (sru->entity.vsp1->pdata.uapi)
if (sru->entity.vsp1->info->uapi)
mutex_unlock(sru->ctrls.lock);
vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);

View File

@ -324,7 +324,7 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
/* Follow links downstream for each input and make sure the graph
* contains no loop and that all branches end at the output WPF.
*/
for (i = 0; i < video->vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < video->vsp1->info->rpf_count; ++i) {
if (!pipe->inputs[i])
continue;
@ -456,7 +456,7 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
unsigned int i;
/* Complete buffers on all video nodes. */
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
if (!pipe->inputs[i])
continue;

View File

@ -98,7 +98,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
* inputs as sub-layers and select the virtual RPF as the master
* layer.
*/
for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
for (i = 0; i < vsp1->info->rpf_count; ++i) {
struct vsp1_rwpf *input = pipe->inputs[i];
if (!input)
@ -155,11 +155,11 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
/* Take the control handler lock to ensure that the PDV value won't be
* changed behind our back by a set control operation.
*/
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
mutex_lock(wpf->ctrls.lock);
outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT;
vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
if (vsp1->pdata.uapi)
if (vsp1->info->uapi)
mutex_unlock(wpf->ctrls.lock);
vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index),