Commit 85999e8e authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: rcar-vin: Use generic parser for parsing fwnode endpoints

Instead of using a custom driver implementation, use
v4l2_async_notifier_parse_fwnode_endpoints() to parse the fwnode endpoints
of the device.
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent df497566
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <media/v4l2-async.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include "rcar-vin.h" #include "rcar-vin.h"
...@@ -77,14 +78,14 @@ static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier) ...@@ -77,14 +78,14 @@ static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier)
int ret; int ret;
/* Verify subdevices mbus format */ /* Verify subdevices mbus format */
if (!rvin_mbus_supported(&vin->digital)) { if (!rvin_mbus_supported(vin->digital)) {
vin_err(vin, "Unsupported media bus format for %s\n", vin_err(vin, "Unsupported media bus format for %s\n",
vin->digital.subdev->name); vin->digital->subdev->name);
return -EINVAL; return -EINVAL;
} }
vin_dbg(vin, "Found media bus format for %s: %d\n", vin_dbg(vin, "Found media bus format for %s: %d\n",
vin->digital.subdev->name, vin->digital.code); vin->digital->subdev->name, vin->digital->code);
ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev); ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
if (ret < 0) { if (ret < 0) {
...@@ -103,7 +104,7 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier, ...@@ -103,7 +104,7 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier,
vin_dbg(vin, "unbind digital subdev %s\n", subdev->name); vin_dbg(vin, "unbind digital subdev %s\n", subdev->name);
rvin_v4l2_remove(vin); rvin_v4l2_remove(vin);
vin->digital.subdev = NULL; vin->digital->subdev = NULL;
} }
static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier,
...@@ -120,117 +121,71 @@ static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier, ...@@ -120,117 +121,71 @@ static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier,
ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE); ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
if (ret < 0) if (ret < 0)
return ret; return ret;
vin->digital.source_pad = ret; vin->digital->source_pad = ret;
ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK); ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
vin->digital.sink_pad = ret < 0 ? 0 : ret; vin->digital->sink_pad = ret < 0 ? 0 : ret;
vin->digital.subdev = subdev; vin->digital->subdev = subdev;
vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n", vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n",
subdev->name, vin->digital.source_pad, subdev->name, vin->digital->source_pad,
vin->digital.sink_pad); vin->digital->sink_pad);
return 0; return 0;
} }
static int rvin_digitial_parse_v4l2(struct rvin_dev *vin, static int rvin_digital_parse_v4l2(struct device *dev,
struct device_node *ep, struct v4l2_fwnode_endpoint *vep,
struct v4l2_mbus_config *mbus_cfg) struct v4l2_async_subdev *asd)
{ {
struct v4l2_fwnode_endpoint v4l2_ep; struct rvin_dev *vin = dev_get_drvdata(dev);
int ret; struct rvin_graph_entity *rvge =
container_of(asd, struct rvin_graph_entity, asd);
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep); if (vep->base.port || vep->base.id)
if (ret) { return -ENOTCONN;
vin_err(vin, "Could not parse v4l2 endpoint\n");
return -EINVAL;
}
mbus_cfg->type = v4l2_ep.bus_type; rvge->mbus_cfg.type = vep->bus_type;
switch (mbus_cfg->type) { switch (rvge->mbus_cfg.type) {
case V4L2_MBUS_PARALLEL: case V4L2_MBUS_PARALLEL:
vin_dbg(vin, "Found PARALLEL media bus\n"); vin_dbg(vin, "Found PARALLEL media bus\n");
mbus_cfg->flags = v4l2_ep.bus.parallel.flags; rvge->mbus_cfg.flags = vep->bus.parallel.flags;
break; break;
case V4L2_MBUS_BT656: case V4L2_MBUS_BT656:
vin_dbg(vin, "Found BT656 media bus\n"); vin_dbg(vin, "Found BT656 media bus\n");
mbus_cfg->flags = 0; rvge->mbus_cfg.flags = 0;
break; break;
default: default:
vin_err(vin, "Unknown media bus type\n"); vin_err(vin, "Unknown media bus type\n");
return -EINVAL; return -EINVAL;
} }
return 0; vin->digital = rvge;
}
static int rvin_digital_graph_parse(struct rvin_dev *vin)
{
struct device_node *ep, *np;
int ret;
vin->digital.asd.match.fwnode.fwnode = NULL;
vin->digital.subdev = NULL;
/*
* Port 0 id 0 is local digital input, try to get it.
* Not all instances can or will have this, that is OK
*/
ep = of_graph_get_endpoint_by_regs(vin->dev->of_node, 0, 0);
if (!ep)
return 0;
np = of_graph_get_remote_port_parent(ep);
if (!np) {
vin_err(vin, "No remote parent for digital input\n");
of_node_put(ep);
return -EINVAL;
}
of_node_put(np);
ret = rvin_digitial_parse_v4l2(vin, ep, &vin->digital.mbus_cfg);
of_node_put(ep);
if (ret)
return ret;
vin->digital.asd.match.fwnode.fwnode = of_fwnode_handle(np);
vin->digital.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
return 0; return 0;
} }
static int rvin_digital_graph_init(struct rvin_dev *vin) static int rvin_digital_graph_init(struct rvin_dev *vin)
{ {
struct v4l2_async_subdev **subdevs = NULL;
int ret; int ret;
ret = rvin_digital_graph_parse(vin); ret = v4l2_async_notifier_parse_fwnode_endpoints(
vin->dev, &vin->notifier,
sizeof(struct rvin_graph_entity), rvin_digital_parse_v4l2);
if (ret) if (ret)
return ret; return ret;
if (!vin->digital.asd.match.fwnode.fwnode) { if (!vin->digital)
vin_dbg(vin, "No digital subdevice found\n");
return -ENODEV; return -ENODEV;
}
/* Register the subdevices notifier. */
subdevs = devm_kzalloc(vin->dev, sizeof(*subdevs), GFP_KERNEL);
if (subdevs == NULL)
return -ENOMEM;
subdevs[0] = &vin->digital.asd;
vin_dbg(vin, "Found digital subdevice %pOF\n", vin_dbg(vin, "Found digital subdevice %pOF\n",
to_of_node(subdevs[0]->match.fwnode.fwnode)); to_of_node(vin->digital->asd.match.fwnode.fwnode));
vin->notifier.num_subdevs = 1;
vin->notifier.subdevs = subdevs;
vin->notifier.bound = rvin_digital_notify_bound; vin->notifier.bound = rvin_digital_notify_bound;
vin->notifier.unbind = rvin_digital_notify_unbind; vin->notifier.unbind = rvin_digital_notify_unbind;
vin->notifier.complete = rvin_digital_notify_complete; vin->notifier.complete = rvin_digital_notify_complete;
ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier); ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
if (ret < 0) { if (ret < 0) {
vin_err(vin, "Notifier registration failed\n"); vin_err(vin, "Notifier registration failed\n");
...@@ -290,6 +245,8 @@ static int rcar_vin_probe(struct platform_device *pdev) ...@@ -290,6 +245,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
platform_set_drvdata(pdev, vin);
ret = rvin_digital_graph_init(vin); ret = rvin_digital_graph_init(vin);
if (ret < 0) if (ret < 0)
goto error; goto error;
...@@ -297,11 +254,10 @@ static int rcar_vin_probe(struct platform_device *pdev) ...@@ -297,11 +254,10 @@ static int rcar_vin_probe(struct platform_device *pdev)
pm_suspend_ignore_children(&pdev->dev, true); pm_suspend_ignore_children(&pdev->dev, true);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
platform_set_drvdata(pdev, vin);
return 0; return 0;
error: error:
rvin_dma_remove(vin); rvin_dma_remove(vin);
v4l2_async_notifier_cleanup(&vin->notifier);
return ret; return ret;
} }
...@@ -313,6 +269,7 @@ static int rcar_vin_remove(struct platform_device *pdev) ...@@ -313,6 +269,7 @@ static int rcar_vin_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
v4l2_async_notifier_unregister(&vin->notifier); v4l2_async_notifier_unregister(&vin->notifier);
v4l2_async_notifier_cleanup(&vin->notifier);
rvin_dma_remove(vin); rvin_dma_remove(vin);
......
...@@ -183,7 +183,7 @@ static int rvin_setup(struct rvin_dev *vin) ...@@ -183,7 +183,7 @@ static int rvin_setup(struct rvin_dev *vin)
/* /*
* Input interface * Input interface
*/ */
switch (vin->digital.code) { switch (vin->digital->code) {
case MEDIA_BUS_FMT_YUYV8_1X16: case MEDIA_BUS_FMT_YUYV8_1X16:
/* BT.601/BT.1358 16bit YCbCr422 */ /* BT.601/BT.1358 16bit YCbCr422 */
vnmc |= VNMC_INF_YUV16; vnmc |= VNMC_INF_YUV16;
...@@ -191,7 +191,7 @@ static int rvin_setup(struct rvin_dev *vin) ...@@ -191,7 +191,7 @@ static int rvin_setup(struct rvin_dev *vin)
break; break;
case MEDIA_BUS_FMT_UYVY8_2X8: case MEDIA_BUS_FMT_UYVY8_2X8:
/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ? vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
input_is_yuv = true; input_is_yuv = true;
break; break;
...@@ -200,7 +200,7 @@ static int rvin_setup(struct rvin_dev *vin) ...@@ -200,7 +200,7 @@ static int rvin_setup(struct rvin_dev *vin)
break; break;
case MEDIA_BUS_FMT_UYVY10_2X10: case MEDIA_BUS_FMT_UYVY10_2X10:
/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
vnmc |= vin->digital.mbus_cfg.type == V4L2_MBUS_BT656 ? vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
input_is_yuv = true; input_is_yuv = true;
break; break;
...@@ -212,11 +212,11 @@ static int rvin_setup(struct rvin_dev *vin) ...@@ -212,11 +212,11 @@ static int rvin_setup(struct rvin_dev *vin)
dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1); dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
/* Hsync Signal Polarity Select */ /* Hsync Signal Polarity Select */
if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
dmr2 |= VNDMR2_HPS; dmr2 |= VNDMR2_HPS;
/* Vsync Signal Polarity Select */ /* Vsync Signal Polarity Select */
if (!(vin->digital.mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
dmr2 |= VNDMR2_VPS; dmr2 |= VNDMR2_VPS;
/* /*
......
...@@ -111,7 +111,7 @@ static int rvin_reset_format(struct rvin_dev *vin) ...@@ -111,7 +111,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
struct v4l2_mbus_framefmt *mf = &fmt.format; struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret; int ret;
fmt.pad = vin->digital.source_pad; fmt.pad = vin->digital->source_pad;
ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt); ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
if (ret) if (ret)
...@@ -172,13 +172,13 @@ static int __rvin_try_format_source(struct rvin_dev *vin, ...@@ -172,13 +172,13 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
sd = vin_to_source(vin); sd = vin_to_source(vin);
v4l2_fill_mbus_format(&format.format, pix, vin->digital.code); v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
pad_cfg = v4l2_subdev_alloc_pad_config(sd); pad_cfg = v4l2_subdev_alloc_pad_config(sd);
if (pad_cfg == NULL) if (pad_cfg == NULL)
return -ENOMEM; return -ENOMEM;
format.pad = vin->digital.source_pad; format.pad = vin->digital->source_pad;
field = pix->field; field = pix->field;
...@@ -555,7 +555,7 @@ static int rvin_enum_dv_timings(struct file *file, void *priv_fh, ...@@ -555,7 +555,7 @@ static int rvin_enum_dv_timings(struct file *file, void *priv_fh,
if (timings->pad) if (timings->pad)
return -EINVAL; return -EINVAL;
timings->pad = vin->digital.sink_pad; timings->pad = vin->digital->sink_pad;
ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings); ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings);
...@@ -607,7 +607,7 @@ static int rvin_dv_timings_cap(struct file *file, void *priv_fh, ...@@ -607,7 +607,7 @@ static int rvin_dv_timings_cap(struct file *file, void *priv_fh,
if (cap->pad) if (cap->pad)
return -EINVAL; return -EINVAL;
cap->pad = vin->digital.sink_pad; cap->pad = vin->digital->sink_pad;
ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap); ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
...@@ -625,7 +625,7 @@ static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid) ...@@ -625,7 +625,7 @@ static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
if (edid->pad) if (edid->pad)
return -EINVAL; return -EINVAL;
edid->pad = vin->digital.sink_pad; edid->pad = vin->digital->sink_pad;
ret = v4l2_subdev_call(sd, pad, get_edid, edid); ret = v4l2_subdev_call(sd, pad, get_edid, edid);
...@@ -643,7 +643,7 @@ static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid) ...@@ -643,7 +643,7 @@ static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
if (edid->pad) if (edid->pad)
return -EINVAL; return -EINVAL;
edid->pad = vin->digital.sink_pad; edid->pad = vin->digital->sink_pad;
ret = v4l2_subdev_call(sd, pad, set_edid, edid); ret = v4l2_subdev_call(sd, pad, set_edid, edid);
......
...@@ -126,7 +126,7 @@ struct rvin_dev { ...@@ -126,7 +126,7 @@ struct rvin_dev {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_async_notifier notifier; struct v4l2_async_notifier notifier;
struct rvin_graph_entity digital; struct rvin_graph_entity *digital;
struct mutex lock; struct mutex lock;
struct vb2_queue queue; struct vb2_queue queue;
...@@ -145,7 +145,7 @@ struct rvin_dev { ...@@ -145,7 +145,7 @@ struct rvin_dev {
struct v4l2_rect compose; struct v4l2_rect compose;
}; };
#define vin_to_source(vin) vin->digital.subdev #define vin_to_source(vin) ((vin)->digital->subdev)
/* Debug */ /* Debug */
#define vin_dbg(d, fmt, arg...) dev_dbg(d->dev, fmt, ##arg) #define vin_dbg(d, fmt, arg...) dev_dbg(d->dev, fmt, ##arg)
......
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