* [PATCH 1/2] media: i2c: ov13b10: Fix h_blank calculation
@ 2025-03-07 9:31 Hao Yao
2025-03-07 9:31 ` [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode Hao Yao
0 siblings, 1 reply; 7+ messages in thread
From: Hao Yao @ 2025-03-07 9:31 UTC (permalink / raw)
To: Sakari Ailus, Arec Kao, Mauro Carvalho Chehab, linux-media
Cc: Hao Yao, Bingbu Cao
Pixel per line (PPL) is calculated as pixel_rate / (VTS * FPS), which
is not decided by MIPI CSI-2 link frequency. PPL can vary while link
frequency keeps the same. If PPL is wrong, the h_blank = PPL - width
is also wrong then FPS control is inaccurate.
This patch fix h_blank by:
1. Move PPL from link_freq_config to ov13b10_mode
2. Add PPL value for different modes
3. Use PPL from mode to calculate h_blank
Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
Signed-off-by: Hao Yao <hao.yao@intel.com>
---
drivers/media/i2c/ov13b10.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index 73c844aa5697..2e83fc23f321 100644
--- a/drivers/media/i2c/ov13b10.c
+++ b/drivers/media/i2c/ov13b10.c
@@ -34,9 +34,6 @@
#define OV13B10_VTS_120FPS 0x0320
#define OV13B10_VTS_MAX 0x7fff
-/* HBLANK control - read only */
-#define OV13B10_PPL_560MHZ 4704
-
/* Exposure control */
#define OV13B10_REG_EXPOSURE 0x3500
#define OV13B10_EXPOSURE_MIN 4
@@ -95,7 +92,7 @@ struct ov13b10_reg_list {
/* Link frequency config */
struct ov13b10_link_freq_config {
- u32 pixels_per_line;
+ u64 link_freq;
/* registers for this link frequency */
struct ov13b10_reg_list reg_list;
@@ -114,6 +111,10 @@ struct ov13b10_mode {
/* Index of Link frequency config to be used */
u32 link_freq_index;
+
+ /* Pixels per line in current mode */
+ u32 ppl;
+
/* Default register values */
struct ov13b10_reg_list reg_list;
};
@@ -549,7 +550,7 @@ static const s64 link_freq_menu_items[] = {
static const struct ov13b10_link_freq_config
link_freq_configs[] = {
{
- .pixels_per_line = OV13B10_PPL_560MHZ,
+ .link_freq = OV13B10_LINK_FREQ_560MHZ,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mipi_data_rate_1120mbps),
.regs = mipi_data_rate_1120mbps,
@@ -564,6 +565,7 @@ static const struct ov13b10_mode supported_modes[] = {
.height = 3120,
.vts_def = OV13B10_VTS_30FPS,
.vts_min = OV13B10_VTS_30FPS,
+ .ppl = 4704,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_4208x3120_regs),
.regs = mode_4208x3120_regs,
@@ -575,6 +577,7 @@ static const struct ov13b10_mode supported_modes[] = {
.height = 3120,
.vts_def = OV13B10_VTS_30FPS,
.vts_min = OV13B10_VTS_30FPS,
+ .ppl = 4704,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_4160x3120_regs),
.regs = mode_4160x3120_regs,
@@ -586,6 +589,7 @@ static const struct ov13b10_mode supported_modes[] = {
.height = 2340,
.vts_def = OV13B10_VTS_30FPS,
.vts_min = OV13B10_VTS_30FPS,
+ .ppl = 4704,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_4160x2340_regs),
.regs = mode_4160x2340_regs,
@@ -597,6 +601,7 @@ static const struct ov13b10_mode supported_modes[] = {
.height = 1560,
.vts_def = OV13B10_VTS_60FPS,
.vts_min = OV13B10_VTS_60FPS,
+ .ppl = 4704,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2104x1560_regs),
.regs = mode_2104x1560_regs,
@@ -608,6 +613,7 @@ static const struct ov13b10_mode supported_modes[] = {
.height = 1170,
.vts_def = OV13B10_VTS_60FPS,
.vts_min = OV13B10_VTS_60FPS,
+ .ppl = 4704,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2080x1170_regs),
.regs = mode_2080x1170_regs,
@@ -620,6 +626,7 @@ static const struct ov13b10_mode supported_modes[] = {
.vts_def = OV13B10_VTS_120FPS,
.vts_min = OV13B10_VTS_120FPS,
.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
+ .ppl = 4664,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1364x768_120fps_regs),
.regs = mode_1364x768_120fps_regs,
@@ -1062,19 +1069,13 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
__v4l2_ctrl_s_ctrl_int64(ov13b->pixel_rate, pixel_rate);
/* Update limits and set FPS to default */
- vblank_def = ov13b->cur_mode->vts_def -
- ov13b->cur_mode->height;
- vblank_min = ov13b->cur_mode->vts_min -
- ov13b->cur_mode->height;
+ vblank_def = mode->vts_def - mode->height;
+ vblank_min = mode->vts_min - mode->height;
__v4l2_ctrl_modify_range(ov13b->vblank, vblank_min,
- OV13B10_VTS_MAX
- - ov13b->cur_mode->height,
- 1,
- vblank_def);
+ OV13B10_VTS_MAX - mode->height,
+ 1, vblank_def);
__v4l2_ctrl_s_ctrl(ov13b->vblank, vblank_def);
- h_blank =
- link_freq_configs[mode->link_freq_index].pixels_per_line
- - ov13b->cur_mode->width;
+ h_blank = mode->ppl - mode->width;
__v4l2_ctrl_modify_range(ov13b->hblank, h_blank,
h_blank, 1, h_blank);
}
@@ -1328,8 +1329,7 @@ static int ov13b10_init_controls(struct ov13b10 *ov13b)
OV13B10_VTS_MAX - mode->height, 1,
vblank_def);
- hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
- mode->width;
+ hblank = mode->ppl - mode->width;
ov13b->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
V4L2_CID_HBLANK,
hblank, hblank, 1, hblank);
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-07 9:31 [PATCH 1/2] media: i2c: ov13b10: Fix h_blank calculation Hao Yao
@ 2025-03-07 9:31 ` Hao Yao
2025-03-07 9:43 ` Sakari Ailus
0 siblings, 1 reply; 7+ messages in thread
From: Hao Yao @ 2025-03-07 9:31 UTC (permalink / raw)
To: Sakari Ailus, Arec Kao, Mauro Carvalho Chehab, linux-media
Cc: Hao Yao, Bingbu Cao
1. Fix pixel rate calculation to consider different lane number
2. Add 2104x1560 60fps 2 data lanes register setting
3. Support 2 lane in check_hwcfg
4. Select correct mode considering lane number used
Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
Signed-off-by: Hao Yao <hao.yao@intel.com>
---
drivers/media/i2c/ov13b10.c | 134 ++++++++++++++++++++++++++++++------
1 file changed, 112 insertions(+), 22 deletions(-)
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index 2e83fc23f321..20481b8d4e79 100644
--- a/drivers/media/i2c/ov13b10.c
+++ b/drivers/media/i2c/ov13b10.c
@@ -514,6 +514,52 @@ static const struct ov13b10_reg mode_1364x768_120fps_regs[] = {
{0x5001, 0x0d},
};
+static const struct ov13b10_reg mode_2lanes_2104x1560_60fps_regs[] = {
+ {0x3016, 0x32},
+ {0x3106, 0x29},
+ {0x0305, 0xaf},
+ {0x3501, 0x06},
+ {0x3662, 0x88},
+ {0x3714, 0x28},
+ {0x3739, 0x10},
+ {0x37c2, 0x14},
+ {0x37d9, 0x06},
+ {0x37e2, 0x0c},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x08},
+ {0x3804, 0x10},
+ {0x3805, 0x8f},
+ {0x3806, 0x0c},
+ {0x3807, 0x47},
+ {0x3808, 0x08},
+ {0x3809, 0x38},
+ {0x380a, 0x06},
+ {0x380b, 0x18},
+ {0x380c, 0x04},
+ {0x380d, 0x98},
+ {0x380e, 0x06},
+ {0x380f, 0x3e},
+ {0x3810, 0x00},
+ {0x3811, 0x07},
+ {0x3812, 0x00},
+ {0x3813, 0x05},
+ {0x3814, 0x03},
+ {0x3816, 0x03},
+ {0x3820, 0x8b},
+ {0x3c8c, 0x18},
+ {0x4008, 0x00},
+ {0x4009, 0x05},
+ {0x4050, 0x00},
+ {0x4051, 0x05},
+ {0x4501, 0x08},
+ {0x4505, 0x00},
+ {0x4837, 0x0e},
+ {0x5000, 0xfd},
+ {0x5001, 0x0d},
+};
+
static const char * const ov13b10_test_pattern_menu[] = {
"Disabled",
"Vertical Color Bar Type 1",
@@ -527,15 +573,16 @@ static const char * const ov13b10_test_pattern_menu[] = {
#define OV13B10_LINK_FREQ_INDEX_0 0
#define OV13B10_EXT_CLK 19200000
-#define OV13B10_DATA_LANES 4
+#define OV13B10_4_DATA_LANES 4
+#define OV13B10_2_DATA_LANES 2
/*
- * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
- * data rate => double data rate; number of lanes => 4; bits per pixel => 10
+ * pixel_rate = data_rate * nr_of_lanes / bits_per_pixel
+ * data_rate => link_freq * 2; number of lanes => 4; bits per pixel => 10
*/
-static u64 link_freq_to_pixel_rate(u64 f)
+static u64 link_freq_to_pixel_rate(u64 f, u8 lanes)
{
- f *= 2 * OV13B10_DATA_LANES;
+ f *= 2 * lanes;
do_div(f, 10);
return f;
@@ -559,7 +606,8 @@ static const struct ov13b10_link_freq_config
};
/* Mode configs */
-static const struct ov13b10_mode supported_modes[] = {
+static const struct ov13b10_mode supported_4_lanes_modes[] = {
+ /* 4 data lanes */
{
.width = 4208,
.height = 3120,
@@ -634,6 +682,23 @@ static const struct ov13b10_mode supported_modes[] = {
},
};
+static const struct ov13b10_mode supported_2_lanes_modes[] = {
+ /* 2 data lanes */
+ {
+ .width = 2104,
+ .height = 1560,
+ .vts_def = OV13B10_VTS_60FPS,
+ .vts_min = OV13B10_VTS_60FPS,
+ .link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
+ .ppl = 2352,
+ .reg_list = {
+ .num_of_regs =
+ ARRAY_SIZE(mode_2lanes_2104x1560_60fps_regs),
+ .regs = mode_2lanes_2104x1560_60fps_regs,
+ },
+ },
+};
+
struct ov13b10 {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -651,12 +716,20 @@ struct ov13b10 {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure;
+ /* Supported modes */
+ const struct ov13b10_mode *supported_modes;
+
/* Current mode */
const struct ov13b10_mode *cur_mode;
/* Mutex for serialized access */
struct mutex mutex;
+ u8 supported_modes_num;
+
+ /* Data lanes used */
+ u8 data_lanes;
+
/* True if the device has been identified */
bool identified;
};
@@ -760,8 +833,8 @@ static int ov13b10_write_reg_list(struct ov13b10 *ov13b,
/* Open sub-device */
static int ov13b10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
- const struct ov13b10_mode *default_mode = &supported_modes[0];
struct ov13b10 *ov13b = to_ov13b10(sd);
+ const struct ov13b10_mode *default_mode = ov13b->supported_modes;
struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state,
0);
@@ -980,7 +1053,10 @@ static int ov13b10_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->index >= ARRAY_SIZE(supported_modes))
+ struct ov13b10 *ov13b = to_ov13b10(sd);
+ const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
+
+ if (fse->index >= ov13b->supported_modes_num)
return -EINVAL;
if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
@@ -1040,6 +1116,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
{
struct ov13b10 *ov13b = to_ov13b10(sd);
const struct ov13b10_mode *mode;
+ const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
struct v4l2_mbus_framefmt *framefmt;
s32 vblank_def;
s32 vblank_min;
@@ -1054,7 +1131,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
mode = v4l2_find_nearest_size(supported_modes,
- ARRAY_SIZE(supported_modes),
+ ov13b->supported_modes_num,
width, height,
fmt->format.width, fmt->format.height);
ov13b10_update_pad_format(mode, fmt);
@@ -1065,7 +1142,8 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
ov13b->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov13b->link_freq, mode->link_freq_index);
link_freq = link_freq_menu_items[mode->link_freq_index];
- pixel_rate = link_freq_to_pixel_rate(link_freq);
+ pixel_rate = link_freq_to_pixel_rate(link_freq,
+ ov13b->data_lanes);
__v4l2_ctrl_s_ctrl_int64(ov13b->pixel_rate, pixel_rate);
/* Update limits and set FPS to default */
@@ -1312,7 +1390,8 @@ static int ov13b10_init_controls(struct ov13b10 *ov13b)
if (ov13b->link_freq)
ov13b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
+ pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0],
+ ov13b->data_lanes);
pixel_rate_min = 0;
/* By default, PIXEL_RATE is read only */
ov13b->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
@@ -1423,7 +1502,7 @@ static int ov13b10_get_pm_resources(struct device *dev)
return 0;
}
-static int ov13b10_check_hwcfg(struct device *dev)
+static int ov13b10_check_hwcfg(struct device *dev, struct ov13b10 *ov13b)
{
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY
@@ -1433,6 +1512,7 @@ static int ov13b10_check_hwcfg(struct device *dev)
unsigned int i, j;
int ret;
u32 ext_clk;
+ u8 dlane;
if (!fwnode)
return -ENXIO;
@@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
if (ret)
return ret;
- if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
+ dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
+ if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
dev_err(dev, "number of CSI2 data lanes %d is not supported",
- bus_cfg.bus.mipi_csi2.num_data_lanes);
+ dlane);
ret = -EINVAL;
goto out_err;
}
+ ov13b->data_lanes = dlane;
+ ov13b->supported_modes = supported_4_lanes_modes;
+ ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
+ if (dlane == OV13B10_2_DATA_LANES) {
+ ov13b->supported_modes = supported_2_lanes_modes;
+ ov13b->supported_modes_num =
+ ARRAY_SIZE(supported_2_lanes_modes);
+ }
+
+ ov13b->cur_mode = ov13b->supported_modes;
+ dev_dbg(dev, "%u lanes with %u modes selected\n",
+ ov13b->data_lanes, ov13b->supported_modes_num);
if (!bus_cfg.nr_of_link_frequencies) {
dev_err(dev, "no link frequencies defined");
@@ -1499,17 +1592,17 @@ static int ov13b10_probe(struct i2c_client *client)
bool full_power;
int ret;
+ ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
+ if (!ov13b)
+ return -ENOMEM;
+
/* Check HW config */
- ret = ov13b10_check_hwcfg(&client->dev);
+ ret = ov13b10_check_hwcfg(&client->dev, ov13b);
if (ret) {
dev_err(&client->dev, "failed to check hwcfg: %d", ret);
return ret;
}
- ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
- if (!ov13b)
- return -ENOMEM;
-
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
@@ -1533,9 +1626,6 @@ static int ov13b10_probe(struct i2c_client *client)
}
}
- /* Set default mode to max resolution */
- ov13b->cur_mode = &supported_modes[0];
-
ret = ov13b10_init_controls(ov13b);
if (ret)
goto error_power_off;
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-07 9:31 ` [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode Hao Yao
@ 2025-03-07 9:43 ` Sakari Ailus
2025-03-10 4:06 ` Hao Yao
0 siblings, 1 reply; 7+ messages in thread
From: Sakari Ailus @ 2025-03-07 9:43 UTC (permalink / raw)
To: Hao Yao; +Cc: Arec Kao, Mauro Carvalho Chehab, linux-media, Bingbu Cao
Hi Bingbu, Hao,
Thanks for the patchset.
On Fri, Mar 07, 2025 at 05:31:17PM +0800, Hao Yao wrote:
> 1. Fix pixel rate calculation to consider different lane number
> 2. Add 2104x1560 60fps 2 data lanes register setting
> 3. Support 2 lane in check_hwcfg
> 4. Select correct mode considering lane number used
>
> Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
> Signed-off-by: Hao Yao <hao.yao@intel.com>
> ---
> drivers/media/i2c/ov13b10.c | 134 ++++++++++++++++++++++++++++++------
> 1 file changed, 112 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
> index 2e83fc23f321..20481b8d4e79 100644
> --- a/drivers/media/i2c/ov13b10.c
> +++ b/drivers/media/i2c/ov13b10.c
> @@ -514,6 +514,52 @@ static const struct ov13b10_reg mode_1364x768_120fps_regs[] = {
> {0x5001, 0x0d},
> };
>
> +static const struct ov13b10_reg mode_2lanes_2104x1560_60fps_regs[] = {
> + {0x3016, 0x32},
> + {0x3106, 0x29},
> + {0x0305, 0xaf},
> + {0x3501, 0x06},
> + {0x3662, 0x88},
> + {0x3714, 0x28},
> + {0x3739, 0x10},
> + {0x37c2, 0x14},
> + {0x37d9, 0x06},
> + {0x37e2, 0x0c},
> + {0x3800, 0x00},
> + {0x3801, 0x00},
> + {0x3802, 0x00},
> + {0x3803, 0x08},
> + {0x3804, 0x10},
> + {0x3805, 0x8f},
> + {0x3806, 0x0c},
> + {0x3807, 0x47},
> + {0x3808, 0x08},
> + {0x3809, 0x38},
> + {0x380a, 0x06},
> + {0x380b, 0x18},
> + {0x380c, 0x04},
> + {0x380d, 0x98},
> + {0x380e, 0x06},
> + {0x380f, 0x3e},
> + {0x3810, 0x00},
> + {0x3811, 0x07},
> + {0x3812, 0x00},
> + {0x3813, 0x05},
> + {0x3814, 0x03},
> + {0x3816, 0x03},
> + {0x3820, 0x8b},
> + {0x3c8c, 0x18},
> + {0x4008, 0x00},
> + {0x4009, 0x05},
> + {0x4050, 0x00},
> + {0x4051, 0x05},
> + {0x4501, 0x08},
> + {0x4505, 0x00},
> + {0x4837, 0x0e},
> + {0x5000, 0xfd},
> + {0x5001, 0x0d},
> +};
> +
> static const char * const ov13b10_test_pattern_menu[] = {
> "Disabled",
> "Vertical Color Bar Type 1",
> @@ -527,15 +573,16 @@ static const char * const ov13b10_test_pattern_menu[] = {
> #define OV13B10_LINK_FREQ_INDEX_0 0
>
> #define OV13B10_EXT_CLK 19200000
> -#define OV13B10_DATA_LANES 4
> +#define OV13B10_4_DATA_LANES 4
> +#define OV13B10_2_DATA_LANES 2
>
> /*
> - * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
> - * data rate => double data rate; number of lanes => 4; bits per pixel => 10
> + * pixel_rate = data_rate * nr_of_lanes / bits_per_pixel
> + * data_rate => link_freq * 2; number of lanes => 4; bits per pixel => 10
> */
> -static u64 link_freq_to_pixel_rate(u64 f)
> +static u64 link_freq_to_pixel_rate(u64 f, u8 lanes)
> {
> - f *= 2 * OV13B10_DATA_LANES;
> + f *= 2 * lanes;
> do_div(f, 10);
>
> return f;
> @@ -559,7 +606,8 @@ static const struct ov13b10_link_freq_config
> };
>
> /* Mode configs */
> -static const struct ov13b10_mode supported_modes[] = {
> +static const struct ov13b10_mode supported_4_lanes_modes[] = {
> + /* 4 data lanes */
> {
> .width = 4208,
> .height = 3120,
> @@ -634,6 +682,23 @@ static const struct ov13b10_mode supported_modes[] = {
> },
> };
>
> +static const struct ov13b10_mode supported_2_lanes_modes[] = {
> + /* 2 data lanes */
> + {
> + .width = 2104,
> + .height = 1560,
> + .vts_def = OV13B10_VTS_60FPS,
> + .vts_min = OV13B10_VTS_60FPS,
> + .link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
> + .ppl = 2352,
> + .reg_list = {
> + .num_of_regs =
> + ARRAY_SIZE(mode_2lanes_2104x1560_60fps_regs),
> + .regs = mode_2lanes_2104x1560_60fps_regs,
> + },
> + },
> +};
> +
> struct ov13b10 {
> struct v4l2_subdev sd;
> struct media_pad pad;
> @@ -651,12 +716,20 @@ struct ov13b10 {
> struct v4l2_ctrl *hblank;
> struct v4l2_ctrl *exposure;
>
> + /* Supported modes */
> + const struct ov13b10_mode *supported_modes;
> +
> /* Current mode */
> const struct ov13b10_mode *cur_mode;
>
> /* Mutex for serialized access */
> struct mutex mutex;
>
> + u8 supported_modes_num;
> +
> + /* Data lanes used */
> + u8 data_lanes;
> +
> /* True if the device has been identified */
> bool identified;
> };
> @@ -760,8 +833,8 @@ static int ov13b10_write_reg_list(struct ov13b10 *ov13b,
> /* Open sub-device */
> static int ov13b10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> {
> - const struct ov13b10_mode *default_mode = &supported_modes[0];
> struct ov13b10 *ov13b = to_ov13b10(sd);
> + const struct ov13b10_mode *default_mode = ov13b->supported_modes;
> struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state,
> 0);
>
> @@ -980,7 +1053,10 @@ static int ov13b10_enum_frame_size(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_frame_size_enum *fse)
> {
> - if (fse->index >= ARRAY_SIZE(supported_modes))
> + struct ov13b10 *ov13b = to_ov13b10(sd);
> + const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
> +
> + if (fse->index >= ov13b->supported_modes_num)
> return -EINVAL;
>
> if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
> @@ -1040,6 +1116,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
> {
> struct ov13b10 *ov13b = to_ov13b10(sd);
> const struct ov13b10_mode *mode;
> + const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
> struct v4l2_mbus_framefmt *framefmt;
> s32 vblank_def;
> s32 vblank_min;
> @@ -1054,7 +1131,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
> fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
>
> mode = v4l2_find_nearest_size(supported_modes,
> - ARRAY_SIZE(supported_modes),
> + ov13b->supported_modes_num,
> width, height,
> fmt->format.width, fmt->format.height);
> ov13b10_update_pad_format(mode, fmt);
> @@ -1065,7 +1142,8 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
> ov13b->cur_mode = mode;
> __v4l2_ctrl_s_ctrl(ov13b->link_freq, mode->link_freq_index);
> link_freq = link_freq_menu_items[mode->link_freq_index];
> - pixel_rate = link_freq_to_pixel_rate(link_freq);
> + pixel_rate = link_freq_to_pixel_rate(link_freq,
> + ov13b->data_lanes);
> __v4l2_ctrl_s_ctrl_int64(ov13b->pixel_rate, pixel_rate);
>
> /* Update limits and set FPS to default */
> @@ -1312,7 +1390,8 @@ static int ov13b10_init_controls(struct ov13b10 *ov13b)
> if (ov13b->link_freq)
> ov13b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
>
> - pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
> + pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0],
> + ov13b->data_lanes);
> pixel_rate_min = 0;
> /* By default, PIXEL_RATE is read only */
> ov13b->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
> @@ -1423,7 +1502,7 @@ static int ov13b10_get_pm_resources(struct device *dev)
> return 0;
> }
>
> -static int ov13b10_check_hwcfg(struct device *dev)
> +static int ov13b10_check_hwcfg(struct device *dev, struct ov13b10 *ov13b)
> {
> struct v4l2_fwnode_endpoint bus_cfg = {
> .bus_type = V4L2_MBUS_CSI2_DPHY
> @@ -1433,6 +1512,7 @@ static int ov13b10_check_hwcfg(struct device *dev)
> unsigned int i, j;
> int ret;
> u32 ext_clk;
> + u8 dlane;
>
> if (!fwnode)
> return -ENXIO;
> @@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
> if (ret)
> return ret;
>
> - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
> + dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
> + if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
> dev_err(dev, "number of CSI2 data lanes %d is not supported",
> - bus_cfg.bus.mipi_csi2.num_data_lanes);
> + dlane);
> ret = -EINVAL;
> goto out_err;
> }
> + ov13b->data_lanes = dlane;
> + ov13b->supported_modes = supported_4_lanes_modes;
> + ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
> + if (dlane == OV13B10_2_DATA_LANES) {
> + ov13b->supported_modes = supported_2_lanes_modes;
> + ov13b->supported_modes_num =
> + ARRAY_SIZE(supported_2_lanes_modes);
How about using switch() here?
> + }
> +
> + ov13b->cur_mode = ov13b->supported_modes;
> + dev_dbg(dev, "%u lanes with %u modes selected\n",
> + ov13b->data_lanes, ov13b->supported_modes_num);
>
> if (!bus_cfg.nr_of_link_frequencies) {
> dev_err(dev, "no link frequencies defined");
> @@ -1499,17 +1592,17 @@ static int ov13b10_probe(struct i2c_client *client)
> bool full_power;
> int ret;
>
> + ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
> + if (!ov13b)
> + return -ENOMEM;
> +
> /* Check HW config */
> - ret = ov13b10_check_hwcfg(&client->dev);
> + ret = ov13b10_check_hwcfg(&client->dev, ov13b);
> if (ret) {
> dev_err(&client->dev, "failed to check hwcfg: %d", ret);
> return ret;
> }
>
> - ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
> - if (!ov13b)
> - return -ENOMEM;
> -
> /* Initialize subdev */
> v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
>
> @@ -1533,9 +1626,6 @@ static int ov13b10_probe(struct i2c_client *client)
> }
> }
>
> - /* Set default mode to max resolution */
> - ov13b->cur_mode = &supported_modes[0];
> -
> ret = ov13b10_init_controls(ov13b);
> if (ret)
> goto error_power_off;
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-07 9:43 ` Sakari Ailus
@ 2025-03-10 4:06 ` Hao Yao
2025-03-10 7:14 ` Sakari Ailus
0 siblings, 1 reply; 7+ messages in thread
From: Hao Yao @ 2025-03-10 4:06 UTC (permalink / raw)
To: Sakari Ailus; +Cc: Arec Kao, Mauro Carvalho Chehab, linux-media, Bingbu Cao
Hi Sakari,
Thanks for reviewing this.
On 2025/3/7 17:43, Sakari Ailus wrote:
> Hi Bingbu, Hao,
>
> Thanks for the patchset.
>
> On Fri, Mar 07, 2025 at 05:31:17PM +0800, Hao Yao wrote:
>> 1. Fix pixel rate calculation to consider different lane number
>> 2. Add 2104x1560 60fps 2 data lanes register setting
>> 3. Support 2 lane in check_hwcfg
>> 4. Select correct mode considering lane number used
>>
>> Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
>> Signed-off-by: Hao Yao <hao.yao@intel.com>
>> ---
>> drivers/media/i2c/ov13b10.c | 134 ++++++++++++++++++++++++++++++------
>> 1 file changed, 112 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
>> index 2e83fc23f321..20481b8d4e79 100644
>> --- a/drivers/media/i2c/ov13b10.c
>> +++ b/drivers/media/i2c/ov13b10.c
>> @@ -514,6 +514,52 @@ static const struct ov13b10_reg mode_1364x768_120fps_regs[] = {
>> {0x5001, 0x0d},
>> };
>>
>> +static const struct ov13b10_reg mode_2lanes_2104x1560_60fps_regs[] = {
>> + {0x3016, 0x32},
>> + {0x3106, 0x29},
>> + {0x0305, 0xaf},
>> + {0x3501, 0x06},
>> + {0x3662, 0x88},
>> + {0x3714, 0x28},
>> + {0x3739, 0x10},
>> + {0x37c2, 0x14},
>> + {0x37d9, 0x06},
>> + {0x37e2, 0x0c},
>> + {0x3800, 0x00},
>> + {0x3801, 0x00},
>> + {0x3802, 0x00},
>> + {0x3803, 0x08},
>> + {0x3804, 0x10},
>> + {0x3805, 0x8f},
>> + {0x3806, 0x0c},
>> + {0x3807, 0x47},
>> + {0x3808, 0x08},
>> + {0x3809, 0x38},
>> + {0x380a, 0x06},
>> + {0x380b, 0x18},
>> + {0x380c, 0x04},
>> + {0x380d, 0x98},
>> + {0x380e, 0x06},
>> + {0x380f, 0x3e},
>> + {0x3810, 0x00},
>> + {0x3811, 0x07},
>> + {0x3812, 0x00},
>> + {0x3813, 0x05},
>> + {0x3814, 0x03},
>> + {0x3816, 0x03},
>> + {0x3820, 0x8b},
>> + {0x3c8c, 0x18},
>> + {0x4008, 0x00},
>> + {0x4009, 0x05},
>> + {0x4050, 0x00},
>> + {0x4051, 0x05},
>> + {0x4501, 0x08},
>> + {0x4505, 0x00},
>> + {0x4837, 0x0e},
>> + {0x5000, 0xfd},
>> + {0x5001, 0x0d},
>> +};
>> +
>> static const char * const ov13b10_test_pattern_menu[] = {
>> "Disabled",
>> "Vertical Color Bar Type 1",
>> @@ -527,15 +573,16 @@ static const char * const ov13b10_test_pattern_menu[] = {
>> #define OV13B10_LINK_FREQ_INDEX_0 0
>>
>> #define OV13B10_EXT_CLK 19200000
>> -#define OV13B10_DATA_LANES 4
>> +#define OV13B10_4_DATA_LANES 4
>> +#define OV13B10_2_DATA_LANES 2
>>
>> /*
>> - * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
>> - * data rate => double data rate; number of lanes => 4; bits per pixel => 10
>> + * pixel_rate = data_rate * nr_of_lanes / bits_per_pixel
>> + * data_rate => link_freq * 2; number of lanes => 4; bits per pixel => 10
>> */
>> -static u64 link_freq_to_pixel_rate(u64 f)
>> +static u64 link_freq_to_pixel_rate(u64 f, u8 lanes)
>> {
>> - f *= 2 * OV13B10_DATA_LANES;
>> + f *= 2 * lanes;
>> do_div(f, 10);
>>
>> return f;
>> @@ -559,7 +606,8 @@ static const struct ov13b10_link_freq_config
>> };
>>
>> /* Mode configs */
>> -static const struct ov13b10_mode supported_modes[] = {
>> +static const struct ov13b10_mode supported_4_lanes_modes[] = {
>> + /* 4 data lanes */
>> {
>> .width = 4208,
>> .height = 3120,
>> @@ -634,6 +682,23 @@ static const struct ov13b10_mode supported_modes[] = {
>> },
>> };
>>
>> +static const struct ov13b10_mode supported_2_lanes_modes[] = {
>> + /* 2 data lanes */
>> + {
>> + .width = 2104,
>> + .height = 1560,
>> + .vts_def = OV13B10_VTS_60FPS,
>> + .vts_min = OV13B10_VTS_60FPS,
>> + .link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
>> + .ppl = 2352,
>> + .reg_list = {
>> + .num_of_regs =
>> + ARRAY_SIZE(mode_2lanes_2104x1560_60fps_regs),
>> + .regs = mode_2lanes_2104x1560_60fps_regs,
>> + },
>> + },
>> +};
>> +
>> struct ov13b10 {
>> struct v4l2_subdev sd;
>> struct media_pad pad;
>> @@ -651,12 +716,20 @@ struct ov13b10 {
>> struct v4l2_ctrl *hblank;
>> struct v4l2_ctrl *exposure;
>>
>> + /* Supported modes */
>> + const struct ov13b10_mode *supported_modes;
>> +
>> /* Current mode */
>> const struct ov13b10_mode *cur_mode;
>>
>> /* Mutex for serialized access */
>> struct mutex mutex;
>>
>> + u8 supported_modes_num;
>> +
>> + /* Data lanes used */
>> + u8 data_lanes;
>> +
>> /* True if the device has been identified */
>> bool identified;
>> };
>> @@ -760,8 +833,8 @@ static int ov13b10_write_reg_list(struct ov13b10 *ov13b,
>> /* Open sub-device */
>> static int ov13b10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
>> {
>> - const struct ov13b10_mode *default_mode = &supported_modes[0];
>> struct ov13b10 *ov13b = to_ov13b10(sd);
>> + const struct ov13b10_mode *default_mode = ov13b->supported_modes;
>> struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state,
>> 0);
>>
>> @@ -980,7 +1053,10 @@ static int ov13b10_enum_frame_size(struct v4l2_subdev *sd,
>> struct v4l2_subdev_state *sd_state,
>> struct v4l2_subdev_frame_size_enum *fse)
>> {
>> - if (fse->index >= ARRAY_SIZE(supported_modes))
>> + struct ov13b10 *ov13b = to_ov13b10(sd);
>> + const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
>> +
>> + if (fse->index >= ov13b->supported_modes_num)
>> return -EINVAL;
>>
>> if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
>> @@ -1040,6 +1116,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
>> {
>> struct ov13b10 *ov13b = to_ov13b10(sd);
>> const struct ov13b10_mode *mode;
>> + const struct ov13b10_mode *supported_modes = ov13b->supported_modes;
>> struct v4l2_mbus_framefmt *framefmt;
>> s32 vblank_def;
>> s32 vblank_min;
>> @@ -1054,7 +1131,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
>> fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
>>
>> mode = v4l2_find_nearest_size(supported_modes,
>> - ARRAY_SIZE(supported_modes),
>> + ov13b->supported_modes_num,
>> width, height,
>> fmt->format.width, fmt->format.height);
>> ov13b10_update_pad_format(mode, fmt);
>> @@ -1065,7 +1142,8 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
>> ov13b->cur_mode = mode;
>> __v4l2_ctrl_s_ctrl(ov13b->link_freq, mode->link_freq_index);
>> link_freq = link_freq_menu_items[mode->link_freq_index];
>> - pixel_rate = link_freq_to_pixel_rate(link_freq);
>> + pixel_rate = link_freq_to_pixel_rate(link_freq,
>> + ov13b->data_lanes);
>> __v4l2_ctrl_s_ctrl_int64(ov13b->pixel_rate, pixel_rate);
>>
>> /* Update limits and set FPS to default */
>> @@ -1312,7 +1390,8 @@ static int ov13b10_init_controls(struct ov13b10 *ov13b)
>> if (ov13b->link_freq)
>> ov13b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>
>> - pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
>> + pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0],
>> + ov13b->data_lanes);
>> pixel_rate_min = 0;
>> /* By default, PIXEL_RATE is read only */
>> ov13b->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
>> @@ -1423,7 +1502,7 @@ static int ov13b10_get_pm_resources(struct device *dev)
>> return 0;
>> }
>>
>> -static int ov13b10_check_hwcfg(struct device *dev)
>> +static int ov13b10_check_hwcfg(struct device *dev, struct ov13b10 *ov13b)
>> {
>> struct v4l2_fwnode_endpoint bus_cfg = {
>> .bus_type = V4L2_MBUS_CSI2_DPHY
>> @@ -1433,6 +1512,7 @@ static int ov13b10_check_hwcfg(struct device *dev)
>> unsigned int i, j;
>> int ret;
>> u32 ext_clk;
>> + u8 dlane;
>>
>> if (!fwnode)
>> return -ENXIO;
>> @@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
>> if (ret)
>> return ret;
>>
>> - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
>> + dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
>> + if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
>> dev_err(dev, "number of CSI2 data lanes %d is not supported",
>> - bus_cfg.bus.mipi_csi2.num_data_lanes);
>> + dlane);
>> ret = -EINVAL;
>> goto out_err;
>> }
>> + ov13b->data_lanes = dlane;
>> + ov13b->supported_modes = supported_4_lanes_modes;
>> + ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
>> + if (dlane == OV13B10_2_DATA_LANES) {
>> + ov13b->supported_modes = supported_2_lanes_modes;
>> + ov13b->supported_modes_num =
>> + ARRAY_SIZE(supported_2_lanes_modes);
>
> How about using switch() here?
How about:
ov13b->data_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
switch (ov13b->data_lanes) {
case OV13B10_4_DATA_LANES:
ov13b->supported_modes = supported_4_lanes_modes;
ov13b->supported_modes_num =
ARRAY_SIZE(supported_4_lanes_modes);
break;
case OV13B10_2_DATA_LANES:
ov13b->supported_modes = supported_2_lanes_modes;
ov13b->supported_modes_num =
ARRAY_SIZE(supported_2_lanes_modes);
break;
default:
dev_err(dev, "number of CSI2 data lanes %d is not supported",
ov13b->data_lanes);
ret = -EINVAL;
goto out_err;
}
Best Regards,
Hao Yao
>
>> + }
>> +
>> + ov13b->cur_mode = ov13b->supported_modes;
>> + dev_dbg(dev, "%u lanes with %u modes selected\n",
>> + ov13b->data_lanes, ov13b->supported_modes_num);
>>
>> if (!bus_cfg.nr_of_link_frequencies) {
>> dev_err(dev, "no link frequencies defined");
>> @@ -1499,17 +1592,17 @@ static int ov13b10_probe(struct i2c_client *client)
>> bool full_power;
>> int ret;
>>
>> + ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
>> + if (!ov13b)
>> + return -ENOMEM;
>> +
>> /* Check HW config */
>> - ret = ov13b10_check_hwcfg(&client->dev);
>> + ret = ov13b10_check_hwcfg(&client->dev, ov13b);
>> if (ret) {
>> dev_err(&client->dev, "failed to check hwcfg: %d", ret);
>> return ret;
>> }
>>
>> - ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
>> - if (!ov13b)
>> - return -ENOMEM;
>> -
>> /* Initialize subdev */
>> v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
>>
>> @@ -1533,9 +1626,6 @@ static int ov13b10_probe(struct i2c_client *client)
>> }
>> }
>>
>> - /* Set default mode to max resolution */
>> - ov13b->cur_mode = &supported_modes[0];
>> -
>> ret = ov13b10_init_controls(ov13b);
>> if (ret)
>> goto error_power_off;
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-10 4:06 ` Hao Yao
@ 2025-03-10 7:14 ` Sakari Ailus
2025-03-11 6:42 ` Hao Yao
0 siblings, 1 reply; 7+ messages in thread
From: Sakari Ailus @ 2025-03-10 7:14 UTC (permalink / raw)
To: Hao Yao; +Cc: Arec Kao, Mauro Carvalho Chehab, linux-media, Bingbu Cao
Hi Hao,
On Mon, Mar 10, 2025 at 12:06:04PM +0800, Hao Yao wrote:
> > > @@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
> > > if (ret)
> > > return ret;
> > > - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
> > > + dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
> > > + if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
> > > dev_err(dev, "number of CSI2 data lanes %d is not supported",
> > > - bus_cfg.bus.mipi_csi2.num_data_lanes);
> > > + dlane);
> > > ret = -EINVAL;
> > > goto out_err;
> > > }
> > > + ov13b->data_lanes = dlane;
> > > + ov13b->supported_modes = supported_4_lanes_modes;
> > > + ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
> > > + if (dlane == OV13B10_2_DATA_LANES) {
> > > + ov13b->supported_modes = supported_2_lanes_modes;
> > > + ov13b->supported_modes_num =
> > > + ARRAY_SIZE(supported_2_lanes_modes);
> >
> > How about using switch() here?
>
> How about:
> ov13b->data_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
> switch (ov13b->data_lanes) {
> case OV13B10_4_DATA_LANES:
> ov13b->supported_modes = supported_4_lanes_modes;
> ov13b->supported_modes_num =
> ARRAY_SIZE(supported_4_lanes_modes);
> break;
>
> case OV13B10_2_DATA_LANES:
> ov13b->supported_modes = supported_2_lanes_modes;
> ov13b->supported_modes_num =
> ARRAY_SIZE(supported_2_lanes_modes);
> break;
>
> default:
> dev_err(dev, "number of CSI2 data lanes %d is not supported",
> ov13b->data_lanes);
> ret = -EINVAL;
> goto out_err;
> }
Looks good to me. I'd do the assignment to ov13b->data_lanes after checking
the value though.
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-10 7:14 ` Sakari Ailus
@ 2025-03-11 6:42 ` Hao Yao
2025-03-11 8:17 ` Sakari Ailus
0 siblings, 1 reply; 7+ messages in thread
From: Hao Yao @ 2025-03-11 6:42 UTC (permalink / raw)
To: Sakari Ailus; +Cc: Arec Kao, Mauro Carvalho Chehab, linux-media, Bingbu Cao
Hi Sakari,
On 2025/3/10 15:14, Sakari Ailus wrote:
> Hi Hao,
>
> On Mon, Mar 10, 2025 at 12:06:04PM +0800, Hao Yao wrote:
>>>> @@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
>>>> if (ret)
>>>> return ret;
>>>> - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
>>>> + dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
>>>> + if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
>>>> dev_err(dev, "number of CSI2 data lanes %d is not supported",
>>>> - bus_cfg.bus.mipi_csi2.num_data_lanes);
>>>> + dlane);
>>>> ret = -EINVAL;
>>>> goto out_err;
>>>> }
>>>> + ov13b->data_lanes = dlane;
>>>> + ov13b->supported_modes = supported_4_lanes_modes;
>>>> + ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
>>>> + if (dlane == OV13B10_2_DATA_LANES) {
>>>> + ov13b->supported_modes = supported_2_lanes_modes;
>>>> + ov13b->supported_modes_num =
>>>> + ARRAY_SIZE(supported_2_lanes_modes);
>>>
>>> How about using switch() here?
>>
>> How about:
>> ov13b->data_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
>> switch (ov13b->data_lanes) {
>> case OV13B10_4_DATA_LANES:
>> ov13b->supported_modes = supported_4_lanes_modes;
>> ov13b->supported_modes_num =
>> ARRAY_SIZE(supported_4_lanes_modes);
>> break;
>>
>> case OV13B10_2_DATA_LANES:
>> ov13b->supported_modes = supported_2_lanes_modes;
>> ov13b->supported_modes_num =
>> ARRAY_SIZE(supported_2_lanes_modes);
>> break;
>>
>> default:
>> dev_err(dev, "number of CSI2 data lanes %d is not supported",
>> ov13b->data_lanes);
>> ret = -EINVAL;
>> goto out_err;
>> }
>
> Looks good to me. I'd do the assignment to ov13b->data_lanes after checking
> the value though.
>
Thank you, I will prepare v2 later.
BTW, do you have any suggestions on patch 1/2 ?
Best Regards,
Hao Yao
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode
2025-03-11 6:42 ` Hao Yao
@ 2025-03-11 8:17 ` Sakari Ailus
0 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2025-03-11 8:17 UTC (permalink / raw)
To: Hao Yao; +Cc: Arec Kao, Mauro Carvalho Chehab, linux-media, Bingbu Cao
Hi Hao,
On Tue, Mar 11, 2025 at 02:42:57PM +0800, Hao Yao wrote:
> Hi Sakari,
>
> On 2025/3/10 15:14, Sakari Ailus wrote:
> > Hi Hao,
> >
> > On Mon, Mar 10, 2025 at 12:06:04PM +0800, Hao Yao wrote:
> > > > > @@ -1459,12 +1539,25 @@ static int ov13b10_check_hwcfg(struct device *dev)
> > > > > if (ret)
> > > > > return ret;
> > > > > - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
> > > > > + dlane = bus_cfg.bus.mipi_csi2.num_data_lanes;
> > > > > + if (dlane != OV13B10_4_DATA_LANES && dlane != OV13B10_2_DATA_LANES) {
> > > > > dev_err(dev, "number of CSI2 data lanes %d is not supported",
> > > > > - bus_cfg.bus.mipi_csi2.num_data_lanes);
> > > > > + dlane);
> > > > > ret = -EINVAL;
> > > > > goto out_err;
> > > > > }
> > > > > + ov13b->data_lanes = dlane;
> > > > > + ov13b->supported_modes = supported_4_lanes_modes;
> > > > > + ov13b->supported_modes_num = ARRAY_SIZE(supported_4_lanes_modes);
> > > > > + if (dlane == OV13B10_2_DATA_LANES) {
> > > > > + ov13b->supported_modes = supported_2_lanes_modes;
> > > > > + ov13b->supported_modes_num =
> > > > > + ARRAY_SIZE(supported_2_lanes_modes);
> > > >
> > > > How about using switch() here?
> > >
> > > How about:
> > > ov13b->data_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
> > > switch (ov13b->data_lanes) {
> > > case OV13B10_4_DATA_LANES:
> > > ov13b->supported_modes = supported_4_lanes_modes;
> > > ov13b->supported_modes_num =
> > > ARRAY_SIZE(supported_4_lanes_modes);
> > > break;
> > >
> > > case OV13B10_2_DATA_LANES:
> > > ov13b->supported_modes = supported_2_lanes_modes;
> > > ov13b->supported_modes_num =
> > > ARRAY_SIZE(supported_2_lanes_modes);
> > > break;
> > >
> > > default:
> > > dev_err(dev, "number of CSI2 data lanes %d is not supported",
> > > ov13b->data_lanes);
> > > ret = -EINVAL;
> > > goto out_err;
> > > }
> >
> > Looks good to me. I'd do the assignment to ov13b->data_lanes after checking
> > the value though.
> >
>
> Thank you, I will prepare v2 later.
> BTW, do you have any suggestions on patch 1/2 ?
That looks good to me.
--
Sakari Ailus
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-03-11 8:17 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-07 9:31 [PATCH 1/2] media: i2c: ov13b10: Fix h_blank calculation Hao Yao
2025-03-07 9:31 ` [PATCH 2/2] media: i2c: ov13b10: Support 2 lane mode Hao Yao
2025-03-07 9:43 ` Sakari Ailus
2025-03-10 4:06 ` Hao Yao
2025-03-10 7:14 ` Sakari Ailus
2025-03-11 6:42 ` Hao Yao
2025-03-11 8:17 ` Sakari Ailus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox