Commit 5acc3e22 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

media: ti-vpe: cal: Create subdev for CAMERARX

Create and register V4L2 subdevs for the CAMERARX instances, and link
them in the media graph to the sensors and video nodes. The subdev API
is not exposed to userspace at this point, and no subdev operation is
implemented, but the media controller graph is visible to applications.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarKieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 5c8fe583
...@@ -533,8 +533,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal, ...@@ -533,8 +533,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
static int cal_camerarx_parse_dt(struct cal_camerarx *phy) static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
{ {
struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint; struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
struct device_node *ep_node;
char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2]; char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
struct device_node *ep_node;
unsigned int i; unsigned int i;
int ret; int ret;
...@@ -582,9 +582,11 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy) ...@@ -582,9 +582,11 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
endpoint->bus.mipi_csi2.flags); endpoint->bus.mipi_csi2.flags);
/* Retrieve the connected device and store it for later use. */ /* Retrieve the connected device and store it for later use. */
phy->sensor_node = of_graph_get_remote_port_parent(ep_node); phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
if (!phy->sensor_node) { if (!phy->sensor_node) {
phy_dbg(3, phy, "Can't get remote parent\n"); phy_dbg(3, phy, "Can't get remote parent\n");
of_node_put(phy->sensor_ep_node);
ret = -EINVAL; ret = -EINVAL;
goto done; goto done;
} }
...@@ -596,11 +598,25 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy) ...@@ -596,11 +598,25 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
return ret; return ret;
} }
/* ------------------------------------------------------------------
* V4L2 Subdev Operations
* ------------------------------------------------------------------
*/
static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
};
/* ------------------------------------------------------------------
* Create and Destroy
* ------------------------------------------------------------------
*/
struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
unsigned int instance) unsigned int instance)
{ {
struct platform_device *pdev = to_platform_device(cal->dev); struct platform_device *pdev = to_platform_device(cal->dev);
struct cal_camerarx *phy; struct cal_camerarx *phy;
struct v4l2_subdev *sd;
int ret; int ret;
phy = kzalloc(sizeof(*phy), GFP_KERNEL); phy = kzalloc(sizeof(*phy), GFP_KERNEL);
...@@ -632,9 +648,28 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, ...@@ -632,9 +648,28 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
if (ret) if (ret)
goto error; goto error;
/* Initialize the V4L2 subdev and media entity. */
sd = &phy->subdev;
v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
sd->dev = cal->dev;
phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
phy->pads);
if (ret)
goto error;
ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
if (ret)
goto error;
return phy; return phy;
error: error:
media_entity_cleanup(&phy->subdev.entity);
kfree(phy); kfree(phy);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -644,6 +679,9 @@ void cal_camerarx_destroy(struct cal_camerarx *phy) ...@@ -644,6 +679,9 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
if (!phy) if (!phy)
return; return;
v4l2_device_unregister_subdev(&phy->subdev);
media_entity_cleanup(&phy->subdev.entity);
of_node_put(phy->sensor_ep_node);
of_node_put(phy->sensor_node); of_node_put(phy->sensor_node);
kfree(phy); kfree(phy);
} }
...@@ -809,6 +809,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx) ...@@ -809,6 +809,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
return ret; return ret;
} }
ret = media_create_pad_link(&ctx->phy->subdev.entity,
CAL_CAMERARX_PAD_SOURCE,
&vfd->entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
ctx_err(ctx, "Failed to create media link for context %u\n",
ctx->index);
video_unregister_device(vfd);
return ret;
}
ctx_info(ctx, "V4L2 device registered as %s\n", ctx_info(ctx, "V4L2 device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
......
...@@ -421,6 +421,8 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier, ...@@ -421,6 +421,8 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
struct v4l2_async_subdev *asd) struct v4l2_async_subdev *asd)
{ {
struct cal_camerarx *phy = to_cal_asd(asd)->phy; struct cal_camerarx *phy = to_cal_asd(asd)->phy;
int pad;
int ret;
if (phy->sensor) { if (phy->sensor) {
phy_info(phy, "Rejecting subdev %s (Already set!!)", phy_info(phy, "Rejecting subdev %s (Already set!!)",
...@@ -431,6 +433,25 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier, ...@@ -431,6 +433,25 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
phy->sensor = subdev; phy->sensor = subdev;
phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name); phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
pad = media_entity_get_fwnode_pad(&subdev->entity,
of_fwnode_handle(phy->sensor_ep_node),
MEDIA_PAD_FL_SOURCE);
if (pad < 0) {
phy_err(phy, "Sensor %s has no connected source pad\n",
subdev->name);
return pad;
}
ret = media_create_pad_link(&subdev->entity, pad,
&phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
phy_err(phy, "Failed to create media link for sensor %s\n",
subdev->name);
return ret;
}
return 0; return 0;
} }
...@@ -797,6 +818,11 @@ static int cal_probe(struct platform_device *pdev) ...@@ -797,6 +818,11 @@ static int cal_probe(struct platform_device *pdev)
cal_get_hwinfo(cal); cal_get_hwinfo(cal);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
/* Initialize the media device. */
ret = cal_media_init(cal);
if (ret < 0)
goto error_pm_runtime;
/* Create CAMERARX PHYs. */ /* Create CAMERARX PHYs. */
for (i = 0; i < cal->data->num_csi2_phy; ++i) { for (i = 0; i < cal->data->num_csi2_phy; ++i) {
cal->phy[i] = cal_camerarx_create(cal, i); cal->phy[i] = cal_camerarx_create(cal, i);
...@@ -816,11 +842,6 @@ static int cal_probe(struct platform_device *pdev) ...@@ -816,11 +842,6 @@ static int cal_probe(struct platform_device *pdev)
goto error_camerarx; goto error_camerarx;
} }
/* Initialize the media device. */
ret = cal_media_init(cal);
if (ret < 0)
goto error_camerarx;
/* Create contexts. */ /* Create contexts. */
for (i = 0; i < cal->data->num_csi2_phy; ++i) { for (i = 0; i < cal->data->num_csi2_phy; ++i) {
if (!cal->phy[i]->sensor_node) if (!cal->phy[i]->sensor_node)
...@@ -848,12 +869,12 @@ static int cal_probe(struct platform_device *pdev) ...@@ -848,12 +869,12 @@ static int cal_probe(struct platform_device *pdev)
cal_ctx_v4l2_cleanup(ctx); cal_ctx_v4l2_cleanup(ctx);
} }
cal_media_cleanup(cal);
error_camerarx: error_camerarx:
for (i = 0; i < ARRAY_SIZE(cal->phy); i++) for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
cal_camerarx_destroy(cal->phy[i]); cal_camerarx_destroy(cal->phy[i]);
cal_media_cleanup(cal);
error_pm_runtime: error_pm_runtime:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-v4l2.h> #include <media/videobuf2-v4l2.h>
#define CAL_MODULE_NAME "cal" #define CAL_MODULE_NAME "cal"
...@@ -33,12 +34,14 @@ ...@@ -33,12 +34,14 @@
#define MAX_WIDTH_BYTES (8192 * 8) #define MAX_WIDTH_BYTES (8192 * 8)
#define MAX_HEIGHT_LINES 16383 #define MAX_HEIGHT_LINES 16383
#define CAL_CAMERARX_PAD_SINK 0
#define CAL_CAMERARX_PAD_SOURCE 1
struct device; struct device;
struct device_node; struct device_node;
struct resource; struct resource;
struct regmap; struct regmap;
struct regmap_fied; struct regmap_fied;
struct v4l2_subdev;
/* CTRL_CORE_CAMERRX_CONTROL register field id */ /* CTRL_CORE_CAMERRX_CONTROL register field id */
enum cal_camerarx_field { enum cal_camerarx_field {
...@@ -108,8 +111,12 @@ struct cal_camerarx { ...@@ -108,8 +111,12 @@ struct cal_camerarx {
unsigned int instance; unsigned int instance;
struct v4l2_fwnode_endpoint endpoint; struct v4l2_fwnode_endpoint endpoint;
struct device_node *sensor_ep_node;
struct device_node *sensor_node; struct device_node *sensor_node;
struct v4l2_subdev *sensor; struct v4l2_subdev *sensor;
struct v4l2_subdev subdev;
struct media_pad pads[2];
}; };
struct cal_dev { struct cal_dev {
......
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