aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/imx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/imx')
-rw-r--r--drivers/staging/media/imx/Kconfig4
-rw-r--r--drivers/staging/media/imx/imx-ic-common.c4
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c18
-rw-r--r--drivers/staging/media/imx/imx-media-dev-common.c4
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c28
-rw-r--r--drivers/staging/media/imx/imx-media-internal-sd.c32
-rw-r--r--drivers/staging/media/imx/imx-media-of.c73
-rw-r--r--drivers/staging/media/imx/imx-media-vdic.c12
-rw-r--r--drivers/staging/media/imx/imx-media.h7
-rw-r--r--drivers/staging/media/imx/imx7-media-csi.c6
-rw-r--r--drivers/staging/media/imx/imx7-mipi-csis.c26
11 files changed, 111 insertions, 103 deletions
diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig
index 6c8b69491ef0..4c726345dc25 100644
--- a/drivers/staging/media/imx/Kconfig
+++ b/drivers/staging/media/imx/Kconfig
@@ -7,7 +7,7 @@ config VIDEO_IMX_MEDIA
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
- ---help---
+ help
Say yes here to enable support for video4linux media controller
driver for the i.MX5/6 SOC.
@@ -18,7 +18,7 @@ config VIDEO_IMX_CSI
tristate "i.MX5/6 Camera Sensor Interface driver"
depends on VIDEO_IMX_MEDIA && VIDEO_DEV && I2C
default y
- ---help---
+ help
A video4linux camera sensor interface driver for i.MX5/6.
config VIDEO_IMX7_CSI
diff --git a/drivers/staging/media/imx/imx-ic-common.c b/drivers/staging/media/imx/imx-ic-common.c
index 7e2455097315..18cd4cb92431 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -22,7 +22,7 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
static int imx_ic_probe(struct platform_device *pdev)
{
- struct imx_media_internal_sd_platformdata *pdata;
+ struct imx_media_ipu_internal_sd_pdata *pdata;
struct imx_ic_priv *priv;
int ret;
@@ -59,7 +59,7 @@ static int imx_ic_probe(struct platform_device *pdev)
priv->sd.owner = THIS_MODULE;
priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
priv->sd.grp_id = pdata->grp_id;
- strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
+ strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
ret = ic_ops[priv->task_id]->init(priv);
if (ret)
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index edc0e9a2a90d..28fe66052cc7 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -150,9 +150,10 @@ static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep,
/*
* Parses the fwnode endpoint from the source pad of the entity
* connected to this CSI. This will either be the entity directly
- * upstream from the CSI-2 receiver, or directly upstream from the
- * video mux. The endpoint is needed to determine the bus type and
- * bus config coming into the CSI.
+ * upstream from the CSI-2 receiver, directly upstream from the
+ * video mux, or directly upstream from the CSI itself. The endpoint
+ * is needed to determine the bus type and bus config coming into
+ * the CSI.
*/
static int csi_get_upstream_endpoint(struct csi_priv *priv,
struct v4l2_fwnode_endpoint *ep)
@@ -168,7 +169,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
if (!priv->src_sd)
return -EPIPE;
- src = &priv->src_sd->entity;
+ sd = priv->src_sd;
+ src = &sd->entity;
if (src->function == MEDIA_ENT_F_VID_MUX) {
/*
@@ -182,6 +184,14 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
src = &sd->entity;
}
+ /*
+ * If the source is neither the video mux nor the CSI-2 receiver,
+ * get the source pad directly upstream from CSI itself.
+ */
+ if (src->function != MEDIA_ENT_F_VID_MUX &&
+ sd->grp_id != IMX_MEDIA_GRP_ID_CSI2)
+ src = &priv->sd.entity;
+
/* get source pad of entity directly upstream from src */
pad = imx_media_find_upstream_pad(priv->md, src, 0);
if (IS_ERR(pad))
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
index 910594125889..6cd93419b81d 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -30,7 +30,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev)
dev_set_drvdata(dev, imxmd);
- strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
+ strscpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
imxmd->md.ops = &imx_media_md_ops;
imxmd->md.dev = dev;
@@ -38,7 +38,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev)
imxmd->v4l2_dev.mdev = &imxmd->md;
imxmd->v4l2_dev.notify = imx_media_notify;
- strlcpy(imxmd->v4l2_dev.name, "imx-media",
+ strscpy(imxmd->v4l2_dev.name, "imx-media",
sizeof(imxmd->v4l2_dev.name));
media_device_init(&imxmd->md);
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index bd4ddea488f1..6be95584006d 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -46,12 +46,14 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
int ret;
if (fwnode) {
- asd = v4l2_async_notifier_add_fwnode_subdev(
- &imxmd->notifier, fwnode, sizeof(*imxasd));
+ asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier,
+ fwnode,
+ sizeof(*imxasd));
} else {
devname = dev_name(&pdev->dev);
- asd = v4l2_async_notifier_add_devname_subdev(
- &imxmd->notifier, devname, sizeof(*imxasd));
+ asd = v4l2_async_notifier_add_devname_subdev(&imxmd->notifier,
+ devname,
+ sizeof(*imxasd));
}
if (IS_ERR(asd)) {
@@ -262,10 +264,9 @@ static int imx_media_alloc_pad_vdev_lists(struct imx_media_dev *imxmd)
list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
entity = &sd->entity;
- vdev_lists = devm_kcalloc(
- imxmd->md.dev,
- entity->num_pads, sizeof(*vdev_lists),
- GFP_KERNEL);
+ vdev_lists = devm_kcalloc(imxmd->md.dev,
+ entity->num_pads, sizeof(*vdev_lists),
+ GFP_KERNEL);
if (!vdev_lists)
return -ENOMEM;
@@ -473,13 +474,6 @@ static int imx_media_probe(struct platform_device *pdev)
goto cleanup;
}
- ret = imx_media_add_internal_subdevs(imxmd);
- if (ret) {
- v4l2_err(&imxmd->v4l2_dev,
- "add_internal_subdevs failed with %d\n", ret);
- goto cleanup;
- }
-
ret = imx_media_dev_notifier_register(imxmd);
if (ret)
goto del_int;
@@ -487,7 +481,7 @@ static int imx_media_probe(struct platform_device *pdev)
return 0;
del_int:
- imx_media_remove_internal_subdevs(imxmd);
+ imx_media_remove_ipu_internal_subdevs(imxmd);
cleanup:
v4l2_async_notifier_cleanup(&imxmd->notifier);
v4l2_device_unregister(&imxmd->v4l2_dev);
@@ -504,7 +498,7 @@ static int imx_media_remove(struct platform_device *pdev)
v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n");
v4l2_async_notifier_unregister(&imxmd->notifier);
- imx_media_remove_internal_subdevs(imxmd);
+ imx_media_remove_ipu_internal_subdevs(imxmd);
v4l2_async_notifier_cleanup(&imxmd->notifier);
media_device_unregister(&imxmd->md);
v4l2_device_unregister(&imxmd->v4l2_dev);
diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c
index c547280a309e..df49ebfbe98a 100644
--- a/drivers/staging/media/imx/imx-media-internal-sd.c
+++ b/drivers/staging/media/imx/imx-media-internal-sd.c
@@ -2,7 +2,7 @@
/*
* Media driver for Freescale i.MX5/6 SOC
*
- * Adds the internal subdevices and the media links between them.
+ * Adds the IPU internal subdevices and the media links between them.
*
* Copyright (c) 2016 Mentor Graphics Inc.
*/
@@ -188,7 +188,7 @@ static struct v4l2_subdev *find_sink(struct imx_media_dev *imxmd,
/*
* retrieve IPU id from subdev name, note: can't get this from
- * struct imx_media_internal_sd_platformdata because if src is
+ * struct imx_media_ipu_internal_sd_pdata because if src is
* a CSI, it has different struct ipu_client_platformdata which
* does not contain IPU id.
*/
@@ -266,7 +266,7 @@ static int add_internal_subdev(struct imx_media_dev *imxmd,
const struct internal_subdev *isd,
int ipu_id)
{
- struct imx_media_internal_sd_platformdata pdata;
+ struct imx_media_ipu_internal_sd_pdata pdata;
struct platform_device_info pdevinfo = {};
struct platform_device *pdev;
@@ -294,13 +294,14 @@ static int add_internal_subdev(struct imx_media_dev *imxmd,
}
/* adds the internal subdevs in one ipu */
-static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id)
+int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd,
+ int ipu_id)
{
enum isd_enum i;
+ int ret;
for (i = 0; i < num_isd; i++) {
const struct internal_subdev *isd = &int_subdev[i];
- int ret;
/*
* the CSIs are represented in the device-tree, so those
@@ -318,32 +319,17 @@ static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id)
}
if (ret)
- return ret;
+ goto remove;
}
return 0;
-}
-
-int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd)
-{
- int ret;
-
- ret = add_ipu_internal_subdevs(imxmd, 0);
- if (ret)
- goto remove;
-
- ret = add_ipu_internal_subdevs(imxmd, 1);
- if (ret)
- goto remove;
-
- return 0;
remove:
- imx_media_remove_internal_subdevs(imxmd);
+ imx_media_remove_ipu_internal_subdevs(imxmd);
return ret;
}
-void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd)
+void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd)
{
struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev *asd;
diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
index 09580d83c685..990e82aa8e42 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -19,36 +19,25 @@
int imx_media_of_add_csi(struct imx_media_dev *imxmd,
struct device_node *csi_np)
{
- int ret;
-
if (!of_device_is_available(csi_np)) {
dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__,
csi_np);
- /* unavailable is not an error */
- return 0;
+ return -ENODEV;
}
/* add CSI fwnode to async notifier */
- ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL);
- if (ret) {
- if (ret == -EEXIST) {
- /* already added, everything is fine */
- return 0;
- }
-
- /* other error, can't continue */
- return ret;
- }
-
- return 0;
+ return imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np),
+ NULL);
}
EXPORT_SYMBOL_GPL(imx_media_of_add_csi);
int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
struct device_node *np)
{
+ bool ipu_found[2] = {false, false};
struct device_node *csi_np;
int i, ret;
+ u32 ipu_id;
for (i = 0; ; i++) {
csi_np = of_parse_phandle(np, "ports", i);
@@ -56,12 +45,43 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
break;
ret = imx_media_of_add_csi(imxmd, csi_np);
- of_node_put(csi_np);
- if (ret)
- return ret;
+ if (ret) {
+ /* unavailable or already added is not an error */
+ if (ret == -ENODEV || ret == -EEXIST) {
+ of_node_put(csi_np);
+ continue;
+ }
+
+ /* other error, can't continue */
+ goto err_out;
+ }
+
+ ret = of_alias_get_id(csi_np->parent, "ipu");
+ if (ret < 0)
+ goto err_out;
+ if (ret > 1) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ ipu_id = ret;
+
+ if (!ipu_found[ipu_id]) {
+ ret = imx_media_add_ipu_internal_subdevs(imxmd,
+ ipu_id);
+ if (ret)
+ goto err_out;
+ }
+
+ ipu_found[ipu_id] = true;
}
return 0;
+
+err_out:
+ imx_media_remove_ipu_internal_subdevs(imxmd);
+ of_node_put(csi_np);
+ return ret;
}
/*
@@ -141,15 +161,18 @@ int imx_media_create_csi_of_links(struct imx_media_dev *imxmd,
struct v4l2_subdev *csi)
{
struct device_node *csi_np = csi->dev->of_node;
- struct fwnode_handle *fwnode, *csi_ep;
- struct v4l2_fwnode_link link;
struct device_node *ep;
- int ret;
-
- link.local_node = of_fwnode_handle(csi_np);
- link.local_port = CSI_SINK_PAD;
for_each_child_of_node(csi_np, ep) {
+ struct fwnode_handle *fwnode, *csi_ep;
+ struct v4l2_fwnode_link link;
+ int ret;
+
+ memset(&link, 0, sizeof(link));
+
+ link.local_node = of_fwnode_handle(csi_np);
+ link.local_port = CSI_SINK_PAD;
+
csi_ep = of_fwnode_handle(ep);
fwnode = fwnode_graph_get_remote_endpoint(csi_ep);
diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c
index 3f4b5e9080d4..4487374c9435 100644
--- a/drivers/staging/media/imx/imx-media-vdic.c
+++ b/drivers/staging/media/imx/imx-media-vdic.c
@@ -227,6 +227,12 @@ static void __maybe_unused prepare_vdi_in_buffers(struct vdic_priv *priv,
curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0);
next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + is;
break;
+ default:
+ /*
+ * can't get here, priv->fieldtype can only be one of
+ * the above. This is to quiet smatch errors.
+ */
+ return;
}
ipu_cpmem_set_buffer(priv->vdi_in_ch_p, 0, prev_phys);
@@ -740,7 +746,7 @@ static int vdic_link_setup(struct media_entity *entity,
remote_sd = media_entity_to_v4l2_subdev(remote->entity);
/* direct pad must connect to a CSI */
- if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_CSI) ||
+ if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) ||
remote->index != CSI_SRC_PAD_DIRECT) {
ret = -EINVAL;
goto out;
@@ -930,7 +936,7 @@ static const struct v4l2_subdev_internal_ops vdic_internal_ops = {
static int imx_vdic_probe(struct platform_device *pdev)
{
- struct imx_media_internal_sd_platformdata *pdata;
+ struct imx_media_ipu_internal_sd_pdata *pdata;
struct vdic_priv *priv;
int ret;
@@ -954,7 +960,7 @@ static int imx_vdic_probe(struct platform_device *pdev)
priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
/* get our group id */
priv->sd.grp_id = pdata->grp_id;
- strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
+ strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
mutex_init(&priv->lock);
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index 1f7501d527fb..eb59ba0c3b62 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -111,7 +111,7 @@ struct imx_media_pad_vdev {
struct list_head list;
};
-struct imx_media_internal_sd_platformdata {
+struct imx_media_ipu_internal_sd_pdata {
char sd_name[V4L2_SUBDEV_NAME_SIZE];
u32 grp_id;
int ipu_id;
@@ -248,10 +248,11 @@ struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
void imx_media_fim_free(struct imx_media_fim *fim);
/* imx-media-internal-sd.c */
-int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd);
+int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd,
+ int ipu_id);
int imx_media_create_ipu_internal_links(struct imx_media_dev *imxmd,
struct v4l2_subdev *sd);
-void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd);
+void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd);
/* imx-media-of.c */
int imx_media_add_of_subdevs(struct imx_media_dev *dev,
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index 3fba7c27c0ec..18eb5d3ecf10 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1051,7 +1051,9 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
goto out_unlock;
}
- imx7_csi_try_fmt(csi, cfg, sdformat, &cc);
+ ret = imx7_csi_try_fmt(csi, cfg, sdformat, &cc);
+ if (ret < 0)
+ goto out_unlock;
fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which);
if (!fmt) {
@@ -1271,7 +1273,7 @@ static int imx7_csi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &csi->sd);
ret = imx_media_of_add_csi(imxmd, node);
- if (ret < 0)
+ if (ret < 0 && ret != -ENODEV && ret != -EEXIST)
goto cleanup;
ret = imx_media_dev_notifier_register(imxmd);
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
index 2ddcc42ab8ff..19455f425416 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -9,6 +9,7 @@
*/
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
@@ -491,7 +492,7 @@ static int mipi_csis_clk_get(struct csi_state *state)
state->wrap_clk = devm_clk_get(dev, "wrap");
if (IS_ERR(state->wrap_clk))
- return IS_ERR(state->wrap_clk);
+ return PTR_ERR(state->wrap_clk);
/* Set clock rate */
ret = clk_set_rate(state->wrap_clk, state->clk_frequency);
@@ -706,7 +707,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
mutex_lock(&state->lock);
- if (fmt && sdformat->pad == CSIS_PAD_SOURCE) {
+ if (sdformat->pad == CSIS_PAD_SOURCE) {
sdformat->format = *fmt;
goto unlock;
}
@@ -889,8 +890,6 @@ static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
return ret;
}
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
{
@@ -900,7 +899,7 @@ static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
}
DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
-static int __init_or_module mipi_csis_debugfs_init(struct csi_state *state)
+static int mipi_csis_debugfs_init(struct csi_state *state)
{
struct dentry *d;
@@ -934,17 +933,6 @@ static void mipi_csis_debugfs_exit(struct csi_state *state)
debugfs_remove_recursive(state->debugfs_root);
}
-#else
-static int mipi_csis_debugfs_init(struct csi_state *state __maybe_unused)
-{
- return 0;
-}
-
-static void mipi_csis_debugfs_exit(struct csi_state *state __maybe_unused)
-{
-}
-#endif
-
static int mipi_csis_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1039,8 +1027,7 @@ disable_clock:
static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev);
+ struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev);
struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
int ret = 0;
@@ -1064,8 +1051,7 @@ unlock:
static int mipi_csis_pm_resume(struct device *dev, bool runtime)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev);
+ struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev);
struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
int ret = 0;