* [PATCH v2 00/11] media: ov5645: Add support for streams
@ 2024-09-10 17:05 Prabhakar
2024-09-10 17:06 ` [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Prabhakar
` (10 more replies)
0 siblings, 11 replies; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:05 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Hi All,
This patch series aims to add the below features,
- Support subdev active state
- Support for streams
- Support for virtual channel
- Code cleanup
Note, these patches are dependent on below:
1] https://patchwork.kernel.org/project/linux-media/patch/20240416193319.778192-27-sakari.ailus@linux.intel.com/
2] https://patchwork.kernel.org/project/linux-media/patch/20240416193319.778192-26-sakari.ailus@linux.intel.com/
RFC->v2
- Dropped setting of VC using routes
- Defaulted the native format to MEDIA_BUS_FMT_SBGGR8_1X8
- Fixed ov5645_enum_frame_size and ov5645_enum_mbus_code
for internal image pad
RFC patch,
Link: https://lore.kernel.org/all/20240904210719.52466-1-prabhakar.mahadev-lad.rj@bp.renesas.com/
Test logs:
====================================
root@smarc-rzg2l:~# media-ctl -p
.....
- entity 4: ov5645 0-003c (2 pads, 1 link, 1 route)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev1
routes:
1/0 -> 0/0 [ACTIVE]
pad0: SOURCE
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb
crop:(0,0)/1920x1080]
-> "csi-10830400.csi2":0 [ENABLED,IMMUTABLE]
pad1: SINK,0x8
[stream:0 fmt:SBGGR8_1X8/2592x1944 field:none colorspace:srgb
crop:(0,0)/1920x1080]
.....
root@smarc-rzg2l:~# v4l2-ctl --device /dev/v4l-subdev1 --list-subdev-mbus-codes pad=0
ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0,stream=0)
0x200f: MEDIA_BUS_FMT_UYVY8_1X16
root@smarc-rzg2l:~# v4l2-ctl --device /dev/v4l-subdev1 --list-subdev-mbus-codes pad=1
ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=1,stream=0)
0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
root@smarc-rzg2l:~# v4l2-ctl --device /dev/v4l-subdev1 --list-subdev-framesizes pad=1,code=0x3001
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=1,stream=0)
Size Range: 2592x1944 - 2592x1944
root@smarc-rzg2l:~# v4l2-ctl --device /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0,stream=0)
Size Range: 1280x960 - 1280x960
Size Range: 1920x1080 - 1920x1080
Size Range: 2592x1944 - 2592x1944
root@smarc-rzg2l:~#
v4l2-compliance log:
-------------------
root@smarc-rzg2l:~# v4l2-compliance -u /dev/v4l-subdev1
v4l2-compliance 1.28.1-5233, 64 bits, 64-bit time_t
v4l2-compliance SHA: fc15e229d9d3 2024-07-23 19:22:15
Compliance test for device /dev/v[ 6347.789338] ov5645 0-003c: ================= START STATUS =================
4l-subdev1:
Driver In[ 6347.798197] ov5645 0-003c: ================== END STATUS ==================
fo:
Driver version : 6.11.0
Capabilities : 0x00000002
Streams Support
Client Capabilities: 0x0000000000000003
streams interval-uses-which
Required ioctls:
test VIDIOC_SUDBEV_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/v4l-subdev1 open: OK
test VIDIOC_SUBDEV_QUERYCAP: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device routing ioctls:
test Try VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: OK
test Active VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: OK
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 12 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test CREATE_BUFS maximum buffers: OK
test VIDIOC_REMOVE_BUFS: OK
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for device /dev/v4l-subdev1: 47, Succeeded: 47, Failed: 0, Warnings: 0
Lad Prabhakar (11):
media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks
media: i2c: ov5645: Use local `dev` pointer for subdev device
assignment
media: i2c: ov5645: Enable runtime PM after
v4l2_async_register_subdev()
media: i2c: ov5645: Use dev_err_probe instead of dev_err
media: i2c: ov5645: Use v4l2_async_register_subdev_sensor()
media: i2c: ov5645: Drop `power_lock` mutex
media: i2c: ov5645: Use subdev active state
media: i2c: ov5645: Switch to {enable,disable}_streams
media: i2c: ov5645: Add internal image sink pad
media: i2c: ov5645: Report internal routes to userspace
media: i2c: ov5645: Report streams using frame descriptors
drivers/media/i2c/ov5645.c | 433 ++++++++++++++++++++-----------------
1 file changed, 240 insertions(+), 193 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:35 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment Prabhakar
` (9 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
The OV5645 sensor exposes controls, so the V4L2_SUBDEV_FL_HAS_EVENTS flag
should be set and implement subscribe_event and unsubscribe_event hooks.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 019979f553b1..6eedd0310b02 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -1042,7 +1043,13 @@ static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
.get_selection = ov5645_get_selection,
};
+static const struct v4l2_subdev_core_ops ov5645_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
static const struct v4l2_subdev_ops ov5645_subdev_ops = {
+ .core = &ov5645_core_ops,
.video = &ov5645_video_ops,
.pad = &ov5645_subdev_pad_ops,
};
@@ -1178,7 +1185,7 @@ static int ov5645_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
ov5645->sd.internal_ops = &ov5645_internal_ops;
- ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
ov5645->sd.dev = &client->dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
2024-09-10 17:06 ` [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:35 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev() Prabhakar
` (8 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
While assigning the subdev device pointer, use the local `dev` pointer
which is already extracted from the `i2c_client` pointer.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 6eedd0310b02..ab3a419df2df 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1187,7 +1187,7 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
- ov5645->sd.dev = &client->dev;
+ ov5645->sd.dev = dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev()
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
2024-09-10 17:06 ` [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Prabhakar
2024-09-10 17:06 ` [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:37 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err Prabhakar
` (7 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
To simplify the probe error path, enable runtime PM after the
v4l2_async_register_subdev() call.
This change ensures that runtime PM is only enabled once the subdevice
registration is successful, avoiding unnecessary cleanup in the error
path.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index ab3a419df2df..78b86438c798 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1239,18 +1239,17 @@ static int ov5645_probe(struct i2c_client *client)
goto power_down;
}
- pm_runtime_set_active(dev);
- pm_runtime_get_noresume(dev);
- pm_runtime_enable(dev);
-
ov5645_init_state(&ov5645->sd, NULL);
ret = v4l2_async_register_subdev(&ov5645->sd);
if (ret < 0) {
dev_err(dev, "could not register v4l2 device\n");
- goto err_pm_runtime;
+ goto power_down;
}
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
@@ -1258,9 +1257,6 @@ static int ov5645_probe(struct i2c_client *client)
return 0;
-err_pm_runtime:
- pm_runtime_disable(dev);
- pm_runtime_put_noidle(dev);
power_down:
ov5645_set_power_off(dev);
free_entity:
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (2 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev() Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:43 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor() Prabhakar
` (6 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Drop dev_err() and use the dev_err_probe() helper on probe path.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 74 +++++++++++++++-----------------------
1 file changed, 28 insertions(+), 46 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 78b86438c798..9e6ff1f1b9ac 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1076,51 +1076,37 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->dev = dev;
endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
- if (!endpoint) {
- dev_err(dev, "endpoint node not found\n");
- return -EINVAL;
- }
+ if (!endpoint)
+ return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&ov5645->ep);
of_node_put(endpoint);
- if (ret < 0) {
- dev_err(dev, "parsing endpoint node failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "parsing endpoint node failed\n");
- if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
- dev_err(dev, "invalid bus type, must be CSI2\n");
- return -EINVAL;
- }
+ if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
+ return dev_err_probe(dev, -EINVAL, "invalid bus type, must be CSI2\n");
/* get system clock (xclk) */
ov5645->xclk = devm_clk_get(dev, NULL);
- if (IS_ERR(ov5645->xclk)) {
- dev_err(dev, "could not get xclk");
- return PTR_ERR(ov5645->xclk);
- }
+ if (IS_ERR(ov5645->xclk))
+ return dev_err_probe(dev, PTR_ERR(ov5645->xclk), "could not get xclk");
ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
- if (ret) {
- dev_err(dev, "could not get xclk frequency\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "could not get xclk frequency\n");
/* external clock must be 24MHz, allow 1% tolerance */
- if (xclk_freq < 23760000 || xclk_freq > 24240000) {
- dev_err(dev, "external clock frequency %u is not supported\n",
- xclk_freq);
- return -EINVAL;
- }
+ if (xclk_freq < 23760000 || xclk_freq > 24240000)
+ return dev_err_probe(dev, -EINVAL, "external clock frequency %u is not supported\n",
+ xclk_freq);
ret = clk_set_rate(ov5645->xclk, xclk_freq);
- if (ret) {
- dev_err(dev, "could not set xclk frequency\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "could not set xclk frequency\n");
for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
ov5645->supplies[i].supply = ov5645_supply_name[i];
@@ -1131,16 +1117,12 @@ static int ov5645_probe(struct i2c_client *client)
return ret;
ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
- if (IS_ERR(ov5645->enable_gpio)) {
- dev_err(dev, "cannot get enable gpio\n");
- return PTR_ERR(ov5645->enable_gpio);
- }
+ if (IS_ERR(ov5645->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio), "cannot get enable gpio\n");
ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(ov5645->rst_gpio)) {
- dev_err(dev, "cannot get reset gpio\n");
- return PTR_ERR(ov5645->rst_gpio);
- }
+ if (IS_ERR(ov5645->rst_gpio))
+ return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio), "cannot get reset gpio\n");
mutex_init(&ov5645->power_lock);
@@ -1177,9 +1159,9 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.ctrl_handler = &ov5645->ctrls;
if (ov5645->ctrls.error) {
- dev_err(dev, "%s: control initialization error %d\n",
- __func__, ov5645->ctrls.error);
ret = ov5645->ctrls.error;
+ dev_err_probe(dev, ret, "%s: control initialization error %d\n",
+ __func__, ov5645->ctrls.error);
goto free_ctrl;
}
@@ -1192,7 +1174,7 @@ static int ov5645_probe(struct i2c_client *client)
ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
if (ret < 0) {
- dev_err(dev, "could not register media entity\n");
+ dev_err_probe(dev, ret, "could not register media entity\n");
goto free_ctrl;
}
@@ -1202,14 +1184,14 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
- dev_err(dev, "could not read ID high\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read ID high\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
- dev_err(dev, "could not read ID low\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read ID low\n");
goto power_down;
}
@@ -1218,24 +1200,24 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
&ov5645->aec_pk_manual);
if (ret < 0) {
- dev_err(dev, "could not read AEC/AGC mode\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
&ov5645->timing_tc_reg20);
if (ret < 0) {
- dev_err(dev, "could not read vflip value\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read vflip value\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
&ov5645->timing_tc_reg21);
if (ret < 0) {
- dev_err(dev, "could not read hflip value\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read hflip value\n");
goto power_down;
}
@@ -1243,7 +1225,7 @@ static int ov5645_probe(struct i2c_client *client)
ret = v4l2_async_register_subdev(&ov5645->sd);
if (ret < 0) {
- dev_err(dev, "could not register v4l2 device\n");
+ dev_err_probe(dev, ret, "could not register v4l2 device\n");
goto power_down;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor()
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (3 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:44 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex Prabhakar
` (5 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Make use v4l2_async_register_subdev_sensor() helper to register
the subdev.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 9e6ff1f1b9ac..45687d004004 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1223,7 +1223,7 @@ static int ov5645_probe(struct i2c_client *client)
ov5645_init_state(&ov5645->sd, NULL);
- ret = v4l2_async_register_subdev(&ov5645->sd);
+ ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
if (ret < 0) {
dev_err_probe(dev, ret, "could not register v4l2 device\n");
goto power_down;
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (4 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor() Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:46 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state Prabhakar
` (4 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Drop mutex while applying controls and just rely on
pm_runtime_get_if_in_use() call.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 45687d004004..25c60afcc0ec 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -106,8 +106,6 @@ struct ov5645 {
u8 timing_tc_reg20;
u8 timing_tc_reg21;
- struct mutex power_lock; /* lock to protect power state */
-
struct gpio_desc *enable_gpio;
struct gpio_desc *rst_gpio;
};
@@ -782,11 +780,8 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
struct ov5645, ctrls);
int ret;
- mutex_lock(&ov5645->power_lock);
- if (!pm_runtime_get_if_in_use(ov5645->dev)) {
- mutex_unlock(&ov5645->power_lock);
+ if (!pm_runtime_get_if_in_use(ov5645->dev))
return 0;
- }
switch (ctrl->id) {
case V4L2_CID_SATURATION:
@@ -817,7 +812,6 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev);
- mutex_unlock(&ov5645->power_lock);
return ret;
}
@@ -1124,8 +1118,6 @@ static int ov5645_probe(struct i2c_client *client)
if (IS_ERR(ov5645->rst_gpio))
return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio), "cannot get reset gpio\n");
- mutex_init(&ov5645->power_lock);
-
v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_SATURATION, -4, 4, 1, 0);
@@ -1245,7 +1237,6 @@ static int ov5645_probe(struct i2c_client *client)
media_entity_cleanup(&ov5645->sd.entity);
free_ctrl:
v4l2_ctrl_handler_free(&ov5645->ctrls);
- mutex_destroy(&ov5645->power_lock);
return ret;
}
@@ -1262,7 +1253,6 @@ static void ov5645_remove(struct i2c_client *client)
if (!pm_runtime_status_suspended(ov5645->dev))
ov5645_set_power_off(ov5645->dev);
pm_runtime_set_suspended(ov5645->dev);
- mutex_destroy(&ov5645->power_lock);
}
static const struct i2c_device_id ov5645_id[] = {
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (5 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:51 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams Prabhakar
` (3 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Port the ov5645 sensor driver to use the subdev active state.
Move all the format configuration to the subdevice state and simplify
the format handling, locking and initialization.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 109 +++++++++++++------------------------
1 file changed, 39 insertions(+), 70 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 25c60afcc0ec..9497ec737cb7 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -89,7 +89,6 @@ struct ov5645 {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_fwnode_endpoint ep;
- struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct clk *xclk;
@@ -850,49 +849,6 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
return 0;
}
-static struct v4l2_mbus_framefmt *
-__ov5645_get_pad_format(struct ov5645 *ov5645,
- struct v4l2_subdev_state *sd_state,
- unsigned int pad,
- enum v4l2_subdev_format_whence which)
-{
- switch (which) {
- case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_state_get_format(sd_state, pad);
- case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &ov5645->fmt;
- default:
- return NULL;
- }
-}
-
-static int ov5645_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
-{
- struct ov5645 *ov5645 = to_ov5645(sd);
-
- format->format = *__ov5645_get_pad_format(ov5645, sd_state,
- format->pad,
- format->which);
- return 0;
-}
-
-static struct v4l2_rect *
-__ov5645_get_pad_crop(struct ov5645 *ov5645,
- struct v4l2_subdev_state *sd_state,
- unsigned int pad, enum v4l2_subdev_format_whence which)
-{
- switch (which) {
- case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_state_get_crop(sd_state, pad);
- case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &ov5645->crop;
- default:
- return NULL;
- }
-}
-
static int ov5645_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
@@ -903,33 +859,30 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
const struct ov5645_mode_info *new_mode;
int ret;
- __crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad,
- format->which);
-
+ __crop = v4l2_subdev_state_get_crop(sd_state, 0);
new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
- ARRAY_SIZE(ov5645_mode_info_data),
- width, height,
- format->format.width, format->format.height);
+ ARRAY_SIZE(ov5645_mode_info_data),
+ width, height, format->format.width,
+ format->format.height);
__crop->width = new_mode->width;
__crop->height = new_mode->height;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- ret = v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
- new_mode->pixel_clock);
+ ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
+ new_mode->pixel_clock);
if (ret < 0)
return ret;
- ret = v4l2_ctrl_s_ctrl(ov5645->link_freq,
- new_mode->link_freq);
+ ret = __v4l2_ctrl_s_ctrl(ov5645->link_freq,
+ new_mode->link_freq);
if (ret < 0)
return ret;
ov5645->current_mode = new_mode;
}
- __format = __ov5645_get_pad_format(ov5645, sd_state, format->pad,
- format->which);
+ __format = v4l2_subdev_state_get_format(sd_state, 0);
__format->width = __crop->width;
__format->height = __crop->height;
__format->code = MEDIA_BUS_FMT_UYVY8_1X16;
@@ -944,11 +897,15 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
static int ov5645_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state)
{
- struct v4l2_subdev_format fmt = { 0 };
-
- fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- fmt.format.width = 1920;
- fmt.format.height = 1080;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .pad = 0,
+ .format = {
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .width = ov5645_mode_info_data[1].width,
+ .height = ov5645_mode_info_data[1].height,
+ },
+ };
ov5645_set_format(subdev, sd_state, &fmt);
@@ -959,25 +916,27 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
- struct ov5645 *ov5645 = to_ov5645(sd);
-
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad,
- sel->which);
+ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
return 0;
}
static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
{
struct ov5645 *ov5645 = to_ov5645(subdev);
+ struct v4l2_subdev_state *state;
int ret;
+ state = v4l2_subdev_lock_and_get_active_state(&ov5645->sd);
+
if (enable) {
ret = pm_runtime_resume_and_get(ov5645->dev);
- if (ret < 0)
+ if (ret < 0) {
+ v4l2_subdev_unlock_state(state);
return ret;
+ }
ret = ov5645_set_register_array(ov5645,
ov5645->current_mode->data,
@@ -988,7 +947,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
ov5645->current_mode->height);
goto err_rpm_put;
}
- ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);
+ ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
if (ret < 0) {
dev_err(ov5645->dev, "could not sync v4l2 controls\n");
goto err_rpm_put;
@@ -1013,6 +972,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
goto stream_off_rpm_put;
}
+ v4l2_subdev_unlock_state(state);
return 0;
err_rpm_put:
@@ -1022,6 +982,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
stream_off_rpm_put:
pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev);
+ v4l2_subdev_unlock_state(state);
return ret;
}
@@ -1032,7 +993,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
.enum_mbus_code = ov5645_enum_mbus_code,
.enum_frame_size = ov5645_enum_frame_size,
- .get_fmt = ov5645_get_format,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ov5645_set_format,
.get_selection = ov5645_get_selection,
};
@@ -1213,12 +1174,17 @@ static int ov5645_probe(struct i2c_client *client)
goto power_down;
}
- ov5645_init_state(&ov5645->sd, NULL);
+ ov5645->sd.state_lock = ov5645->ctrls.lock;
+ ret = v4l2_subdev_init_finalize(&ov5645->sd);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "subdev init error\n");
+ goto power_down;
+ }
ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
if (ret < 0) {
dev_err_probe(dev, ret, "could not register v4l2 device\n");
- goto power_down;
+ goto error_subdev_cleanup;
}
pm_runtime_set_active(dev);
@@ -1231,6 +1197,8 @@ static int ov5645_probe(struct i2c_client *client)
return 0;
+error_subdev_cleanup:
+ v4l2_subdev_cleanup(&ov5645->sd);
power_down:
ov5645_set_power_off(dev);
free_entity:
@@ -1247,6 +1215,7 @@ static void ov5645_remove(struct i2c_client *client)
struct ov5645 *ov5645 = to_ov5645(sd);
v4l2_async_unregister_subdev(&ov5645->sd);
+ v4l2_subdev_cleanup(sd);
media_entity_cleanup(&ov5645->sd.entity);
v4l2_ctrl_handler_free(&ov5645->ctrls);
pm_runtime_disable(ov5645->dev);
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (6 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-24 22:55 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad Prabhakar
` (2 subsequent siblings)
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Switch from s_stream to enable_streams and disable_streams callbacks.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 90 +++++++++++++++++++-------------------
1 file changed, 46 insertions(+), 44 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 9497ec737cb7..dc93514608ee 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -923,71 +923,71 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
return 0;
}
-static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
+static int ov5645_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
- struct ov5645 *ov5645 = to_ov5645(subdev);
- struct v4l2_subdev_state *state;
+ struct ov5645 *ov5645 = to_ov5645(sd);
int ret;
- state = v4l2_subdev_lock_and_get_active_state(&ov5645->sd);
-
- if (enable) {
- ret = pm_runtime_resume_and_get(ov5645->dev);
- if (ret < 0) {
- v4l2_subdev_unlock_state(state);
- return ret;
- }
+ ret = pm_runtime_resume_and_get(ov5645->dev);
+ if (ret < 0)
+ return ret;
- ret = ov5645_set_register_array(ov5645,
+ ret = ov5645_set_register_array(ov5645,
ov5645->current_mode->data,
ov5645->current_mode->data_size);
- if (ret < 0) {
- dev_err(ov5645->dev, "could not set mode %dx%d\n",
- ov5645->current_mode->width,
- ov5645->current_mode->height);
- goto err_rpm_put;
- }
- ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
- if (ret < 0) {
- dev_err(ov5645->dev, "could not sync v4l2 controls\n");
- goto err_rpm_put;
- }
-
- ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
- if (ret < 0)
- goto err_rpm_put;
-
- ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
- OV5645_SYSTEM_CTRL0_START);
- if (ret < 0)
- goto err_rpm_put;
- } else {
- ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
- if (ret < 0)
- goto stream_off_rpm_put;
+ if (ret < 0) {
+ dev_err(ov5645->dev, "could not set mode %dx%d\n",
+ ov5645->current_mode->width,
+ ov5645->current_mode->height);
+ goto err_rpm_put;
+ }
+ ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
+ if (ret < 0) {
+ dev_err(ov5645->dev, "could not sync v4l2 controls\n");
+ goto err_rpm_put;
+ }
- ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
- OV5645_SYSTEM_CTRL0_STOP);
+ ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
+ if (ret < 0)
+ goto err_rpm_put;
- goto stream_off_rpm_put;
- }
+ ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
+ OV5645_SYSTEM_CTRL0_START);
+ if (ret < 0)
+ goto err_rpm_put;
- v4l2_subdev_unlock_state(state);
return 0;
err_rpm_put:
pm_runtime_put_sync(ov5645->dev);
return ret;
+}
+
+static int ov5645_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct ov5645 *ov5645 = to_ov5645(sd);
+ int ret;
+
+ ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
+ if (ret < 0)
+ goto rpm_put;
+
+ ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
+ OV5645_SYSTEM_CTRL0_STOP);
-stream_off_rpm_put:
+rpm_put:
pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev);
- v4l2_subdev_unlock_state(state);
+
return ret;
}
static const struct v4l2_subdev_video_ops ov5645_video_ops = {
- .s_stream = ov5645_s_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
@@ -996,6 +996,8 @@ static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ov5645_set_format,
.get_selection = ov5645_get_selection,
+ .enable_streams = ov5645_enable_streams,
+ .disable_streams = ov5645_disable_streams,
};
static const struct v4l2_subdev_core_ops ov5645_core_ops = {
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (7 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-25 16:21 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 10/11] media: i2c: ov5645: Report internal routes to userspace Prabhakar
2024-09-10 17:06 ` [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors Prabhakar
10 siblings, 1 reply; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Use the newly added internal pad API to expose the internal
configuration of the sensor to userspace in a standard manner.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 107 +++++++++++++++++++++++++++----------
1 file changed, 79 insertions(+), 28 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index dc93514608ee..255c6395a268 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -60,6 +60,10 @@
#define OV5645_SDE_SAT_U 0x5583
#define OV5645_SDE_SAT_V 0x5584
+#define OV5645_NATIVE_FORMAT MEDIA_BUS_FMT_SBGGR8_1X8
+#define OV5645_NATIVE_WIDTH 2592
+#define OV5645_NATIVE_HEIGHT 1944
+
/* regulator supplies */
static const char * const ov5645_supply_name[] = {
"vdddo", /* Digital I/O (1.8V) supply */
@@ -69,6 +73,12 @@ static const char * const ov5645_supply_name[] = {
#define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)
+enum ov5645_pad_ids {
+ OV5645_PAD_SOURCE,
+ OV5645_PAD_IMAGE,
+ OV5645_NUM_PADS,
+};
+
struct reg_value {
u16 reg;
u8 val;
@@ -87,7 +97,7 @@ struct ov5645 {
struct i2c_client *i2c_client;
struct device *dev;
struct v4l2_subdev sd;
- struct media_pad pad;
+ struct media_pad pads[OV5645_NUM_PADS];
struct v4l2_fwnode_endpoint ep;
struct v4l2_rect crop;
struct clk *xclk;
@@ -826,7 +836,10 @@ static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index > 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_UYVY8_1X16;
+ if (code->pad == OV5645_PAD_IMAGE)
+ code->code = OV5645_NATIVE_FORMAT;
+ else
+ code->code = MEDIA_BUS_FMT_UYVY8_1X16;
return 0;
}
@@ -835,16 +848,24 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
- return -EINVAL;
-
- if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
- return -EINVAL;
-
- fse->min_width = ov5645_mode_info_data[fse->index].width;
- fse->max_width = ov5645_mode_info_data[fse->index].width;
- fse->min_height = ov5645_mode_info_data[fse->index].height;
- fse->max_height = ov5645_mode_info_data[fse->index].height;
+ if (fse->pad == OV5645_PAD_IMAGE) {
+ if (fse->code != OV5645_NATIVE_FORMAT || fse->index > 0)
+ return -EINVAL;
+
+ fse->min_width = OV5645_NATIVE_WIDTH;
+ fse->max_width = OV5645_NATIVE_WIDTH;
+ fse->min_height = OV5645_NATIVE_HEIGHT;
+ fse->max_height = OV5645_NATIVE_HEIGHT;
+ } else {
+ if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16 ||
+ fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
+ return -EINVAL;
+
+ fse->min_width = ov5645_mode_info_data[fse->index].width;
+ fse->max_width = ov5645_mode_info_data[fse->index].width;
+ fse->min_height = ov5645_mode_info_data[fse->index].height;
+ fse->max_height = ov5645_mode_info_data[fse->index].height;
+ }
return 0;
}
@@ -855,18 +876,55 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
{
struct ov5645 *ov5645 = to_ov5645(sd);
struct v4l2_mbus_framefmt *__format;
+ struct v4l2_rect *compose;
struct v4l2_rect *__crop;
const struct ov5645_mode_info *new_mode;
int ret;
- __crop = v4l2_subdev_state_get_crop(sd_state, 0);
+ if (format->pad != OV5645_PAD_SOURCE)
+ return v4l2_subdev_get_fmt(sd, sd_state, format);
+
new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
ARRAY_SIZE(ov5645_mode_info_data),
width, height, format->format.width,
format->format.height);
-
- __crop->width = new_mode->width;
- __crop->height = new_mode->height;
+ format->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
+ format->format.width = new_mode->width;
+ format->format.height = new_mode->height;
+ format->format.field = V4L2_FIELD_NONE;
+ format->format.colorspace = V4L2_COLORSPACE_SRGB;
+ format->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ format->format.quantization = V4L2_QUANTIZATION_DEFAULT;
+ format->format.xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+ __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE);
+ *__format = format->format;
+ __format->code = OV5645_NATIVE_FORMAT;
+ __format->width = OV5645_NATIVE_WIDTH;
+ __format->height = OV5645_NATIVE_HEIGHT;
+
+ __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE);
+ __crop->width = format->format.width;
+ __crop->height = format->format.height;
+
+ /*
+ * The compose rectangle models binning, its size is the sensor output
+ * size.
+ */
+ compose = v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE);
+ compose->left = 0;
+ compose->top = 0;
+ compose->width = format->format.width;
+ compose->height = format->format.height;
+
+ __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE);
+ __crop->left = 0;
+ __crop->top = 0;
+ __crop->width = format->format.width;
+ __crop->height = format->format.height;
+
+ __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE);
+ *__format = format->format;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
@@ -882,14 +940,6 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
ov5645->current_mode = new_mode;
}
- __format = v4l2_subdev_state_get_format(sd_state, 0);
- __format->width = __crop->width;
- __format->height = __crop->height;
- __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
- __format->field = V4L2_FIELD_NONE;
- __format->colorspace = V4L2_COLORSPACE_SRGB;
-
- format->format = *__format;
return 0;
}
@@ -899,7 +949,7 @@ static int ov5645_init_state(struct v4l2_subdev *subdev,
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
- .pad = 0,
+ .pad = OV5645_PAD_SOURCE,
.format = {
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.width = ov5645_mode_info_data[1].width,
@@ -919,7 +969,7 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
+ sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
return 0;
}
@@ -1123,11 +1173,12 @@ static int ov5645_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
- ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ov5645->pads[OV5645_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ ov5645->pads[OV5645_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
ov5645->sd.dev = dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
- ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
+ ret = media_entity_pads_init(&ov5645->sd.entity, ARRAY_SIZE(ov5645->pads), ov5645->pads);
if (ret < 0) {
dev_err_probe(dev, ret, "could not register media entity\n");
goto free_ctrl;
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 10/11] media: i2c: ov5645: Report internal routes to userspace
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (8 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-10 17:06 ` [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors Prabhakar
10 siblings, 0 replies; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Usage of internal pads creates a route internal to the subdev, and the
V4L2 camera sensor API requires such routes to be reported to userspace.
Create the route in the .init_state() operation.
Internal routing support requires stream support, so set the
V4L2_SUBDEV_FL_HAS_STREAMS flag and switch formats and selection
rectangles access from pads to streams. As the route is immutable,
there's no need to implement the .set_routing() operation, and we can
hardcode the sink and source stream IDs to 0.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 255c6395a268..7f1133292ffc 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -947,15 +947,36 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
static int ov5645_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state)
{
+ struct v4l2_subdev_route routes[1] = {
+ {
+ .sink_pad = OV5645_PAD_IMAGE,
+ .sink_stream = 0,
+ .source_pad = OV5645_PAD_SOURCE,
+ .source_stream = 0,
+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+ V4L2_SUBDEV_ROUTE_FL_IMMUTABLE,
+ },
+ };
+ struct v4l2_subdev_krouting routing = {
+ .len_routes = ARRAY_SIZE(routes),
+ .num_routes = ARRAY_SIZE(routes),
+ .routes = routes,
+ };
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
.pad = OV5645_PAD_SOURCE,
+ .stream = 0,
.format = {
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.width = ov5645_mode_info_data[1].width,
.height = ov5645_mode_info_data[1].height,
},
};
+ int ret;
+
+ ret = v4l2_subdev_set_routing(subdev, sd_state, &routing);
+ if (ret)
+ return ret;
ov5645_set_format(subdev, sd_state, &fmt);
@@ -1172,7 +1193,8 @@ static int ov5645_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
ov5645->sd.internal_ops = &ov5645_internal_ops;
- ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+ ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS |
+ V4L2_SUBDEV_FL_STREAMS;
ov5645->pads[OV5645_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ov5645->pads[OV5645_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
ov5645->sd.dev = dev;
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
` (9 preceding siblings ...)
2024-09-10 17:06 ` [PATCH v2 10/11] media: i2c: ov5645: Report internal routes to userspace Prabhakar
@ 2024-09-10 17:06 ` Prabhakar
2024-09-25 16:26 ` Laurent Pinchart
2024-09-26 15:45 ` Sakari Ailus
10 siblings, 2 replies; 34+ messages in thread
From: Prabhakar @ 2024-09-10 17:06 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart, Kieran Bingham, Tomi Valkeinen,
Jacopo Mondi, Mauro Carvalho Chehab, Hans Verkuil
Cc: linux-media, linux-kernel, linux-renesas-soc, Prabhakar, Biju Das,
Fabrizio Castro, Lad Prabhakar
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Implement the .get_frame_desc() subdev operation to report information
about streams to the connected CSI-2 receiver. This is required to let
the CSI-2 receiver driver know about virtual channels and data types for
each stream.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 7f1133292ffc..c24eb6e7a7b5 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -28,6 +28,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <media/mipi-csi2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
@@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
.s_ctrl = ov5645_s_ctrl,
};
+static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_frame_desc *fd)
+{
+ const struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_subdev_state *state;
+
+ if (pad != OV5645_PAD_SOURCE)
+ return -EINVAL;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+ fmt = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0);
+ v4l2_subdev_unlock_state(state);
+
+ fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+ fd->num_entries = 1;
+
+ memset(fd->entry, 0, sizeof(fd->entry));
+
+ fd->entry[0].pixelcode = fmt->code;
+ fd->entry[0].stream = 0;
+ fd->entry[0].bus.csi2.vc = 0;
+ fd->entry[0].bus.csi2.dt = MIPI_CSI2_DT_YUV422_8B;
+
+ return 0;
+}
+
static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
@@ -1062,6 +1089,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
+ .get_frame_desc = ov5645_get_frame_desc,
.enum_mbus_code = ov5645_enum_mbus_code,
.enum_frame_size = ov5645_enum_frame_size,
.get_fmt = v4l2_subdev_get_fmt,
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks
2024-09-10 17:06 ` [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Prabhakar
@ 2024-09-24 22:35 ` Laurent Pinchart
0 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:35 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:00PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> The OV5645 sensor exposes controls, so the V4L2_SUBDEV_FL_HAS_EVENTS flag
> should be set and implement subscribe_event and unsubscribe_event hooks.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 019979f553b1..6eedd0310b02 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -29,6 +29,7 @@
> #include <linux/slab.h>
> #include <linux/types.h>
> #include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> #include <media/v4l2-fwnode.h>
> #include <media/v4l2-subdev.h>
>
> @@ -1042,7 +1043,13 @@ static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> .get_selection = ov5645_get_selection,
> };
>
> +static const struct v4l2_subdev_core_ops ov5645_core_ops = {
> + .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
> + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
> +};
> +
> static const struct v4l2_subdev_ops ov5645_subdev_ops = {
> + .core = &ov5645_core_ops,
> .video = &ov5645_video_ops,
> .pad = &ov5645_subdev_pad_ops,
> };
> @@ -1178,7 +1185,7 @@ static int ov5645_probe(struct i2c_client *client)
>
> v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
> ov5645->sd.internal_ops = &ov5645_internal_ops;
> - ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> + ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
> ov5645->sd.dev = &client->dev;
> ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> --
> 2.34.1
>
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment
2024-09-10 17:06 ` [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment Prabhakar
@ 2024-09-24 22:35 ` Laurent Pinchart
0 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:35 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
On Tue, Sep 10, 2024 at 06:06:01PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> While assigning the subdev device pointer, use the local `dev` pointer
> which is already extracted from the `i2c_client` pointer.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 6eedd0310b02..ab3a419df2df 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -1187,7 +1187,7 @@ static int ov5645_probe(struct i2c_client *client)
> ov5645->sd.internal_ops = &ov5645_internal_ops;
> ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
> - ov5645->sd.dev = &client->dev;
> + ov5645->sd.dev = dev;
> ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
>
> ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev()
2024-09-10 17:06 ` [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev() Prabhakar
@ 2024-09-24 22:37 ` Laurent Pinchart
2024-09-25 15:22 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:37 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:02PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> To simplify the probe error path, enable runtime PM after the
> v4l2_async_register_subdev() call.
>
> This change ensures that runtime PM is only enabled once the subdevice
> registration is successful, avoiding unnecessary cleanup in the error
> path.
The subdev could start being used as soon as it gets registered, so
runtime PM initialization should happen before
v4l2_async_register_subdev().
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> drivers/media/i2c/ov5645.c | 12 ++++--------
> 1 file changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index ab3a419df2df..78b86438c798 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -1239,18 +1239,17 @@ static int ov5645_probe(struct i2c_client *client)
> goto power_down;
> }
>
> - pm_runtime_set_active(dev);
> - pm_runtime_get_noresume(dev);
> - pm_runtime_enable(dev);
> -
> ov5645_init_state(&ov5645->sd, NULL);
>
> ret = v4l2_async_register_subdev(&ov5645->sd);
> if (ret < 0) {
> dev_err(dev, "could not register v4l2 device\n");
> - goto err_pm_runtime;
> + goto power_down;
> }
>
> + pm_runtime_set_active(dev);
> + pm_runtime_get_noresume(dev);
> + pm_runtime_enable(dev);
> pm_runtime_set_autosuspend_delay(dev, 1000);
> pm_runtime_use_autosuspend(dev);
> pm_runtime_mark_last_busy(dev);
> @@ -1258,9 +1257,6 @@ static int ov5645_probe(struct i2c_client *client)
>
> return 0;
>
> -err_pm_runtime:
> - pm_runtime_disable(dev);
> - pm_runtime_put_noidle(dev);
> power_down:
> ov5645_set_power_off(dev);
> free_entity:
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err
2024-09-10 17:06 ` [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err Prabhakar
@ 2024-09-24 22:43 ` Laurent Pinchart
2024-09-25 15:24 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:43 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:03PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Drop dev_err() and use the dev_err_probe() helper on probe path.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> drivers/media/i2c/ov5645.c | 74 +++++++++++++++-----------------------
> 1 file changed, 28 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 78b86438c798..9e6ff1f1b9ac 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -1076,51 +1076,37 @@ static int ov5645_probe(struct i2c_client *client)
> ov5645->dev = dev;
>
> endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
> - if (!endpoint) {
> - dev_err(dev, "endpoint node not found\n");
> - return -EINVAL;
> - }
> + if (!endpoint)
> + return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
>
> ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
> &ov5645->ep);
>
> of_node_put(endpoint);
>
> - if (ret < 0) {
> - dev_err(dev, "parsing endpoint node failed\n");
> - return ret;
> - }
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "parsing endpoint node failed\n");
>
> - if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
> - dev_err(dev, "invalid bus type, must be CSI2\n");
> - return -EINVAL;
> - }
> + if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
> + return dev_err_probe(dev, -EINVAL, "invalid bus type, must be CSI2\n");
>
> /* get system clock (xclk) */
> ov5645->xclk = devm_clk_get(dev, NULL);
> - if (IS_ERR(ov5645->xclk)) {
> - dev_err(dev, "could not get xclk");
> - return PTR_ERR(ov5645->xclk);
> - }
> + if (IS_ERR(ov5645->xclk))
> + return dev_err_probe(dev, PTR_ERR(ov5645->xclk), "could not get xclk");
>
> ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
> - if (ret) {
> - dev_err(dev, "could not get xclk frequency\n");
> - return ret;
> - }
> + if (ret)
> + return dev_err_probe(dev, ret, "could not get xclk frequency\n");
>
> /* external clock must be 24MHz, allow 1% tolerance */
> - if (xclk_freq < 23760000 || xclk_freq > 24240000) {
> - dev_err(dev, "external clock frequency %u is not supported\n",
> - xclk_freq);
> - return -EINVAL;
> - }
> + if (xclk_freq < 23760000 || xclk_freq > 24240000)
> + return dev_err_probe(dev, -EINVAL, "external clock frequency %u is not supported\n",
> + xclk_freq);
>
> ret = clk_set_rate(ov5645->xclk, xclk_freq);
> - if (ret) {
> - dev_err(dev, "could not set xclk frequency\n");
> - return ret;
> - }
> + if (ret)
> + return dev_err_probe(dev, ret, "could not set xclk frequency\n");
>
> for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
> ov5645->supplies[i].supply = ov5645_supply_name[i];
> @@ -1131,16 +1117,12 @@ static int ov5645_probe(struct i2c_client *client)
> return ret;
>
> ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
> - if (IS_ERR(ov5645->enable_gpio)) {
> - dev_err(dev, "cannot get enable gpio\n");
> - return PTR_ERR(ov5645->enable_gpio);
> - }
> + if (IS_ERR(ov5645->enable_gpio))
> + return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio), "cannot get enable gpio\n");
Those lines are getting long. We usually try to wrap at 80 columns for
sensor drivers:
return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio),
"cannot get enable gpio\n");
Same elsewhere. I'll let Sakari decide.
>
> ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> - if (IS_ERR(ov5645->rst_gpio)) {
> - dev_err(dev, "cannot get reset gpio\n");
> - return PTR_ERR(ov5645->rst_gpio);
> - }
> + if (IS_ERR(ov5645->rst_gpio))
> + return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio), "cannot get reset gpio\n");
>
> mutex_init(&ov5645->power_lock);
>
> @@ -1177,9 +1159,9 @@ static int ov5645_probe(struct i2c_client *client)
> ov5645->sd.ctrl_handler = &ov5645->ctrls;
>
> if (ov5645->ctrls.error) {
> - dev_err(dev, "%s: control initialization error %d\n",
> - __func__, ov5645->ctrls.error);
> ret = ov5645->ctrls.error;
> + dev_err_probe(dev, ret, "%s: control initialization error %d\n",
> + __func__, ov5645->ctrls.error);
> goto free_ctrl;
> }
>
> @@ -1192,7 +1174,7 @@ static int ov5645_probe(struct i2c_client *client)
>
> ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
> if (ret < 0) {
> - dev_err(dev, "could not register media entity\n");
> + dev_err_probe(dev, ret, "could not register media entity\n");
> goto free_ctrl;
> }
>
> @@ -1202,14 +1184,14 @@ static int ov5645_probe(struct i2c_client *client)
>
> ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
> if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
> - dev_err(dev, "could not read ID high\n");
> ret = -ENODEV;
> + dev_err_probe(dev, ret, "could not read ID high\n");
> goto power_down;
> }
> ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
> if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
> - dev_err(dev, "could not read ID low\n");
> ret = -ENODEV;
> + dev_err_probe(dev, ret, "could not read ID low\n");
> goto power_down;
> }
>
> @@ -1218,24 +1200,24 @@ static int ov5645_probe(struct i2c_client *client)
> ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
> &ov5645->aec_pk_manual);
> if (ret < 0) {
> - dev_err(dev, "could not read AEC/AGC mode\n");
> ret = -ENODEV;
> + dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
> goto power_down;
> }
>
> ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
> &ov5645->timing_tc_reg20);
> if (ret < 0) {
> - dev_err(dev, "could not read vflip value\n");
> ret = -ENODEV;
> + dev_err_probe(dev, ret, "could not read vflip value\n");
> goto power_down;
> }
>
> ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
> &ov5645->timing_tc_reg21);
> if (ret < 0) {
> - dev_err(dev, "could not read hflip value\n");
> ret = -ENODEV;
> + dev_err_probe(dev, ret, "could not read hflip value\n");
> goto power_down;
> }
>
> @@ -1243,7 +1225,7 @@ static int ov5645_probe(struct i2c_client *client)
>
> ret = v4l2_async_register_subdev(&ov5645->sd);
> if (ret < 0) {
> - dev_err(dev, "could not register v4l2 device\n");
> + dev_err_probe(dev, ret, "could not register v4l2 device\n");
> goto power_down;
> }
>
The probe function looks really young, I think it would benefit from
being broken down in multiple functions.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor()
2024-09-10 17:06 ` [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor() Prabhakar
@ 2024-09-24 22:44 ` Laurent Pinchart
2024-09-25 15:26 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:44 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
On Tue, Sep 10, 2024 at 06:06:04PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Make use v4l2_async_register_subdev_sensor() helper to register
> the subdev.
The commit message should explain why.
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 9e6ff1f1b9ac..45687d004004 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -1223,7 +1223,7 @@ static int ov5645_probe(struct i2c_client *client)
>
> ov5645_init_state(&ov5645->sd, NULL);
>
> - ret = v4l2_async_register_subdev(&ov5645->sd);
> + ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
> if (ret < 0) {
> dev_err_probe(dev, ret, "could not register v4l2 device\n");
> goto power_down;
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex
2024-09-10 17:06 ` [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex Prabhakar
@ 2024-09-24 22:46 ` Laurent Pinchart
2024-09-25 15:35 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:46 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
On Tue, Sep 10, 2024 at 06:06:05PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Drop mutex while applying controls and just rely on
> pm_runtime_get_if_in_use() call.
Here too the commit message should explain why the mutex can be dropped.
Given that it is only used in .s_ctrl(), and the control framework
serializes calls to the function, the mutex is not needed.
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 12 +-----------
> 1 file changed, 1 insertion(+), 11 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 45687d004004..25c60afcc0ec 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -106,8 +106,6 @@ struct ov5645 {
> u8 timing_tc_reg20;
> u8 timing_tc_reg21;
>
> - struct mutex power_lock; /* lock to protect power state */
> -
> struct gpio_desc *enable_gpio;
> struct gpio_desc *rst_gpio;
> };
> @@ -782,11 +780,8 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
> struct ov5645, ctrls);
> int ret;
>
> - mutex_lock(&ov5645->power_lock);
> - if (!pm_runtime_get_if_in_use(ov5645->dev)) {
> - mutex_unlock(&ov5645->power_lock);
> + if (!pm_runtime_get_if_in_use(ov5645->dev))
> return 0;
> - }
>
> switch (ctrl->id) {
> case V4L2_CID_SATURATION:
> @@ -817,7 +812,6 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
>
> pm_runtime_mark_last_busy(ov5645->dev);
> pm_runtime_put_autosuspend(ov5645->dev);
> - mutex_unlock(&ov5645->power_lock);
>
> return ret;
> }
> @@ -1124,8 +1118,6 @@ static int ov5645_probe(struct i2c_client *client)
> if (IS_ERR(ov5645->rst_gpio))
> return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio), "cannot get reset gpio\n");
>
> - mutex_init(&ov5645->power_lock);
> -
> v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
> v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
> V4L2_CID_SATURATION, -4, 4, 1, 0);
> @@ -1245,7 +1237,6 @@ static int ov5645_probe(struct i2c_client *client)
> media_entity_cleanup(&ov5645->sd.entity);
> free_ctrl:
> v4l2_ctrl_handler_free(&ov5645->ctrls);
> - mutex_destroy(&ov5645->power_lock);
>
> return ret;
> }
> @@ -1262,7 +1253,6 @@ static void ov5645_remove(struct i2c_client *client)
> if (!pm_runtime_status_suspended(ov5645->dev))
> ov5645_set_power_off(ov5645->dev);
> pm_runtime_set_suspended(ov5645->dev);
> - mutex_destroy(&ov5645->power_lock);
> }
>
> static const struct i2c_device_id ov5645_id[] = {
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state
2024-09-10 17:06 ` [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state Prabhakar
@ 2024-09-24 22:51 ` Laurent Pinchart
0 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:51 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:06PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Port the ov5645 sensor driver to use the subdev active state.
>
> Move all the format configuration to the subdevice state and simplify
> the format handling, locking and initialization.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 109 +++++++++++++------------------------
> 1 file changed, 39 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 25c60afcc0ec..9497ec737cb7 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -89,7 +89,6 @@ struct ov5645 {
> struct v4l2_subdev sd;
> struct media_pad pad;
> struct v4l2_fwnode_endpoint ep;
> - struct v4l2_mbus_framefmt fmt;
> struct v4l2_rect crop;
> struct clk *xclk;
>
> @@ -850,49 +849,6 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
> return 0;
> }
>
> -static struct v4l2_mbus_framefmt *
> -__ov5645_get_pad_format(struct ov5645 *ov5645,
> - struct v4l2_subdev_state *sd_state,
> - unsigned int pad,
> - enum v4l2_subdev_format_whence which)
> -{
> - switch (which) {
> - case V4L2_SUBDEV_FORMAT_TRY:
> - return v4l2_subdev_state_get_format(sd_state, pad);
> - case V4L2_SUBDEV_FORMAT_ACTIVE:
> - return &ov5645->fmt;
> - default:
> - return NULL;
> - }
> -}
> -
> -static int ov5645_get_format(struct v4l2_subdev *sd,
> - struct v4l2_subdev_state *sd_state,
> - struct v4l2_subdev_format *format)
> -{
> - struct ov5645 *ov5645 = to_ov5645(sd);
> -
> - format->format = *__ov5645_get_pad_format(ov5645, sd_state,
> - format->pad,
> - format->which);
> - return 0;
> -}
> -
> -static struct v4l2_rect *
> -__ov5645_get_pad_crop(struct ov5645 *ov5645,
> - struct v4l2_subdev_state *sd_state,
> - unsigned int pad, enum v4l2_subdev_format_whence which)
> -{
> - switch (which) {
> - case V4L2_SUBDEV_FORMAT_TRY:
> - return v4l2_subdev_state_get_crop(sd_state, pad);
> - case V4L2_SUBDEV_FORMAT_ACTIVE:
> - return &ov5645->crop;
> - default:
> - return NULL;
> - }
> -}
> -
> static int ov5645_set_format(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_format *format)
> @@ -903,33 +859,30 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> const struct ov5645_mode_info *new_mode;
> int ret;
>
> - __crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad,
> - format->which);
> -
> + __crop = v4l2_subdev_state_get_crop(sd_state, 0);
> new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
> - ARRAY_SIZE(ov5645_mode_info_data),
> - width, height,
> - format->format.width, format->format.height);
> + ARRAY_SIZE(ov5645_mode_info_data),
> + width, height, format->format.width,
> + format->format.height);
>
> __crop->width = new_mode->width;
> __crop->height = new_mode->height;
>
> if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> - ret = v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
> - new_mode->pixel_clock);
> + ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
> + new_mode->pixel_clock);
> if (ret < 0)
> return ret;
>
> - ret = v4l2_ctrl_s_ctrl(ov5645->link_freq,
> - new_mode->link_freq);
> + ret = __v4l2_ctrl_s_ctrl(ov5645->link_freq,
> + new_mode->link_freq);
> if (ret < 0)
> return ret;
>
> ov5645->current_mode = new_mode;
> }
>
> - __format = __ov5645_get_pad_format(ov5645, sd_state, format->pad,
> - format->which);
> + __format = v4l2_subdev_state_get_format(sd_state, 0);
> __format->width = __crop->width;
> __format->height = __crop->height;
> __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
> @@ -944,11 +897,15 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> static int ov5645_init_state(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *sd_state)
> {
> - struct v4l2_subdev_format fmt = { 0 };
> -
> - fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
> - fmt.format.width = 1920;
> - fmt.format.height = 1080;
> + struct v4l2_subdev_format fmt = {
> + .which = V4L2_SUBDEV_FORMAT_TRY,
> + .pad = 0,
> + .format = {
> + .code = MEDIA_BUS_FMT_UYVY8_1X16,
> + .width = ov5645_mode_info_data[1].width,
> + .height = ov5645_mode_info_data[1].height,
> + },
> + };
>
> ov5645_set_format(subdev, sd_state, &fmt);
>
> @@ -959,25 +916,27 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_selection *sel)
> {
> - struct ov5645 *ov5645 = to_ov5645(sd);
> -
> if (sel->target != V4L2_SEL_TGT_CROP)
> return -EINVAL;
>
> - sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad,
> - sel->which);
> + sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
> return 0;
> }
>
> static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> {
> struct ov5645 *ov5645 = to_ov5645(subdev);
> + struct v4l2_subdev_state *state;
> int ret;
>
> + state = v4l2_subdev_lock_and_get_active_state(&ov5645->sd);
> +
> if (enable) {
> ret = pm_runtime_resume_and_get(ov5645->dev);
> - if (ret < 0)
> + if (ret < 0) {
> + v4l2_subdev_unlock_state(state);
> return ret;
> + }
>
> ret = ov5645_set_register_array(ov5645,
> ov5645->current_mode->data,
> @@ -988,7 +947,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> ov5645->current_mode->height);
> goto err_rpm_put;
> }
> - ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);
> + ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
> if (ret < 0) {
> dev_err(ov5645->dev, "could not sync v4l2 controls\n");
> goto err_rpm_put;
> @@ -1013,6 +972,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> goto stream_off_rpm_put;
> }
>
> + v4l2_subdev_unlock_state(state);
> return 0;
>
> err_rpm_put:
> @@ -1022,6 +982,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> stream_off_rpm_put:
> pm_runtime_mark_last_busy(ov5645->dev);
> pm_runtime_put_autosuspend(ov5645->dev);
> + v4l2_subdev_unlock_state(state);
> return ret;
> }
>
> @@ -1032,7 +993,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> .enum_mbus_code = ov5645_enum_mbus_code,
> .enum_frame_size = ov5645_enum_frame_size,
> - .get_fmt = ov5645_get_format,
> + .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = ov5645_set_format,
> .get_selection = ov5645_get_selection,
> };
> @@ -1213,12 +1174,17 @@ static int ov5645_probe(struct i2c_client *client)
> goto power_down;
> }
>
> - ov5645_init_state(&ov5645->sd, NULL);
> + ov5645->sd.state_lock = ov5645->ctrls.lock;
> + ret = v4l2_subdev_init_finalize(&ov5645->sd);
> + if (ret < 0) {
> + dev_err_probe(dev, ret, "subdev init error\n");
> + goto power_down;
> + }
>
> ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
> if (ret < 0) {
> dev_err_probe(dev, ret, "could not register v4l2 device\n");
> - goto power_down;
> + goto error_subdev_cleanup;
> }
>
> pm_runtime_set_active(dev);
> @@ -1231,6 +1197,8 @@ static int ov5645_probe(struct i2c_client *client)
>
> return 0;
>
> +error_subdev_cleanup:
> + v4l2_subdev_cleanup(&ov5645->sd);
> power_down:
> ov5645_set_power_off(dev);
> free_entity:
> @@ -1247,6 +1215,7 @@ static void ov5645_remove(struct i2c_client *client)
> struct ov5645 *ov5645 = to_ov5645(sd);
>
> v4l2_async_unregister_subdev(&ov5645->sd);
> + v4l2_subdev_cleanup(sd);
> media_entity_cleanup(&ov5645->sd.entity);
> v4l2_ctrl_handler_free(&ov5645->ctrls);
> pm_runtime_disable(ov5645->dev);
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams
2024-09-10 17:06 ` [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams Prabhakar
@ 2024-09-24 22:55 ` Laurent Pinchart
0 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-24 22:55 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:07PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Switch from s_stream to enable_streams and disable_streams callbacks.
Here too you should explain why. The "why" is the most important part of
any commit message.
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/media/i2c/ov5645.c | 90 +++++++++++++++++++-------------------
> 1 file changed, 46 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 9497ec737cb7..dc93514608ee 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -923,71 +923,71 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
> return 0;
> }
>
> -static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> +static int ov5645_enable_streams(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state, u32 pad,
> + u64 streams_mask)
> {
> - struct ov5645 *ov5645 = to_ov5645(subdev);
> - struct v4l2_subdev_state *state;
> + struct ov5645 *ov5645 = to_ov5645(sd);
> int ret;
>
> - state = v4l2_subdev_lock_and_get_active_state(&ov5645->sd);
> -
> - if (enable) {
> - ret = pm_runtime_resume_and_get(ov5645->dev);
> - if (ret < 0) {
> - v4l2_subdev_unlock_state(state);
> - return ret;
> - }
> + ret = pm_runtime_resume_and_get(ov5645->dev);
> + if (ret < 0)
> + return ret;
>
> - ret = ov5645_set_register_array(ov5645,
> + ret = ov5645_set_register_array(ov5645,
> ov5645->current_mode->data,
> ov5645->current_mode->data_size);
> - if (ret < 0) {
> - dev_err(ov5645->dev, "could not set mode %dx%d\n",
> - ov5645->current_mode->width,
> - ov5645->current_mode->height);
> - goto err_rpm_put;
> - }
> - ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
> - if (ret < 0) {
> - dev_err(ov5645->dev, "could not sync v4l2 controls\n");
> - goto err_rpm_put;
> - }
> -
> - ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
> - if (ret < 0)
> - goto err_rpm_put;
> -
> - ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> - OV5645_SYSTEM_CTRL0_START);
> - if (ret < 0)
> - goto err_rpm_put;
> - } else {
> - ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
> - if (ret < 0)
> - goto stream_off_rpm_put;
> + if (ret < 0) {
> + dev_err(ov5645->dev, "could not set mode %dx%d\n",
> + ov5645->current_mode->width,
> + ov5645->current_mode->height);
> + goto err_rpm_put;
> + }
> + ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
> + if (ret < 0) {
> + dev_err(ov5645->dev, "could not sync v4l2 controls\n");
> + goto err_rpm_put;
> + }
>
> - ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> - OV5645_SYSTEM_CTRL0_STOP);
> + ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
> + if (ret < 0)
> + goto err_rpm_put;
>
> - goto stream_off_rpm_put;
> - }
> + ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> + OV5645_SYSTEM_CTRL0_START);
> + if (ret < 0)
> + goto err_rpm_put;
>
> - v4l2_subdev_unlock_state(state);
> return 0;
>
> err_rpm_put:
> pm_runtime_put_sync(ov5645->dev);
> return ret;
> +}
> +
> +static int ov5645_disable_streams(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state, u32 pad,
> + u64 streams_mask)
> +{
> + struct ov5645 *ov5645 = to_ov5645(sd);
> + int ret;
> +
> + ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
> + if (ret < 0)
> + goto rpm_put;
> +
> + ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> + OV5645_SYSTEM_CTRL0_STOP);
>
> -stream_off_rpm_put:
> +rpm_put:
> pm_runtime_mark_last_busy(ov5645->dev);
> pm_runtime_put_autosuspend(ov5645->dev);
> - v4l2_subdev_unlock_state(state);
> +
> return ret;
> }
>
> static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> - .s_stream = ov5645_s_stream,
> + .s_stream = v4l2_subdev_s_stream_helper,
> };
>
> static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> @@ -996,6 +996,8 @@ static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = ov5645_set_format,
> .get_selection = ov5645_get_selection,
> + .enable_streams = ov5645_enable_streams,
> + .disable_streams = ov5645_disable_streams,
> };
>
> static const struct v4l2_subdev_core_ops ov5645_core_ops = {
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev()
2024-09-24 22:37 ` Laurent Pinchart
@ 2024-09-25 15:22 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-25 15:22 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent,
Thank you for the review.
On Tue, Sep 24, 2024 at 11:38 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Tue, Sep 10, 2024 at 06:06:02PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > To simplify the probe error path, enable runtime PM after the
> > v4l2_async_register_subdev() call.
> >
> > This change ensures that runtime PM is only enabled once the subdevice
> > registration is successful, avoiding unnecessary cleanup in the error
> > path.
>
> The subdev could start being used as soon as it gets registered, so
> runtime PM initialization should happen before
> v4l2_async_register_subdev().
>
Agreed, I will drop this patch.
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err
2024-09-24 22:43 ` Laurent Pinchart
@ 2024-09-25 15:24 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-25 15:24 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent,
Thank you for the review.
On Tue, Sep 24, 2024 at 11:44 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Tue, Sep 10, 2024 at 06:06:03PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Drop dev_err() and use the dev_err_probe() helper on probe path.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > drivers/media/i2c/ov5645.c | 74 +++++++++++++++-----------------------
> > 1 file changed, 28 insertions(+), 46 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > index 78b86438c798..9e6ff1f1b9ac 100644
> > --- a/drivers/media/i2c/ov5645.c
> > +++ b/drivers/media/i2c/ov5645.c
> > @@ -1076,51 +1076,37 @@ static int ov5645_probe(struct i2c_client *client)
> > ov5645->dev = dev;
> >
> > endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
> > - if (!endpoint) {
> > - dev_err(dev, "endpoint node not found\n");
> > - return -EINVAL;
> > - }
> > + if (!endpoint)
> > + return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
> >
> > ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
> > &ov5645->ep);
> >
> > of_node_put(endpoint);
> >
> > - if (ret < 0) {
> > - dev_err(dev, "parsing endpoint node failed\n");
> > - return ret;
> > - }
> > + if (ret < 0)
> > + return dev_err_probe(dev, ret, "parsing endpoint node failed\n");
> >
> > - if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
> > - dev_err(dev, "invalid bus type, must be CSI2\n");
> > - return -EINVAL;
> > - }
> > + if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
> > + return dev_err_probe(dev, -EINVAL, "invalid bus type, must be CSI2\n");
> >
> > /* get system clock (xclk) */
> > ov5645->xclk = devm_clk_get(dev, NULL);
> > - if (IS_ERR(ov5645->xclk)) {
> > - dev_err(dev, "could not get xclk");
> > - return PTR_ERR(ov5645->xclk);
> > - }
> > + if (IS_ERR(ov5645->xclk))
> > + return dev_err_probe(dev, PTR_ERR(ov5645->xclk), "could not get xclk");
> >
> > ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
> > - if (ret) {
> > - dev_err(dev, "could not get xclk frequency\n");
> > - return ret;
> > - }
> > + if (ret)
> > + return dev_err_probe(dev, ret, "could not get xclk frequency\n");
> >
> > /* external clock must be 24MHz, allow 1% tolerance */
> > - if (xclk_freq < 23760000 || xclk_freq > 24240000) {
> > - dev_err(dev, "external clock frequency %u is not supported\n",
> > - xclk_freq);
> > - return -EINVAL;
> > - }
> > + if (xclk_freq < 23760000 || xclk_freq > 24240000)
> > + return dev_err_probe(dev, -EINVAL, "external clock frequency %u is not supported\n",
> > + xclk_freq);
> >
> > ret = clk_set_rate(ov5645->xclk, xclk_freq);
> > - if (ret) {
> > - dev_err(dev, "could not set xclk frequency\n");
> > - return ret;
> > - }
> > + if (ret)
> > + return dev_err_probe(dev, ret, "could not set xclk frequency\n");
> >
> > for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
> > ov5645->supplies[i].supply = ov5645_supply_name[i];
> > @@ -1131,16 +1117,12 @@ static int ov5645_probe(struct i2c_client *client)
> > return ret;
> >
> > ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
> > - if (IS_ERR(ov5645->enable_gpio)) {
> > - dev_err(dev, "cannot get enable gpio\n");
> > - return PTR_ERR(ov5645->enable_gpio);
> > - }
> > + if (IS_ERR(ov5645->enable_gpio))
> > + return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio), "cannot get enable gpio\n");
>
> Those lines are getting long. We usually try to wrap at 80 columns for
> sensor drivers:
>
As there will be a v3 anyway, I'll wrap it to 80 columns.
> return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio),
> "cannot get enable gpio\n");
>
> Same elsewhere. I'll let Sakari decide.
>
> >
> > ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> > - if (IS_ERR(ov5645->rst_gpio)) {
> > - dev_err(dev, "cannot get reset gpio\n");
> > - return PTR_ERR(ov5645->rst_gpio);
> > - }
> > + if (IS_ERR(ov5645->rst_gpio))
> > + return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio), "cannot get reset gpio\n");
> >
> > mutex_init(&ov5645->power_lock);
> >
> > @@ -1177,9 +1159,9 @@ static int ov5645_probe(struct i2c_client *client)
> > ov5645->sd.ctrl_handler = &ov5645->ctrls;
> >
> > if (ov5645->ctrls.error) {
> > - dev_err(dev, "%s: control initialization error %d\n",
> > - __func__, ov5645->ctrls.error);
> > ret = ov5645->ctrls.error;
> > + dev_err_probe(dev, ret, "%s: control initialization error %d\n",
> > + __func__, ov5645->ctrls.error);
> > goto free_ctrl;
> > }
> >
> > @@ -1192,7 +1174,7 @@ static int ov5645_probe(struct i2c_client *client)
> >
> > ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
> > if (ret < 0) {
> > - dev_err(dev, "could not register media entity\n");
> > + dev_err_probe(dev, ret, "could not register media entity\n");
> > goto free_ctrl;
> > }
> >
> > @@ -1202,14 +1184,14 @@ static int ov5645_probe(struct i2c_client *client)
> >
> > ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
> > if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
> > - dev_err(dev, "could not read ID high\n");
> > ret = -ENODEV;
> > + dev_err_probe(dev, ret, "could not read ID high\n");
> > goto power_down;
> > }
> > ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
> > if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
> > - dev_err(dev, "could not read ID low\n");
> > ret = -ENODEV;
> > + dev_err_probe(dev, ret, "could not read ID low\n");
> > goto power_down;
> > }
> >
> > @@ -1218,24 +1200,24 @@ static int ov5645_probe(struct i2c_client *client)
> > ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
> > &ov5645->aec_pk_manual);
> > if (ret < 0) {
> > - dev_err(dev, "could not read AEC/AGC mode\n");
> > ret = -ENODEV;
> > + dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
> > goto power_down;
> > }
> >
> > ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
> > &ov5645->timing_tc_reg20);
> > if (ret < 0) {
> > - dev_err(dev, "could not read vflip value\n");
> > ret = -ENODEV;
> > + dev_err_probe(dev, ret, "could not read vflip value\n");
> > goto power_down;
> > }
> >
> > ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
> > &ov5645->timing_tc_reg21);
> > if (ret < 0) {
> > - dev_err(dev, "could not read hflip value\n");
> > ret = -ENODEV;
> > + dev_err_probe(dev, ret, "could not read hflip value\n");
> > goto power_down;
> > }
> >
> > @@ -1243,7 +1225,7 @@ static int ov5645_probe(struct i2c_client *client)
> >
> > ret = v4l2_async_register_subdev(&ov5645->sd);
> > if (ret < 0) {
> > - dev_err(dev, "could not register v4l2 device\n");
> > + dev_err_probe(dev, ret, "could not register v4l2 device\n");
> > goto power_down;
> > }
> >
>
> The probe function looks really young, I think it would benefit from
> being broken down in multiple functions.
>
I will add this once this initial series gets accepted.
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor()
2024-09-24 22:44 ` Laurent Pinchart
@ 2024-09-25 15:26 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-25 15:26 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent,
Thank you for the review.
On Tue, Sep 24, 2024 at 11:45 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> On Tue, Sep 10, 2024 at 06:06:04PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Make use v4l2_async_register_subdev_sensor() helper to register
> > the subdev.
>
> The commit message should explain why.
>
Sure I'll update the commit message.
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex
2024-09-24 22:46 ` Laurent Pinchart
@ 2024-09-25 15:35 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-25 15:35 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent,
Thank you for the review.
On Tue, Sep 24, 2024 at 11:46 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> On Tue, Sep 10, 2024 at 06:06:05PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Drop mutex while applying controls and just rely on
> > pm_runtime_get_if_in_use() call.
>
> Here too the commit message should explain why the mutex can be dropped.
> Given that it is only used in .s_ctrl(), and the control framework
> serializes calls to the function, the mutex is not needed.
>
Agreed, I'll update the commit message as above and send a v3.
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad
2024-09-10 17:06 ` [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad Prabhakar
@ 2024-09-25 16:21 ` Laurent Pinchart
2024-09-26 15:49 ` Sakari Ailus
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-25 16:21 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:08PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Use the newly added internal pad API to expose the internal
> configuration of the sensor to userspace in a standard manner.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> drivers/media/i2c/ov5645.c | 107 +++++++++++++++++++++++++++----------
> 1 file changed, 79 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index dc93514608ee..255c6395a268 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -60,6 +60,10 @@
> #define OV5645_SDE_SAT_U 0x5583
> #define OV5645_SDE_SAT_V 0x5584
>
> +#define OV5645_NATIVE_FORMAT MEDIA_BUS_FMT_SBGGR8_1X8
> +#define OV5645_NATIVE_WIDTH 2592
> +#define OV5645_NATIVE_HEIGHT 1944
> +
> /* regulator supplies */
> static const char * const ov5645_supply_name[] = {
> "vdddo", /* Digital I/O (1.8V) supply */
> @@ -69,6 +73,12 @@ static const char * const ov5645_supply_name[] = {
>
> #define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)
>
> +enum ov5645_pad_ids {
> + OV5645_PAD_SOURCE,
> + OV5645_PAD_IMAGE,
> + OV5645_NUM_PADS,
> +};
> +
> struct reg_value {
> u16 reg;
> u8 val;
> @@ -87,7 +97,7 @@ struct ov5645 {
> struct i2c_client *i2c_client;
> struct device *dev;
> struct v4l2_subdev sd;
> - struct media_pad pad;
> + struct media_pad pads[OV5645_NUM_PADS];
> struct v4l2_fwnode_endpoint ep;
> struct v4l2_rect crop;
> struct clk *xclk;
> @@ -826,7 +836,10 @@ static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> if (code->index > 0)
> return -EINVAL;
>
> - code->code = MEDIA_BUS_FMT_UYVY8_1X16;
> + if (code->pad == OV5645_PAD_IMAGE)
> + code->code = OV5645_NATIVE_FORMAT;
> + else
> + code->code = MEDIA_BUS_FMT_UYVY8_1X16;
>
> return 0;
> }
> @@ -835,16 +848,24 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_frame_size_enum *fse)
> {
> - if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
> - return -EINVAL;
> -
> - if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> - return -EINVAL;
> -
> - fse->min_width = ov5645_mode_info_data[fse->index].width;
> - fse->max_width = ov5645_mode_info_data[fse->index].width;
> - fse->min_height = ov5645_mode_info_data[fse->index].height;
> - fse->max_height = ov5645_mode_info_data[fse->index].height;
> + if (fse->pad == OV5645_PAD_IMAGE) {
> + if (fse->code != OV5645_NATIVE_FORMAT || fse->index > 0)
> + return -EINVAL;
> +
> + fse->min_width = OV5645_NATIVE_WIDTH;
> + fse->max_width = OV5645_NATIVE_WIDTH;
> + fse->min_height = OV5645_NATIVE_HEIGHT;
> + fse->max_height = OV5645_NATIVE_HEIGHT;
> + } else {
> + if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16 ||
This will be interesting. With internal pads we will introduce the
concept of a "subdev model", which will formally document how the V4L2
subdev configuration items (formats, selection rectangles, ...) maps to
hardware features. Sakari is working on the definition of a subdev model
for raw sensors, that should catter for the needs of raw sensors without
a bayer scaler (the vast majority of them). To use internal pads with a
non-raw sensor, we'll have to define a model. It may be more
challenging/complicated to do so, as the YUV sensor features are less
standardized, but it will be an interesting development.
> + fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> + return -EINVAL;
> +
> + fse->min_width = ov5645_mode_info_data[fse->index].width;
> + fse->max_width = ov5645_mode_info_data[fse->index].width;
> + fse->min_height = ov5645_mode_info_data[fse->index].height;
> + fse->max_height = ov5645_mode_info_data[fse->index].height;
> + }
>
> return 0;
> }
> @@ -855,18 +876,55 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> {
> struct ov5645 *ov5645 = to_ov5645(sd);
> struct v4l2_mbus_framefmt *__format;
> + struct v4l2_rect *compose;
> struct v4l2_rect *__crop;
While at it, could you rename __crop to crop ?
> const struct ov5645_mode_info *new_mode;
> int ret;
>
> - __crop = v4l2_subdev_state_get_crop(sd_state, 0);
> + if (format->pad != OV5645_PAD_SOURCE)
> + return v4l2_subdev_get_fmt(sd, sd_state, format);
> +
> new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
> ARRAY_SIZE(ov5645_mode_info_data),
> width, height, format->format.width,
> format->format.height);
> -
> - __crop->width = new_mode->width;
> - __crop->height = new_mode->height;
> + format->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
> + format->format.width = new_mode->width;
> + format->format.height = new_mode->height;
> + format->format.field = V4L2_FIELD_NONE;
> + format->format.colorspace = V4L2_COLORSPACE_SRGB;
> + format->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> + format->format.quantization = V4L2_QUANTIZATION_DEFAULT;
> + format->format.xfer_func = V4L2_XFER_FUNC_DEFAULT;
Drivers are not supposed to return DEFAULT values, you should pick
appropriate values.
> +
> + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE);
Maybe __format could also become fmt.
> + *__format = format->format;
> + __format->code = OV5645_NATIVE_FORMAT;
> + __format->width = OV5645_NATIVE_WIDTH;
> + __format->height = OV5645_NATIVE_HEIGHT;
> +
> + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE);
> + __crop->width = format->format.width;
> + __crop->height = format->format.height;
> +
> + /*
> + * The compose rectangle models binning, its size is the sensor output
> + * size.
> + */
> + compose = v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE);
> + compose->left = 0;
> + compose->top = 0;
> + compose->width = format->format.width;
> + compose->height = format->format.height;
> +
> + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE);
> + __crop->left = 0;
> + __crop->top = 0;
> + __crop->width = format->format.width;
> + __crop->height = format->format.height;
> +
> + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE);
> + *__format = format->format;
>
> if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
> @@ -882,14 +940,6 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> ov5645->current_mode = new_mode;
> }
>
> - __format = v4l2_subdev_state_get_format(sd_state, 0);
> - __format->width = __crop->width;
> - __format->height = __crop->height;
> - __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
> - __format->field = V4L2_FIELD_NONE;
> - __format->colorspace = V4L2_COLORSPACE_SRGB;
> -
> - format->format = *__format;
>
> return 0;
> }
> @@ -899,7 +949,7 @@ static int ov5645_init_state(struct v4l2_subdev *subdev,
> {
> struct v4l2_subdev_format fmt = {
> .which = V4L2_SUBDEV_FORMAT_TRY,
> - .pad = 0,
> + .pad = OV5645_PAD_SOURCE,
> .format = {
> .code = MEDIA_BUS_FMT_UYVY8_1X16,
> .width = ov5645_mode_info_data[1].width,
> @@ -919,7 +969,7 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
> if (sel->target != V4L2_SEL_TGT_CROP)
> return -EINVAL;
>
> - sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
> + sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
Now there's a compose rectangle, you should support getting it.
> return 0;
> }
>
> @@ -1123,11 +1173,12 @@ static int ov5645_probe(struct i2c_client *client)
> v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
> ov5645->sd.internal_ops = &ov5645_internal_ops;
> ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> - ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
> + ov5645->pads[OV5645_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
> + ov5645->pads[OV5645_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
> ov5645->sd.dev = dev;
> ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
>
> - ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
> + ret = media_entity_pads_init(&ov5645->sd.entity, ARRAY_SIZE(ov5645->pads), ov5645->pads);
Line wrap.
> if (ret < 0) {
> dev_err_probe(dev, ret, "could not register media entity\n");
> goto free_ctrl;
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-10 17:06 ` [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors Prabhakar
@ 2024-09-25 16:26 ` Laurent Pinchart
2024-09-26 10:16 ` Lad, Prabhakar
2024-09-26 15:45 ` Sakari Ailus
1 sibling, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-25 16:26 UTC (permalink / raw)
To: Prabhakar
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thank you for the patch.
On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Implement the .get_frame_desc() subdev operation to report information
> about streams to the connected CSI-2 receiver. This is required to let
> the CSI-2 receiver driver know about virtual channels and data types for
> each stream.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 7f1133292ffc..c24eb6e7a7b5 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -28,6 +28,7 @@
> #include <linux/regulator/consumer.h>
> #include <linux/slab.h>
> #include <linux/types.h>
> +#include <media/mipi-csi2.h>
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-event.h>
> #include <media/v4l2-fwnode.h>
> @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> .s_ctrl = ov5645_s_ctrl,
> };
>
> +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> + struct v4l2_mbus_frame_desc *fd)
> +{
> + const struct v4l2_mbus_framefmt *fmt;
> + struct v4l2_subdev_state *state;
> +
> + if (pad != OV5645_PAD_SOURCE)
> + return -EINVAL;
> +
> + state = v4l2_subdev_lock_and_get_active_state(sd);
> + fmt = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0);
> + v4l2_subdev_unlock_state(state);
Once you unlock the state fmt could change, so you should instead do
state = v4l2_subdev_lock_and_get_active_state(sd);
code = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0)->code;
v4l2_subdev_unlock_state(state);
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> +
> + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
> + fd->num_entries = 1;
> +
> + memset(fd->entry, 0, sizeof(fd->entry));
> +
> + fd->entry[0].pixelcode = fmt->code;
> + fd->entry[0].stream = 0;
> + fd->entry[0].bus.csi2.vc = 0;
> + fd->entry[0].bus.csi2.dt = MIPI_CSI2_DT_YUV422_8B;
> +
> + return 0;
> +}
> +
> static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_mbus_code_enum *code)
> @@ -1062,6 +1089,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> };
>
> static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> + .get_frame_desc = ov5645_get_frame_desc,
> .enum_mbus_code = ov5645_enum_mbus_code,
> .enum_frame_size = ov5645_enum_frame_size,
> .get_fmt = v4l2_subdev_get_fmt,
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-25 16:26 ` Laurent Pinchart
@ 2024-09-26 10:16 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-26 10:16 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent,
Thank you for the review.
On Wed, Sep 25, 2024 at 5:26 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Implement the .get_frame_desc() subdev operation to report information
> > about streams to the connected CSI-2 receiver. This is required to let
> > the CSI-2 receiver driver know about virtual channels and data types for
> > each stream.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> > 1 file changed, 28 insertions(+)
> >
> > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > index 7f1133292ffc..c24eb6e7a7b5 100644
> > --- a/drivers/media/i2c/ov5645.c
> > +++ b/drivers/media/i2c/ov5645.c
> > @@ -28,6 +28,7 @@
> > #include <linux/regulator/consumer.h>
> > #include <linux/slab.h>
> > #include <linux/types.h>
> > +#include <media/mipi-csi2.h>
> > #include <media/v4l2-ctrls.h>
> > #include <media/v4l2-event.h>
> > #include <media/v4l2-fwnode.h>
> > @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> > .s_ctrl = ov5645_s_ctrl,
> > };
> >
> > +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> > + struct v4l2_mbus_frame_desc *fd)
> > +{
> > + const struct v4l2_mbus_framefmt *fmt;
> > + struct v4l2_subdev_state *state;
> > +
> > + if (pad != OV5645_PAD_SOURCE)
> > + return -EINVAL;
> > +
> > + state = v4l2_subdev_lock_and_get_active_state(sd);
> > + fmt = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0);
> > + v4l2_subdev_unlock_state(state);
>
> Once you unlock the state fmt could change, so you should instead do
>
> state = v4l2_subdev_lock_and_get_active_state(sd);
> code = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0)->code;
> v4l2_subdev_unlock_state(state);
>
Ok, I will update the above.
Cheers,
Prabhakar
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
> > +
> > + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
> > + fd->num_entries = 1;
> > +
> > + memset(fd->entry, 0, sizeof(fd->entry));
> > +
> > + fd->entry[0].pixelcode = fmt->code;
> > + fd->entry[0].stream = 0;
> > + fd->entry[0].bus.csi2.vc = 0;
> > + fd->entry[0].bus.csi2.dt = MIPI_CSI2_DT_YUV422_8B;
> > +
> > + return 0;
> > +}
> > +
> > static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> > struct v4l2_subdev_state *sd_state,
> > struct v4l2_subdev_mbus_code_enum *code)
> > @@ -1062,6 +1089,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> > };
> >
> > static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> > + .get_frame_desc = ov5645_get_frame_desc,
> > .enum_mbus_code = ov5645_enum_mbus_code,
> > .enum_frame_size = ov5645_enum_frame_size,
> > .get_fmt = v4l2_subdev_get_fmt,
>
> --
> Regards,
>
> Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-10 17:06 ` [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors Prabhakar
2024-09-25 16:26 ` Laurent Pinchart
@ 2024-09-26 15:45 ` Sakari Ailus
2024-09-26 17:48 ` Laurent Pinchart
1 sibling, 1 reply; 34+ messages in thread
From: Sakari Ailus @ 2024-09-26 15:45 UTC (permalink / raw)
To: Prabhakar
Cc: Laurent Pinchart, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
Thanks for the set. It looks largely very nice to me, after addressing
Laurent's comments. A few comments here and possibly on other patches...
On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Implement the .get_frame_desc() subdev operation to report information
> about streams to the connected CSI-2 receiver. This is required to let
> the CSI-2 receiver driver know about virtual channels and data types for
> each stream.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> index 7f1133292ffc..c24eb6e7a7b5 100644
> --- a/drivers/media/i2c/ov5645.c
> +++ b/drivers/media/i2c/ov5645.c
> @@ -28,6 +28,7 @@
> #include <linux/regulator/consumer.h>
> #include <linux/slab.h>
> #include <linux/types.h>
> +#include <media/mipi-csi2.h>
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-event.h>
> #include <media/v4l2-fwnode.h>
> @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> .s_ctrl = ov5645_s_ctrl,
> };
>
> +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> + struct v4l2_mbus_frame_desc *fd)
> +{
> + const struct v4l2_mbus_framefmt *fmt;
> + struct v4l2_subdev_state *state;
> +
> + if (pad != OV5645_PAD_SOURCE)
> + return -EINVAL;
As you have a single source pad, and pretty much all sensor drivers will, I
think it'd be nice to add a check for this (that it's not an internal pad)
to the caller side in v4l2-subdev.c. And of course drop this one.
> +
> + state = v4l2_subdev_lock_and_get_active_state(sd);
> + fmt = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0);
> + v4l2_subdev_unlock_state(state);
> +
> + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
> + fd->num_entries = 1;
> +
> + memset(fd->entry, 0, sizeof(fd->entry));
> +
> + fd->entry[0].pixelcode = fmt->code;
> + fd->entry[0].stream = 0;
> + fd->entry[0].bus.csi2.vc = 0;
> + fd->entry[0].bus.csi2.dt = MIPI_CSI2_DT_YUV422_8B;
> +
> + return 0;
> +}
> +
> static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_mbus_code_enum *code)
> @@ -1062,6 +1089,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> };
>
> static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> + .get_frame_desc = ov5645_get_frame_desc,
> .enum_mbus_code = ov5645_enum_mbus_code,
> .enum_frame_size = ov5645_enum_frame_size,
> .get_fmt = v4l2_subdev_get_fmt,
>
--
Kind regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad
2024-09-25 16:21 ` Laurent Pinchart
@ 2024-09-26 15:49 ` Sakari Ailus
2024-09-27 15:35 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Sakari Ailus @ 2024-09-26 15:49 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Prabhakar, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Laurent, Prabhakar,
On Wed, Sep 25, 2024 at 07:21:53PM +0300, Laurent Pinchart wrote:
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Tue, Sep 10, 2024 at 06:06:08PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Use the newly added internal pad API to expose the internal
> > configuration of the sensor to userspace in a standard manner.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > drivers/media/i2c/ov5645.c | 107 +++++++++++++++++++++++++++----------
> > 1 file changed, 79 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > index dc93514608ee..255c6395a268 100644
> > --- a/drivers/media/i2c/ov5645.c
> > +++ b/drivers/media/i2c/ov5645.c
> > @@ -60,6 +60,10 @@
> > #define OV5645_SDE_SAT_U 0x5583
> > #define OV5645_SDE_SAT_V 0x5584
> >
> > +#define OV5645_NATIVE_FORMAT MEDIA_BUS_FMT_SBGGR8_1X8
> > +#define OV5645_NATIVE_WIDTH 2592
> > +#define OV5645_NATIVE_HEIGHT 1944
> > +
> > /* regulator supplies */
> > static const char * const ov5645_supply_name[] = {
> > "vdddo", /* Digital I/O (1.8V) supply */
> > @@ -69,6 +73,12 @@ static const char * const ov5645_supply_name[] = {
> >
> > #define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)
> >
> > +enum ov5645_pad_ids {
> > + OV5645_PAD_SOURCE,
> > + OV5645_PAD_IMAGE,
> > + OV5645_NUM_PADS,
> > +};
> > +
> > struct reg_value {
> > u16 reg;
> > u8 val;
> > @@ -87,7 +97,7 @@ struct ov5645 {
> > struct i2c_client *i2c_client;
> > struct device *dev;
> > struct v4l2_subdev sd;
> > - struct media_pad pad;
> > + struct media_pad pads[OV5645_NUM_PADS];
> > struct v4l2_fwnode_endpoint ep;
> > struct v4l2_rect crop;
> > struct clk *xclk;
> > @@ -826,7 +836,10 @@ static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> > if (code->index > 0)
> > return -EINVAL;
> >
> > - code->code = MEDIA_BUS_FMT_UYVY8_1X16;
> > + if (code->pad == OV5645_PAD_IMAGE)
> > + code->code = OV5645_NATIVE_FORMAT;
> > + else
> > + code->code = MEDIA_BUS_FMT_UYVY8_1X16;
> >
> > return 0;
> > }
> > @@ -835,16 +848,24 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
> > struct v4l2_subdev_state *sd_state,
> > struct v4l2_subdev_frame_size_enum *fse)
> > {
> > - if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
> > - return -EINVAL;
> > -
> > - if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> > - return -EINVAL;
> > -
> > - fse->min_width = ov5645_mode_info_data[fse->index].width;
> > - fse->max_width = ov5645_mode_info_data[fse->index].width;
> > - fse->min_height = ov5645_mode_info_data[fse->index].height;
> > - fse->max_height = ov5645_mode_info_data[fse->index].height;
> > + if (fse->pad == OV5645_PAD_IMAGE) {
> > + if (fse->code != OV5645_NATIVE_FORMAT || fse->index > 0)
> > + return -EINVAL;
> > +
> > + fse->min_width = OV5645_NATIVE_WIDTH;
> > + fse->max_width = OV5645_NATIVE_WIDTH;
> > + fse->min_height = OV5645_NATIVE_HEIGHT;
> > + fse->max_height = OV5645_NATIVE_HEIGHT;
> > + } else {
> > + if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16 ||
>
> This will be interesting. With internal pads we will introduce the
> concept of a "subdev model", which will formally document how the V4L2
> subdev configuration items (formats, selection rectangles, ...) maps to
> hardware features. Sakari is working on the definition of a subdev model
> for raw sensors, that should catter for the needs of raw sensors without
> a bayer scaler (the vast majority of them). To use internal pads with a
> non-raw sensor, we'll have to define a model. It may be more
> challenging/complicated to do so, as the YUV sensor features are less
> standardized, but it will be an interesting development.
I think I'll make the sub-device model a bitmask, to allow implementing
more than one at the same time.
I'll try to remember to cc you to the patchset when I'll send it, likely
next week.
>
> > + fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> > + return -EINVAL;
> > +
> > + fse->min_width = ov5645_mode_info_data[fse->index].width;
> > + fse->max_width = ov5645_mode_info_data[fse->index].width;
> > + fse->min_height = ov5645_mode_info_data[fse->index].height;
> > + fse->max_height = ov5645_mode_info_data[fse->index].height;
> > + }
> >
> > return 0;
> > }
> > @@ -855,18 +876,55 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> > {
> > struct ov5645 *ov5645 = to_ov5645(sd);
> > struct v4l2_mbus_framefmt *__format;
> > + struct v4l2_rect *compose;
> > struct v4l2_rect *__crop;
>
> While at it, could you rename __crop to crop ?
>
> > const struct ov5645_mode_info *new_mode;
> > int ret;
> >
> > - __crop = v4l2_subdev_state_get_crop(sd_state, 0);
> > + if (format->pad != OV5645_PAD_SOURCE)
> > + return v4l2_subdev_get_fmt(sd, sd_state, format);
> > +
> > new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
> > ARRAY_SIZE(ov5645_mode_info_data),
> > width, height, format->format.width,
> > format->format.height);
> > -
> > - __crop->width = new_mode->width;
> > - __crop->height = new_mode->height;
> > + format->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
> > + format->format.width = new_mode->width;
> > + format->format.height = new_mode->height;
> > + format->format.field = V4L2_FIELD_NONE;
> > + format->format.colorspace = V4L2_COLORSPACE_SRGB;
> > + format->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> > + format->format.quantization = V4L2_QUANTIZATION_DEFAULT;
> > + format->format.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>
> Drivers are not supposed to return DEFAULT values, you should pick
> appropriate values.
>
> > +
> > + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE);
>
> Maybe __format could also become fmt.
>
> > + *__format = format->format;
> > + __format->code = OV5645_NATIVE_FORMAT;
> > + __format->width = OV5645_NATIVE_WIDTH;
> > + __format->height = OV5645_NATIVE_HEIGHT;
> > +
> > + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE);
> > + __crop->width = format->format.width;
> > + __crop->height = format->format.height;
> > +
> > + /*
> > + * The compose rectangle models binning, its size is the sensor output
> > + * size.
> > + */
> > + compose = v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE);
> > + compose->left = 0;
> > + compose->top = 0;
> > + compose->width = format->format.width;
> > + compose->height = format->format.height;
> > +
> > + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE);
> > + __crop->left = 0;
> > + __crop->top = 0;
> > + __crop->width = format->format.width;
> > + __crop->height = format->format.height;
> > +
> > + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE);
> > + *__format = format->format;
> >
> > if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> > ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
> > @@ -882,14 +940,6 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> > ov5645->current_mode = new_mode;
> > }
> >
> > - __format = v4l2_subdev_state_get_format(sd_state, 0);
> > - __format->width = __crop->width;
> > - __format->height = __crop->height;
> > - __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
> > - __format->field = V4L2_FIELD_NONE;
> > - __format->colorspace = V4L2_COLORSPACE_SRGB;
> > -
> > - format->format = *__format;
> >
> > return 0;
> > }
> > @@ -899,7 +949,7 @@ static int ov5645_init_state(struct v4l2_subdev *subdev,
> > {
> > struct v4l2_subdev_format fmt = {
> > .which = V4L2_SUBDEV_FORMAT_TRY,
> > - .pad = 0,
> > + .pad = OV5645_PAD_SOURCE,
> > .format = {
> > .code = MEDIA_BUS_FMT_UYVY8_1X16,
> > .width = ov5645_mode_info_data[1].width,
> > @@ -919,7 +969,7 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
> > if (sel->target != V4L2_SEL_TGT_CROP)
> > return -EINVAL;
> >
> > - sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
> > + sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
>
> Now there's a compose rectangle, you should support getting it.
>
> > return 0;
> > }
> >
> > @@ -1123,11 +1173,12 @@ static int ov5645_probe(struct i2c_client *client)
> > v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
> > ov5645->sd.internal_ops = &ov5645_internal_ops;
> > ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> > - ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
> > + ov5645->pads[OV5645_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
> > + ov5645->pads[OV5645_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
> > ov5645->sd.dev = dev;
> > ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> >
> > - ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
> > + ret = media_entity_pads_init(&ov5645->sd.entity, ARRAY_SIZE(ov5645->pads), ov5645->pads);
>
> Line wrap.
It's good to run:
scripts/checkpatch.pl --strict --max-line-length=80
on the patches.
>
> > if (ret < 0) {
> > dev_err_probe(dev, ret, "could not register media entity\n");
> > goto free_ctrl;
>
--
Kind regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-26 15:45 ` Sakari Ailus
@ 2024-09-26 17:48 ` Laurent Pinchart
2024-09-26 18:57 ` Sakari Ailus
0 siblings, 1 reply; 34+ messages in thread
From: Laurent Pinchart @ 2024-09-26 17:48 UTC (permalink / raw)
To: Sakari Ailus
Cc: Prabhakar, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
On Thu, Sep 26, 2024 at 03:45:26PM +0000, Sakari Ailus wrote:
> Hi Prabhakar,
>
> Thanks for the set. It looks largely very nice to me, after addressing
> Laurent's comments. A few comments here and possibly on other patches...
>
> On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Implement the .get_frame_desc() subdev operation to report information
> > about streams to the connected CSI-2 receiver. This is required to let
> > the CSI-2 receiver driver know about virtual channels and data types for
> > each stream.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> > 1 file changed, 28 insertions(+)
> >
> > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > index 7f1133292ffc..c24eb6e7a7b5 100644
> > --- a/drivers/media/i2c/ov5645.c
> > +++ b/drivers/media/i2c/ov5645.c
> > @@ -28,6 +28,7 @@
> > #include <linux/regulator/consumer.h>
> > #include <linux/slab.h>
> > #include <linux/types.h>
> > +#include <media/mipi-csi2.h>
> > #include <media/v4l2-ctrls.h>
> > #include <media/v4l2-event.h>
> > #include <media/v4l2-fwnode.h>
> > @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> > .s_ctrl = ov5645_s_ctrl,
> > };
> >
> > +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> > + struct v4l2_mbus_frame_desc *fd)
> > +{
> > + const struct v4l2_mbus_framefmt *fmt;
> > + struct v4l2_subdev_state *state;
> > +
> > + if (pad != OV5645_PAD_SOURCE)
> > + return -EINVAL;
>
> As you have a single source pad, and pretty much all sensor drivers will, I
> think it'd be nice to add a check for this (that it's not an internal pad)
> to the caller side in v4l2-subdev.c. And of course drop this one.
What check would you add, just verifying that the pad is a source pad ?
> > +
> > + state = v4l2_subdev_lock_and_get_active_state(sd);
> > + fmt = v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0);
> > + v4l2_subdev_unlock_state(state);
> > +
> > + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
> > + fd->num_entries = 1;
> > +
> > + memset(fd->entry, 0, sizeof(fd->entry));
> > +
> > + fd->entry[0].pixelcode = fmt->code;
> > + fd->entry[0].stream = 0;
> > + fd->entry[0].bus.csi2.vc = 0;
> > + fd->entry[0].bus.csi2.dt = MIPI_CSI2_DT_YUV422_8B;
> > +
> > + return 0;
> > +}
> > +
> > static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> > struct v4l2_subdev_state *sd_state,
> > struct v4l2_subdev_mbus_code_enum *code)
> > @@ -1062,6 +1089,7 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
> > };
> >
> > static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
> > + .get_frame_desc = ov5645_get_frame_desc,
> > .enum_mbus_code = ov5645_enum_mbus_code,
> > .enum_frame_size = ov5645_enum_frame_size,
> > .get_fmt = v4l2_subdev_get_fmt,
> >
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-26 17:48 ` Laurent Pinchart
@ 2024-09-26 18:57 ` Sakari Ailus
2024-09-27 15:31 ` Lad, Prabhakar
0 siblings, 1 reply; 34+ messages in thread
From: Sakari Ailus @ 2024-09-26 18:57 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Prabhakar, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
On Thu, Sep 26, 2024 at 08:48:19PM +0300, Laurent Pinchart wrote:
> On Thu, Sep 26, 2024 at 03:45:26PM +0000, Sakari Ailus wrote:
> > Hi Prabhakar,
> >
> > Thanks for the set. It looks largely very nice to me, after addressing
> > Laurent's comments. A few comments here and possibly on other patches...
> >
> > On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > >
> > > Implement the .get_frame_desc() subdev operation to report information
> > > about streams to the connected CSI-2 receiver. This is required to let
> > > the CSI-2 receiver driver know about virtual channels and data types for
> > > each stream.
> > >
> > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > ---
> > > drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> > > 1 file changed, 28 insertions(+)
> > >
> > > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > > index 7f1133292ffc..c24eb6e7a7b5 100644
> > > --- a/drivers/media/i2c/ov5645.c
> > > +++ b/drivers/media/i2c/ov5645.c
> > > @@ -28,6 +28,7 @@
> > > #include <linux/regulator/consumer.h>
> > > #include <linux/slab.h>
> > > #include <linux/types.h>
> > > +#include <media/mipi-csi2.h>
> > > #include <media/v4l2-ctrls.h>
> > > #include <media/v4l2-event.h>
> > > #include <media/v4l2-fwnode.h>
> > > @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> > > .s_ctrl = ov5645_s_ctrl,
> > > };
> > >
> > > +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> > > + struct v4l2_mbus_frame_desc *fd)
> > > +{
> > > + const struct v4l2_mbus_framefmt *fmt;
> > > + struct v4l2_subdev_state *state;
> > > +
> > > + if (pad != OV5645_PAD_SOURCE)
> > > + return -EINVAL;
> >
> > As you have a single source pad, and pretty much all sensor drivers will, I
> > think it'd be nice to add a check for this (that it's not an internal pad)
> > to the caller side in v4l2-subdev.c. And of course drop this one.
>
> What check would you add, just verifying that the pad is a source pad ?
I think you could add that, too, besides the absence of the internal flag.
--
Sakari Ailus
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-26 18:57 ` Sakari Ailus
@ 2024-09-27 15:31 ` Lad, Prabhakar
2024-09-27 16:01 ` Sakari Ailus
0 siblings, 1 reply; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-27 15:31 UTC (permalink / raw)
To: Sakari Ailus, Laurent Pinchart
Cc: Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Sakari and Laurent,
On Thu, Sep 26, 2024 at 7:57 PM Sakari Ailus
<sakari.ailus@linux.intel.com> wrote:
>
> On Thu, Sep 26, 2024 at 08:48:19PM +0300, Laurent Pinchart wrote:
> > On Thu, Sep 26, 2024 at 03:45:26PM +0000, Sakari Ailus wrote:
> > > Hi Prabhakar,
> > >
> > > Thanks for the set. It looks largely very nice to me, after addressing
> > > Laurent's comments. A few comments here and possibly on other patches...
> > >
> > > On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > >
> > > > Implement the .get_frame_desc() subdev operation to report information
> > > > about streams to the connected CSI-2 receiver. This is required to let
> > > > the CSI-2 receiver driver know about virtual channels and data types for
> > > > each stream.
> > > >
> > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > ---
> > > > drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> > > > 1 file changed, 28 insertions(+)
> > > >
> > > > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > > > index 7f1133292ffc..c24eb6e7a7b5 100644
> > > > --- a/drivers/media/i2c/ov5645.c
> > > > +++ b/drivers/media/i2c/ov5645.c
> > > > @@ -28,6 +28,7 @@
> > > > #include <linux/regulator/consumer.h>
> > > > #include <linux/slab.h>
> > > > #include <linux/types.h>
> > > > +#include <media/mipi-csi2.h>
> > > > #include <media/v4l2-ctrls.h>
> > > > #include <media/v4l2-event.h>
> > > > #include <media/v4l2-fwnode.h>
> > > > @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> > > > .s_ctrl = ov5645_s_ctrl,
> > > > };
> > > >
> > > > +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> > > > + struct v4l2_mbus_frame_desc *fd)
> > > > +{
> > > > + const struct v4l2_mbus_framefmt *fmt;
> > > > + struct v4l2_subdev_state *state;
> > > > +
> > > > + if (pad != OV5645_PAD_SOURCE)
> > > > + return -EINVAL;
> > >
> > > As you have a single source pad, and pretty much all sensor drivers will, I
> > > think it'd be nice to add a check for this (that it's not an internal pad)
> > > to the caller side in v4l2-subdev.c. And of course drop this one.
> >
> > What check would you add, just verifying that the pad is a source pad ?
>
> I think you could add that, too, besides the absence of the internal flag.
>
Checking only for the source flag should suffice, as the
MEDIA_PAD_FL_INTERNAL flag cannot be set for a source pad because
media_entity_pads_init() enforces this restriction.
Do you agree?
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad
2024-09-26 15:49 ` Sakari Ailus
@ 2024-09-27 15:35 ` Lad, Prabhakar
0 siblings, 0 replies; 34+ messages in thread
From: Lad, Prabhakar @ 2024-09-27 15:35 UTC (permalink / raw)
To: Sakari Ailus
Cc: Laurent Pinchart, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Sakari,
On Thu, Sep 26, 2024 at 4:49 PM Sakari Ailus
<sakari.ailus@linux.intel.com> wrote:
>
> Hi Laurent, Prabhakar,
>
> On Wed, Sep 25, 2024 at 07:21:53PM +0300, Laurent Pinchart wrote:
> > Hi Prabhakar,
> >
> > Thank you for the patch.
> >
> > On Tue, Sep 10, 2024 at 06:06:08PM +0100, Prabhakar wrote:
> > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > >
> > > Use the newly added internal pad API to expose the internal
> > > configuration of the sensor to userspace in a standard manner.
> > >
> > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > ---
> > > drivers/media/i2c/ov5645.c | 107 +++++++++++++++++++++++++++----------
> > > 1 file changed, 79 insertions(+), 28 deletions(-)
> > >
> > > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > > index dc93514608ee..255c6395a268 100644
> > > --- a/drivers/media/i2c/ov5645.c
> > > +++ b/drivers/media/i2c/ov5645.c
> > > @@ -60,6 +60,10 @@
> > > #define OV5645_SDE_SAT_U 0x5583
> > > #define OV5645_SDE_SAT_V 0x5584
> > >
> > > +#define OV5645_NATIVE_FORMAT MEDIA_BUS_FMT_SBGGR8_1X8
> > > +#define OV5645_NATIVE_WIDTH 2592
> > > +#define OV5645_NATIVE_HEIGHT 1944
> > > +
> > > /* regulator supplies */
> > > static const char * const ov5645_supply_name[] = {
> > > "vdddo", /* Digital I/O (1.8V) supply */
> > > @@ -69,6 +73,12 @@ static const char * const ov5645_supply_name[] = {
> > >
> > > #define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)
> > >
> > > +enum ov5645_pad_ids {
> > > + OV5645_PAD_SOURCE,
> > > + OV5645_PAD_IMAGE,
> > > + OV5645_NUM_PADS,
> > > +};
> > > +
> > > struct reg_value {
> > > u16 reg;
> > > u8 val;
> > > @@ -87,7 +97,7 @@ struct ov5645 {
> > > struct i2c_client *i2c_client;
> > > struct device *dev;
> > > struct v4l2_subdev sd;
> > > - struct media_pad pad;
> > > + struct media_pad pads[OV5645_NUM_PADS];
> > > struct v4l2_fwnode_endpoint ep;
> > > struct v4l2_rect crop;
> > > struct clk *xclk;
> > > @@ -826,7 +836,10 @@ static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
> > > if (code->index > 0)
> > > return -EINVAL;
> > >
> > > - code->code = MEDIA_BUS_FMT_UYVY8_1X16;
> > > + if (code->pad == OV5645_PAD_IMAGE)
> > > + code->code = OV5645_NATIVE_FORMAT;
> > > + else
> > > + code->code = MEDIA_BUS_FMT_UYVY8_1X16;
> > >
> > > return 0;
> > > }
> > > @@ -835,16 +848,24 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
> > > struct v4l2_subdev_state *sd_state,
> > > struct v4l2_subdev_frame_size_enum *fse)
> > > {
> > > - if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
> > > - return -EINVAL;
> > > -
> > > - if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> > > - return -EINVAL;
> > > -
> > > - fse->min_width = ov5645_mode_info_data[fse->index].width;
> > > - fse->max_width = ov5645_mode_info_data[fse->index].width;
> > > - fse->min_height = ov5645_mode_info_data[fse->index].height;
> > > - fse->max_height = ov5645_mode_info_data[fse->index].height;
> > > + if (fse->pad == OV5645_PAD_IMAGE) {
> > > + if (fse->code != OV5645_NATIVE_FORMAT || fse->index > 0)
> > > + return -EINVAL;
> > > +
> > > + fse->min_width = OV5645_NATIVE_WIDTH;
> > > + fse->max_width = OV5645_NATIVE_WIDTH;
> > > + fse->min_height = OV5645_NATIVE_HEIGHT;
> > > + fse->max_height = OV5645_NATIVE_HEIGHT;
> > > + } else {
> > > + if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16 ||
> >
> > This will be interesting. With internal pads we will introduce the
> > concept of a "subdev model", which will formally document how the V4L2
> > subdev configuration items (formats, selection rectangles, ...) maps to
> > hardware features. Sakari is working on the definition of a subdev model
> > for raw sensors, that should catter for the needs of raw sensors without
> > a bayer scaler (the vast majority of them). To use internal pads with a
> > non-raw sensor, we'll have to define a model. It may be more
> > challenging/complicated to do so, as the YUV sensor features are less
> > standardized, but it will be an interesting development.
>
> I think I'll make the sub-device model a bitmask, to allow implementing
> more than one at the same time.
>
> I'll try to remember to cc you to the patchset when I'll send it, likely
> next week.
>
Great, I'll withhold sending a v3.
> >
> > > + fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
> > > + return -EINVAL;
> > > +
> > > + fse->min_width = ov5645_mode_info_data[fse->index].width;
> > > + fse->max_width = ov5645_mode_info_data[fse->index].width;
> > > + fse->min_height = ov5645_mode_info_data[fse->index].height;
> > > + fse->max_height = ov5645_mode_info_data[fse->index].height;
> > > + }
> > >
> > > return 0;
> > > }
> > > @@ -855,18 +876,55 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> > > {
> > > struct ov5645 *ov5645 = to_ov5645(sd);
> > > struct v4l2_mbus_framefmt *__format;
> > > + struct v4l2_rect *compose;
> > > struct v4l2_rect *__crop;
> >
> > While at it, could you rename __crop to crop ?
> >
> > > const struct ov5645_mode_info *new_mode;
> > > int ret;
> > >
> > > - __crop = v4l2_subdev_state_get_crop(sd_state, 0);
> > > + if (format->pad != OV5645_PAD_SOURCE)
> > > + return v4l2_subdev_get_fmt(sd, sd_state, format);
> > > +
> > > new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
> > > ARRAY_SIZE(ov5645_mode_info_data),
> > > width, height, format->format.width,
> > > format->format.height);
> > > -
> > > - __crop->width = new_mode->width;
> > > - __crop->height = new_mode->height;
> > > + format->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
> > > + format->format.width = new_mode->width;
> > > + format->format.height = new_mode->height;
> > > + format->format.field = V4L2_FIELD_NONE;
> > > + format->format.colorspace = V4L2_COLORSPACE_SRGB;
> > > + format->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> > > + format->format.quantization = V4L2_QUANTIZATION_DEFAULT;
> > > + format->format.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> >
> > Drivers are not supposed to return DEFAULT values, you should pick
> > appropriate values.
> >
> > > +
> > > + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE);
> >
> > Maybe __format could also become fmt.
> >
> > > + *__format = format->format;
> > > + __format->code = OV5645_NATIVE_FORMAT;
> > > + __format->width = OV5645_NATIVE_WIDTH;
> > > + __format->height = OV5645_NATIVE_HEIGHT;
> > > +
> > > + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE);
> > > + __crop->width = format->format.width;
> > > + __crop->height = format->format.height;
> > > +
> > > + /*
> > > + * The compose rectangle models binning, its size is the sensor output
> > > + * size.
> > > + */
> > > + compose = v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE);
> > > + compose->left = 0;
> > > + compose->top = 0;
> > > + compose->width = format->format.width;
> > > + compose->height = format->format.height;
> > > +
> > > + __crop = v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE);
> > > + __crop->left = 0;
> > > + __crop->top = 0;
> > > + __crop->width = format->format.width;
> > > + __crop->height = format->format.height;
> > > +
> > > + __format = v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE);
> > > + *__format = format->format;
> > >
> > > if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> > > ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
> > > @@ -882,14 +940,6 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
> > > ov5645->current_mode = new_mode;
> > > }
> > >
> > > - __format = v4l2_subdev_state_get_format(sd_state, 0);
> > > - __format->width = __crop->width;
> > > - __format->height = __crop->height;
> > > - __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
> > > - __format->field = V4L2_FIELD_NONE;
> > > - __format->colorspace = V4L2_COLORSPACE_SRGB;
> > > -
> > > - format->format = *__format;
> > >
> > > return 0;
> > > }
> > > @@ -899,7 +949,7 @@ static int ov5645_init_state(struct v4l2_subdev *subdev,
> > > {
> > > struct v4l2_subdev_format fmt = {
> > > .which = V4L2_SUBDEV_FORMAT_TRY,
> > > - .pad = 0,
> > > + .pad = OV5645_PAD_SOURCE,
> > > .format = {
> > > .code = MEDIA_BUS_FMT_UYVY8_1X16,
> > > .width = ov5645_mode_info_data[1].width,
> > > @@ -919,7 +969,7 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
> > > if (sel->target != V4L2_SEL_TGT_CROP)
> > > return -EINVAL;
> > >
> > > - sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
> > > + sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
> >
> > Now there's a compose rectangle, you should support getting it.
> >
> > > return 0;
> > > }
> > >
> > > @@ -1123,11 +1173,12 @@ static int ov5645_probe(struct i2c_client *client)
> > > v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
> > > ov5645->sd.internal_ops = &ov5645_internal_ops;
> > > ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> > > - ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
> > > + ov5645->pads[OV5645_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
> > > + ov5645->pads[OV5645_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
> > > ov5645->sd.dev = dev;
> > > ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> > >
> > > - ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
> > > + ret = media_entity_pads_init(&ov5645->sd.entity, ARRAY_SIZE(ov5645->pads), ov5645->pads);
> >
> > Line wrap.
>
> It's good to run:
>
> scripts/checkpatch.pl --strict --max-line-length=80
>
> on the patches.
>
Thanks for the pointer.
Cheers,
Prabhakar
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors
2024-09-27 15:31 ` Lad, Prabhakar
@ 2024-09-27 16:01 ` Sakari Ailus
0 siblings, 0 replies; 34+ messages in thread
From: Sakari Ailus @ 2024-09-27 16:01 UTC (permalink / raw)
To: Lad, Prabhakar
Cc: Laurent Pinchart, Kieran Bingham, Tomi Valkeinen, Jacopo Mondi,
Mauro Carvalho Chehab, Hans Verkuil, linux-media, linux-kernel,
linux-renesas-soc, Biju Das, Fabrizio Castro, Lad Prabhakar
Hi Prabhakar,
On Fri, Sep 27, 2024 at 04:31:31PM +0100, Lad, Prabhakar wrote:
> Hi Sakari and Laurent,
>
> On Thu, Sep 26, 2024 at 7:57 PM Sakari Ailus
> <sakari.ailus@linux.intel.com> wrote:
> >
> > On Thu, Sep 26, 2024 at 08:48:19PM +0300, Laurent Pinchart wrote:
> > > On Thu, Sep 26, 2024 at 03:45:26PM +0000, Sakari Ailus wrote:
> > > > Hi Prabhakar,
> > > >
> > > > Thanks for the set. It looks largely very nice to me, after addressing
> > > > Laurent's comments. A few comments here and possibly on other patches...
> > > >
> > > > On Tue, Sep 10, 2024 at 06:06:10PM +0100, Prabhakar wrote:
> > > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > >
> > > > > Implement the .get_frame_desc() subdev operation to report information
> > > > > about streams to the connected CSI-2 receiver. This is required to let
> > > > > the CSI-2 receiver driver know about virtual channels and data types for
> > > > > each stream.
> > > > >
> > > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > > ---
> > > > > drivers/media/i2c/ov5645.c | 28 ++++++++++++++++++++++++++++
> > > > > 1 file changed, 28 insertions(+)
> > > > >
> > > > > diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
> > > > > index 7f1133292ffc..c24eb6e7a7b5 100644
> > > > > --- a/drivers/media/i2c/ov5645.c
> > > > > +++ b/drivers/media/i2c/ov5645.c
> > > > > @@ -28,6 +28,7 @@
> > > > > #include <linux/regulator/consumer.h>
> > > > > #include <linux/slab.h>
> > > > > #include <linux/types.h>
> > > > > +#include <media/mipi-csi2.h>
> > > > > #include <media/v4l2-ctrls.h>
> > > > > #include <media/v4l2-event.h>
> > > > > #include <media/v4l2-fwnode.h>
> > > > > @@ -829,6 +830,32 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {
> > > > > .s_ctrl = ov5645_s_ctrl,
> > > > > };
> > > > >
> > > > > +static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> > > > > + struct v4l2_mbus_frame_desc *fd)
> > > > > +{
> > > > > + const struct v4l2_mbus_framefmt *fmt;
> > > > > + struct v4l2_subdev_state *state;
> > > > > +
> > > > > + if (pad != OV5645_PAD_SOURCE)
> > > > > + return -EINVAL;
> > > >
> > > > As you have a single source pad, and pretty much all sensor drivers will, I
> > > > think it'd be nice to add a check for this (that it's not an internal pad)
> > > > to the caller side in v4l2-subdev.c. And of course drop this one.
> > >
> > > What check would you add, just verifying that the pad is a source pad ?
> >
> > I think you could add that, too, besides the absence of the internal flag.
> >
> Checking only for the source flag should suffice, as the
> MEDIA_PAD_FL_INTERNAL flag cannot be set for a source pad because
> media_entity_pads_init() enforces this restriction.
>
> Do you agree?
Works for me.
--
Sakari Ailus
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2024-09-27 16:01 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-10 17:05 [PATCH v2 00/11] media: ov5645: Add support for streams Prabhakar
2024-09-10 17:06 ` [PATCH v2 01/11] media: i2c: ov5645: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Prabhakar
2024-09-24 22:35 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 02/11] media: i2c: ov5645: Use local `dev` pointer for subdev device assignment Prabhakar
2024-09-24 22:35 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 03/11] media: i2c: ov5645: Enable runtime PM after v4l2_async_register_subdev() Prabhakar
2024-09-24 22:37 ` Laurent Pinchart
2024-09-25 15:22 ` Lad, Prabhakar
2024-09-10 17:06 ` [PATCH v2 04/11] media: i2c: ov5645: Use dev_err_probe instead of dev_err Prabhakar
2024-09-24 22:43 ` Laurent Pinchart
2024-09-25 15:24 ` Lad, Prabhakar
2024-09-10 17:06 ` [PATCH v2 05/11] media: i2c: ov5645: Use v4l2_async_register_subdev_sensor() Prabhakar
2024-09-24 22:44 ` Laurent Pinchart
2024-09-25 15:26 ` Lad, Prabhakar
2024-09-10 17:06 ` [PATCH v2 06/11] media: i2c: ov5645: Drop `power_lock` mutex Prabhakar
2024-09-24 22:46 ` Laurent Pinchart
2024-09-25 15:35 ` Lad, Prabhakar
2024-09-10 17:06 ` [PATCH v2 07/11] media: i2c: ov5645: Use subdev active state Prabhakar
2024-09-24 22:51 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 08/11] media: i2c: ov5645: Switch to {enable,disable}_streams Prabhakar
2024-09-24 22:55 ` Laurent Pinchart
2024-09-10 17:06 ` [PATCH v2 09/11] media: i2c: ov5645: Add internal image sink pad Prabhakar
2024-09-25 16:21 ` Laurent Pinchart
2024-09-26 15:49 ` Sakari Ailus
2024-09-27 15:35 ` Lad, Prabhakar
2024-09-10 17:06 ` [PATCH v2 10/11] media: i2c: ov5645: Report internal routes to userspace Prabhakar
2024-09-10 17:06 ` [PATCH v2 11/11] media: i2c: ov5645: Report streams using frame descriptors Prabhakar
2024-09-25 16:26 ` Laurent Pinchart
2024-09-26 10:16 ` Lad, Prabhakar
2024-09-26 15:45 ` Sakari Ailus
2024-09-26 17:48 ` Laurent Pinchart
2024-09-26 18:57 ` Sakari Ailus
2024-09-27 15:31 ` Lad, Prabhakar
2024-09-27 16:01 ` Sakari Ailus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox