* [PATCH 01/23] media: i2c: imx258: Remove unused defines
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 02/23] media: i2c: imx258: Make image geometry meet sensor requirements git
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
The IMX258_FLL_* defines are unused. Remove them.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index a577afb530b7..2dbafd21dd70 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -29,12 +29,6 @@
#define IMX258_VTS_30FPS_VGA 0x034c
#define IMX258_VTS_MAX 0xffff
-/*Frame Length Line*/
-#define IMX258_FLL_MIN 0x08a6
-#define IMX258_FLL_MAX 0xffff
-#define IMX258_FLL_STEP 1
-#define IMX258_FLL_DEFAULT 0x0c98
-
/* HBLANK control - read only */
#define IMX258_PPL_DEFAULT 5352
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 02/23] media: i2c: imx258: Make image geometry meet sensor requirements
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
2024-03-27 22:20 ` [PATCH 01/23] media: i2c: imx258: Remove unused defines git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 03/23] media: i2c: imx258: Disable digital cropping on binned modes git
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
The output image is defined as being 4208x3118 pixels in size.
Y_ADD_STA register was set to 0, and Y_ADD_END to 3118, giving
3119 lines total.
The datasheet lists a requirement for Y_ADD_STA to be a multiple
of a power of 2 depending on binning/scaling mode (2 for full pixel,
4 for x2-bin/scale, 8 for (x2-bin)+(x2-subsample) or x4-bin, or 16
for (x4-bin)+(x2-subsample)).
(Y_ADD_END – Y_ADD_STA + 1) also has to be a similar power of 2.
The current configuration for the full res modes breaks that second
requirement, and we can't increase Y_ADD_STA to 1 to retain exactly
the same field of view as that then breaks the first requirement.
For the binned modes, they are worse off as 3118 is not a multiple of
4.
Increase the main mode to 4208x3120 so that it is the same FOV as the
binned modes, with Y_ADD_STA at 0.
Fix Y_ADD_STA and Y_ADD_END for the binned modes so that they meet the
sensor requirements.
This does change the Bayer order as the default configuration is for
H&V flips to be enabled, so readout is from Y_STA_END to Y_ADD_STA,
and this patch has changed Y_STA_END.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 2dbafd21dd70..4a7048d834c6 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -111,7 +111,7 @@ struct imx258_mode {
struct imx258_reg_list reg_list;
};
-/* 4208x3118 needs 1267Mbps/lane, 4 lanes */
+/* 4208x3120 needs 1267Mbps/lane, 4 lanes */
static const struct imx258_reg mipi_data_rate_1267mbps[] = {
{ 0x0301, 0x05 },
{ 0x0303, 0x02 },
@@ -148,7 +148,7 @@ static const struct imx258_reg mipi_data_rate_640mbps[] = {
{ 0x0823, 0x00 },
};
-static const struct imx258_reg mode_4208x3118_regs[] = {
+static const struct imx258_reg mode_4208x3120_regs[] = {
{ 0x0136, 0x13 },
{ 0x0137, 0x33 },
{ 0x3051, 0x00 },
@@ -210,7 +210,7 @@ static const struct imx258_reg mode_4208x3118_regs[] = {
{ 0x0348, 0x10 },
{ 0x0349, 0x6F },
{ 0x034A, 0x0C },
- { 0x034B, 0x2E },
+ { 0x034B, 0x2F },
{ 0x0381, 0x01 },
{ 0x0383, 0x01 },
{ 0x0385, 0x01 },
@@ -329,7 +329,7 @@ static const struct imx258_reg mode_2104_1560_regs[] = {
{ 0x0348, 0x10 },
{ 0x0349, 0x6F },
{ 0x034A, 0x0C },
- { 0x034B, 0x2E },
+ { 0x034B, 0x2F },
{ 0x0381, 0x01 },
{ 0x0383, 0x01 },
{ 0x0385, 0x01 },
@@ -448,7 +448,7 @@ static const struct imx258_reg mode_1048_780_regs[] = {
{ 0x0348, 0x10 },
{ 0x0349, 0x6F },
{ 0x034A, 0x0C },
- { 0x034B, 0x2E },
+ { 0x034B, 0x2F },
{ 0x0381, 0x01 },
{ 0x0383, 0x01 },
{ 0x0385, 0x01 },
@@ -562,12 +562,12 @@ static const struct imx258_link_freq_config link_freq_configs[] = {
static const struct imx258_mode supported_modes[] = {
{
.width = 4208,
- .height = 3118,
+ .height = 3120,
.vts_def = IMX258_VTS_30FPS,
.vts_min = IMX258_VTS_30FPS,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mode_4208x3118_regs),
- .regs = mode_4208x3118_regs,
+ .num_of_regs = ARRAY_SIZE(mode_4208x3120_regs),
+ .regs = mode_4208x3120_regs,
},
.link_freq_index = IMX258_LINK_FREQ_1267MBPS,
},
@@ -707,7 +707,7 @@ static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
/* Initialize try_fmt */
try_fmt->width = supported_modes[0].width;
try_fmt->height = supported_modes[0].height;
- try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
try_fmt->field = V4L2_FIELD_NONE;
return 0;
@@ -819,7 +819,7 @@ static int imx258_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index > 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
}
@@ -831,7 +831,7 @@ static int imx258_enum_frame_size(struct v4l2_subdev *sd,
if (fse->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+ if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
return -EINVAL;
fse->min_width = supported_modes[fse->index].width;
@@ -847,7 +847,7 @@ static void imx258_update_pad_format(const struct imx258_mode *mode,
{
fmt->format.width = mode->width;
fmt->format.height = mode->height;
- fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
fmt->format.field = V4L2_FIELD_NONE;
}
@@ -894,7 +894,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
mutex_lock(&imx258->mutex);
/* Only one raw bayer(GBRG) order is supported */
- fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
mode = v4l2_find_nearest_size(supported_modes,
ARRAY_SIZE(supported_modes), width, height,
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 03/23] media: i2c: imx258: Disable digital cropping on binned modes
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
2024-03-27 22:20 ` [PATCH 01/23] media: i2c: imx258: Remove unused defines git
2024-03-27 22:20 ` [PATCH 02/23] media: i2c: imx258: Make image geometry meet sensor requirements git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 04/23] media: i2c: imx258: Remove redundant I2C writes git
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
The binned modes set DIG_CROP_X_OFFSET and DIG_CROP_IMAGE_WIDTH
to less than the full image, even though the image being captured
is meant to be a scaled version of the full array size.
Reduce X_OFFSET to 0, and increase IMAGE_WIDTH to the full array.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx258.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 4a7048d834c6..0ae4371940ca 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -340,11 +340,11 @@ static const struct imx258_reg mode_2104_1560_regs[] = {
{ 0x0404, 0x00 },
{ 0x0405, 0x20 },
{ 0x0408, 0x00 },
- { 0x0409, 0x02 },
+ { 0x0409, 0x00 },
{ 0x040A, 0x00 },
{ 0x040B, 0x00 },
{ 0x040C, 0x10 },
- { 0x040D, 0x6A },
+ { 0x040D, 0x70 },
{ 0x040E, 0x06 },
{ 0x040F, 0x18 },
{ 0x3038, 0x00 },
@@ -459,11 +459,11 @@ static const struct imx258_reg mode_1048_780_regs[] = {
{ 0x0404, 0x00 },
{ 0x0405, 0x40 },
{ 0x0408, 0x00 },
- { 0x0409, 0x06 },
+ { 0x0409, 0x00 },
{ 0x040A, 0x00 },
{ 0x040B, 0x00 },
{ 0x040C, 0x10 },
- { 0x040D, 0x64 },
+ { 0x040D, 0x70 },
{ 0x040E, 0x03 },
{ 0x040F, 0x0C },
{ 0x3038, 0x00 },
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 04/23] media: i2c: imx258: Remove redundant I2C writes.
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (2 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 03/23] media: i2c: imx258: Disable digital cropping on binned modes git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 05/23] media: i2c: imx258: Add regulator control git
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Registers 0x0202 and 0x0203 are written via the control handler
for V4L2_CID_EXPOSURE, so are not needed from the mode lists.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 0ae4371940ca..df7ed4716762 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -237,8 +237,6 @@ static const struct imx258_reg mode_4208x3120_regs[] = {
{ 0x034E, 0x0C },
{ 0x034F, 0x30 },
{ 0x0350, 0x01 },
- { 0x0202, 0x0C },
- { 0x0203, 0x46 },
{ 0x0204, 0x00 },
{ 0x0205, 0x00 },
{ 0x020E, 0x01 },
@@ -356,8 +354,6 @@ static const struct imx258_reg mode_2104_1560_regs[] = {
{ 0x034E, 0x06 },
{ 0x034F, 0x18 },
{ 0x0350, 0x01 },
- { 0x0202, 0x06 },
- { 0x0203, 0x2E },
{ 0x0204, 0x00 },
{ 0x0205, 0x00 },
{ 0x020E, 0x01 },
@@ -475,8 +471,6 @@ static const struct imx258_reg mode_1048_780_regs[] = {
{ 0x034E, 0x03 },
{ 0x034F, 0x0C },
{ 0x0350, 0x01 },
- { 0x0202, 0x03 },
- { 0x0203, 0x42 },
{ 0x0204, 0x00 },
{ 0x0205, 0x00 },
{ 0x020E, 0x01 },
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 05/23] media: i2c: imx258: Add regulator control
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (3 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 04/23] media: i2c: imx258: Remove redundant I2C writes git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 06/23] media: i2c: imx258: Make V4L2_CID_VBLANK configurable git
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x, Luigi311
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
The device tree bindings define the relevant regulators for the
sensor, so update the driver to request the regulators and control
them at the appropriate times.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Luigi311 <git@luigi311.com>
---
drivers/media/i2c/imx258.c | 42 +++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index df7ed4716762..495eaada2945 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -7,6 +7,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@@ -507,6 +508,16 @@ static const char * const imx258_test_pattern_menu[] = {
"Pseudorandom Sequence (PN9)",
};
+/* regulator supplies */
+static const char * const imx258_supply_name[] = {
+ /* Supplies can be enabled in any order */
+ "vana", /* Analog (2.8V) supply */
+ "vdig", /* Digital Core (1.2V) supply */
+ "vif", /* IF (1.8V) supply */
+};
+
+#define IMX258_NUM_SUPPLIES ARRAY_SIZE(imx258_supply_name)
+
/* Configurations for supported link frequencies */
#define IMX258_LINK_FREQ_634MHZ 633600000ULL
#define IMX258_LINK_FREQ_320MHZ 320000000ULL
@@ -611,6 +622,7 @@ struct imx258 {
struct mutex mutex;
struct clk *clk;
+ struct regulator_bulk_data supplies[IMX258_NUM_SUPPLIES];
};
static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd)
@@ -995,9 +1007,19 @@ static int imx258_power_on(struct device *dev)
struct imx258 *imx258 = to_imx258(sd);
int ret;
+ ret = regulator_bulk_enable(IMX258_NUM_SUPPLIES,
+ imx258->supplies);
+ if (ret) {
+ dev_err(dev, "%s: failed to enable regulators\n",
+ __func__);
+ return ret;
+ }
+
ret = clk_prepare_enable(imx258->clk);
- if (ret)
+ if (ret) {
dev_err(dev, "failed to enable clock\n");
+ regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
+ }
return ret;
}
@@ -1008,6 +1030,7 @@ static int imx258_power_off(struct device *dev)
struct imx258 *imx258 = to_imx258(sd);
clk_disable_unprepare(imx258->clk);
+ regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
return 0;
}
@@ -1220,6 +1243,18 @@ static void imx258_free_controls(struct imx258 *imx258)
mutex_destroy(&imx258->mutex);
}
+static int imx258_get_regulators(struct imx258 *imx258,
+ struct i2c_client *client)
+{
+ unsigned int i;
+
+ for (i = 0; i < IMX258_NUM_SUPPLIES; i++)
+ imx258->supplies[i].supply = imx258_supply_name[i];
+
+ return devm_regulator_bulk_get(&client->dev,
+ IMX258_NUM_SUPPLIES, imx258->supplies);
+}
+
static int imx258_probe(struct i2c_client *client)
{
struct imx258 *imx258;
@@ -1230,6 +1265,11 @@ static int imx258_probe(struct i2c_client *client)
if (!imx258)
return -ENOMEM;
+ ret = imx258_get_regulators(imx258, client);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to get regulators\n");
+
imx258->clk = devm_clk_get_optional(&client->dev, NULL);
if (IS_ERR(imx258->clk))
return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 06/23] media: i2c: imx258: Make V4L2_CID_VBLANK configurable.
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (4 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 05/23] media: i2c: imx258: Add regulator control git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 07/23] media: i2c: imx258: Split out common registers from the mode based ones git
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
The values and ranges of V4L2_CID_VBLANK are all computed,
so there is no reason for it to be a read only control.
Remove the register values from the mode lists, add the
handler, and remove the read only flag.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx258.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 495eaada2945..321b504c6a48 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -30,6 +30,8 @@
#define IMX258_VTS_30FPS_VGA 0x034c
#define IMX258_VTS_MAX 0xffff
+#define IMX258_REG_VTS 0x0340
+
/* HBLANK control - read only */
#define IMX258_PPL_DEFAULT 5352
@@ -202,8 +204,6 @@ static const struct imx258_reg mode_4208x3120_regs[] = {
{ 0x0114, 0x03 },
{ 0x0342, 0x14 },
{ 0x0343, 0xE8 },
- { 0x0340, 0x0C },
- { 0x0341, 0x50 },
{ 0x0344, 0x00 },
{ 0x0345, 0x00 },
{ 0x0346, 0x00 },
@@ -319,8 +319,6 @@ static const struct imx258_reg mode_2104_1560_regs[] = {
{ 0x0114, 0x03 },
{ 0x0342, 0x14 },
{ 0x0343, 0xE8 },
- { 0x0340, 0x06 },
- { 0x0341, 0x38 },
{ 0x0344, 0x00 },
{ 0x0345, 0x00 },
{ 0x0346, 0x00 },
@@ -436,8 +434,6 @@ static const struct imx258_reg mode_1048_780_regs[] = {
{ 0x0114, 0x03 },
{ 0x0342, 0x14 },
{ 0x0343, 0xE8 },
- { 0x0340, 0x03 },
- { 0x0341, 0x4C },
{ 0x0344, 0x00 },
{ 0x0345, 0x00 },
{ 0x0346, 0x00 },
@@ -800,6 +796,11 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
BIT(IMX258_HDR_RATIO_MAX));
}
break;
+ case V4L2_CID_VBLANK:
+ ret = imx258_write_reg(imx258, IMX258_REG_VTS,
+ IMX258_REG_VALUE_16BIT,
+ imx258->cur_mode->height + ctrl->val);
+ break;
default:
dev_info(&client->dev,
"ctrl(id:0x%x,val:0x%x) is not handled\n",
@@ -1174,9 +1175,6 @@ static int imx258_init_controls(struct imx258 *imx258)
IMX258_VTS_MAX - imx258->cur_mode->height, 1,
vblank_def);
- if (imx258->vblank)
- imx258->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
imx258->hblank = v4l2_ctrl_new_std(
ctrl_hdlr, &imx258_ctrl_ops, V4L2_CID_HBLANK,
IMX258_PPL_DEFAULT - imx258->cur_mode->width,
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 07/23] media: i2c: imx258: Split out common registers from the mode based ones
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (5 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 06/23] media: i2c: imx258: Make V4L2_CID_VBLANK configurable git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 08/23] media: i2c: imx258: Add support for 24MHz clock git
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Out of all the registers that are defined for each mode, only around
10 differ between the modes.
Split the table into common and mode specific ones.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 236 ++++---------------------------------
1 file changed, 21 insertions(+), 215 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 321b504c6a48..351add1bc5d5 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -151,7 +151,7 @@ static const struct imx258_reg mipi_data_rate_640mbps[] = {
{ 0x0823, 0x00 },
};
-static const struct imx258_reg mode_4208x3120_regs[] = {
+static const struct imx258_reg mode_common_regs[] = {
{ 0x0136, 0x13 },
{ 0x0137, 0x33 },
{ 0x3051, 0x00 },
@@ -216,27 +216,17 @@ static const struct imx258_reg mode_4208x3120_regs[] = {
{ 0x0383, 0x01 },
{ 0x0385, 0x01 },
{ 0x0387, 0x01 },
- { 0x0900, 0x00 },
- { 0x0901, 0x11 },
- { 0x0401, 0x00 },
{ 0x0404, 0x00 },
- { 0x0405, 0x10 },
{ 0x0408, 0x00 },
{ 0x0409, 0x00 },
{ 0x040A, 0x00 },
{ 0x040B, 0x00 },
{ 0x040C, 0x10 },
{ 0x040D, 0x70 },
- { 0x040E, 0x0C },
- { 0x040F, 0x30 },
{ 0x3038, 0x00 },
{ 0x303A, 0x00 },
{ 0x303B, 0x10 },
{ 0x300D, 0x00 },
- { 0x034C, 0x10 },
- { 0x034D, 0x70 },
- { 0x034E, 0x0C },
- { 0x034F, 0x30 },
{ 0x0350, 0x01 },
{ 0x0204, 0x00 },
{ 0x0205, 0x00 },
@@ -266,234 +256,43 @@ static const struct imx258_reg mode_4208x3120_regs[] = {
{ 0x0220, 0x00 },
};
+static const struct imx258_reg mode_4208x3120_regs[] = {
+ { 0x0900, 0x00 },
+ { 0x0901, 0x11 },
+ { 0x0401, 0x00 },
+ { 0x0405, 0x10 },
+ { 0x040E, 0x0C },
+ { 0x040F, 0x30 },
+ { 0x034C, 0x10 },
+ { 0x034D, 0x70 },
+ { 0x034E, 0x0C },
+ { 0x034F, 0x30 },
+};
+
static const struct imx258_reg mode_2104_1560_regs[] = {
- { 0x0136, 0x13 },
- { 0x0137, 0x33 },
- { 0x3051, 0x00 },
- { 0x3052, 0x00 },
- { 0x4E21, 0x14 },
- { 0x6B11, 0xCF },
- { 0x7FF0, 0x08 },
- { 0x7FF1, 0x0F },
- { 0x7FF2, 0x08 },
- { 0x7FF3, 0x1B },
- { 0x7FF4, 0x23 },
- { 0x7FF5, 0x60 },
- { 0x7FF6, 0x00 },
- { 0x7FF7, 0x01 },
- { 0x7FF8, 0x00 },
- { 0x7FF9, 0x78 },
- { 0x7FFA, 0x00 },
- { 0x7FFB, 0x00 },
- { 0x7FFC, 0x00 },
- { 0x7FFD, 0x00 },
- { 0x7FFE, 0x00 },
- { 0x7FFF, 0x03 },
- { 0x7F76, 0x03 },
- { 0x7F77, 0xFE },
- { 0x7FA8, 0x03 },
- { 0x7FA9, 0xFE },
- { 0x7B24, 0x81 },
- { 0x7B25, 0x00 },
- { 0x6564, 0x07 },
- { 0x6B0D, 0x41 },
- { 0x653D, 0x04 },
- { 0x6B05, 0x8C },
- { 0x6B06, 0xF9 },
- { 0x6B08, 0x65 },
- { 0x6B09, 0xFC },
- { 0x6B0A, 0xCF },
- { 0x6B0B, 0xD2 },
- { 0x6700, 0x0E },
- { 0x6707, 0x0E },
- { 0x9104, 0x00 },
- { 0x4648, 0x7F },
- { 0x7420, 0x00 },
- { 0x7421, 0x1C },
- { 0x7422, 0x00 },
- { 0x7423, 0xD7 },
- { 0x5F04, 0x00 },
- { 0x5F05, 0xED },
- { 0x0112, 0x0A },
- { 0x0113, 0x0A },
- { 0x0114, 0x03 },
- { 0x0342, 0x14 },
- { 0x0343, 0xE8 },
- { 0x0344, 0x00 },
- { 0x0345, 0x00 },
- { 0x0346, 0x00 },
- { 0x0347, 0x00 },
- { 0x0348, 0x10 },
- { 0x0349, 0x6F },
- { 0x034A, 0x0C },
- { 0x034B, 0x2F },
- { 0x0381, 0x01 },
- { 0x0383, 0x01 },
- { 0x0385, 0x01 },
- { 0x0387, 0x01 },
{ 0x0900, 0x01 },
{ 0x0901, 0x12 },
{ 0x0401, 0x01 },
- { 0x0404, 0x00 },
{ 0x0405, 0x20 },
- { 0x0408, 0x00 },
- { 0x0409, 0x00 },
- { 0x040A, 0x00 },
- { 0x040B, 0x00 },
- { 0x040C, 0x10 },
- { 0x040D, 0x70 },
{ 0x040E, 0x06 },
{ 0x040F, 0x18 },
- { 0x3038, 0x00 },
- { 0x303A, 0x00 },
- { 0x303B, 0x10 },
- { 0x300D, 0x00 },
{ 0x034C, 0x08 },
{ 0x034D, 0x38 },
{ 0x034E, 0x06 },
{ 0x034F, 0x18 },
- { 0x0350, 0x01 },
- { 0x0204, 0x00 },
- { 0x0205, 0x00 },
- { 0x020E, 0x01 },
- { 0x020F, 0x00 },
- { 0x0210, 0x01 },
- { 0x0211, 0x00 },
- { 0x0212, 0x01 },
- { 0x0213, 0x00 },
- { 0x0214, 0x01 },
- { 0x0215, 0x00 },
- { 0x7BCD, 0x01 },
- { 0x94DC, 0x20 },
- { 0x94DD, 0x20 },
- { 0x94DE, 0x20 },
- { 0x95DC, 0x20 },
- { 0x95DD, 0x20 },
- { 0x95DE, 0x20 },
- { 0x7FB0, 0x00 },
- { 0x9010, 0x3E },
- { 0x9419, 0x50 },
- { 0x941B, 0x50 },
- { 0x9519, 0x50 },
- { 0x951B, 0x50 },
- { 0x3030, 0x00 },
- { 0x3032, 0x00 },
- { 0x0220, 0x00 },
};
static const struct imx258_reg mode_1048_780_regs[] = {
- { 0x0136, 0x13 },
- { 0x0137, 0x33 },
- { 0x3051, 0x00 },
- { 0x3052, 0x00 },
- { 0x4E21, 0x14 },
- { 0x6B11, 0xCF },
- { 0x7FF0, 0x08 },
- { 0x7FF1, 0x0F },
- { 0x7FF2, 0x08 },
- { 0x7FF3, 0x1B },
- { 0x7FF4, 0x23 },
- { 0x7FF5, 0x60 },
- { 0x7FF6, 0x00 },
- { 0x7FF7, 0x01 },
- { 0x7FF8, 0x00 },
- { 0x7FF9, 0x78 },
- { 0x7FFA, 0x00 },
- { 0x7FFB, 0x00 },
- { 0x7FFC, 0x00 },
- { 0x7FFD, 0x00 },
- { 0x7FFE, 0x00 },
- { 0x7FFF, 0x03 },
- { 0x7F76, 0x03 },
- { 0x7F77, 0xFE },
- { 0x7FA8, 0x03 },
- { 0x7FA9, 0xFE },
- { 0x7B24, 0x81 },
- { 0x7B25, 0x00 },
- { 0x6564, 0x07 },
- { 0x6B0D, 0x41 },
- { 0x653D, 0x04 },
- { 0x6B05, 0x8C },
- { 0x6B06, 0xF9 },
- { 0x6B08, 0x65 },
- { 0x6B09, 0xFC },
- { 0x6B0A, 0xCF },
- { 0x6B0B, 0xD2 },
- { 0x6700, 0x0E },
- { 0x6707, 0x0E },
- { 0x9104, 0x00 },
- { 0x4648, 0x7F },
- { 0x7420, 0x00 },
- { 0x7421, 0x1C },
- { 0x7422, 0x00 },
- { 0x7423, 0xD7 },
- { 0x5F04, 0x00 },
- { 0x5F05, 0xED },
- { 0x0112, 0x0A },
- { 0x0113, 0x0A },
- { 0x0114, 0x03 },
- { 0x0342, 0x14 },
- { 0x0343, 0xE8 },
- { 0x0344, 0x00 },
- { 0x0345, 0x00 },
- { 0x0346, 0x00 },
- { 0x0347, 0x00 },
- { 0x0348, 0x10 },
- { 0x0349, 0x6F },
- { 0x034A, 0x0C },
- { 0x034B, 0x2F },
- { 0x0381, 0x01 },
- { 0x0383, 0x01 },
- { 0x0385, 0x01 },
- { 0x0387, 0x01 },
{ 0x0900, 0x01 },
{ 0x0901, 0x14 },
{ 0x0401, 0x01 },
- { 0x0404, 0x00 },
{ 0x0405, 0x40 },
- { 0x0408, 0x00 },
- { 0x0409, 0x00 },
- { 0x040A, 0x00 },
- { 0x040B, 0x00 },
- { 0x040C, 0x10 },
- { 0x040D, 0x70 },
{ 0x040E, 0x03 },
{ 0x040F, 0x0C },
- { 0x3038, 0x00 },
- { 0x303A, 0x00 },
- { 0x303B, 0x10 },
- { 0x300D, 0x00 },
{ 0x034C, 0x04 },
{ 0x034D, 0x18 },
{ 0x034E, 0x03 },
{ 0x034F, 0x0C },
- { 0x0350, 0x01 },
- { 0x0204, 0x00 },
- { 0x0205, 0x00 },
- { 0x020E, 0x01 },
- { 0x020F, 0x00 },
- { 0x0210, 0x01 },
- { 0x0211, 0x00 },
- { 0x0212, 0x01 },
- { 0x0213, 0x00 },
- { 0x0214, 0x01 },
- { 0x0215, 0x00 },
- { 0x7BCD, 0x00 },
- { 0x94DC, 0x20 },
- { 0x94DD, 0x20 },
- { 0x94DE, 0x20 },
- { 0x95DC, 0x20 },
- { 0x95DD, 0x20 },
- { 0x95DE, 0x20 },
- { 0x7FB0, 0x00 },
- { 0x9010, 0x3E },
- { 0x9419, 0x50 },
- { 0x941B, 0x50 },
- { 0x9519, 0x50 },
- { 0x951B, 0x50 },
- { 0x3030, 0x00 },
- { 0x3032, 0x00 },
- { 0x0220, 0x00 },
};
static const char * const imx258_test_pattern_menu[] = {
@@ -955,6 +754,13 @@ static int imx258_start_streaming(struct imx258 *imx258)
return ret;
}
+ ret = imx258_write_regs(imx258, mode_common_regs,
+ ARRAY_SIZE(mode_common_regs));
+ if (ret) {
+ dev_err(&client->dev, "%s failed to set common regs\n", __func__);
+ return ret;
+ }
+
/* Apply default values of current mode */
reg_list = &imx258->cur_mode->reg_list;
ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 08/23] media: i2c: imx258: Add support for 24MHz clock
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (6 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 07/23] media: i2c: imx258: Split out common registers from the mode based ones git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 09/23] media: i2c: imx258: Add support for running on 2 CSI data lanes git
2024-03-27 22:20 ` [PATCH 10/23] media: i2c: imx258: Follow normal V4L2 behaviours for clipping exposure git
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x, Luigi311
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
There's no reason why only a clock of 19.2MHz is supported.
Indeed this isn't even a frequency listed in the datasheet.
Add support for 24MHz as well.
The PLL settings result in slightly different link frequencies,
so parameterise those.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Luigi311 <git@luigi311.com>
---
drivers/media/i2c/imx258.c | 133 +++++++++++++++++++++++++++++--------
1 file changed, 107 insertions(+), 26 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 351add1bc5d5..6ee7de079454 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -76,9 +76,6 @@
#define REG_CONFIG_MIRROR_FLIP 0x03
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
-/* Input clock frequency in Hz */
-#define IMX258_INPUT_CLOCK_FREQ 19200000
-
struct imx258_reg {
u16 address;
u8 val;
@@ -115,7 +112,9 @@ struct imx258_mode {
};
/* 4208x3120 needs 1267Mbps/lane, 4 lanes */
-static const struct imx258_reg mipi_data_rate_1267mbps[] = {
+static const struct imx258_reg mipi_1267mbps_19_2mhz[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
{ 0x0301, 0x05 },
{ 0x0303, 0x02 },
{ 0x0305, 0x03 },
@@ -133,7 +132,29 @@ static const struct imx258_reg mipi_data_rate_1267mbps[] = {
{ 0x0823, 0xCC },
};
-static const struct imx258_reg mipi_data_rate_640mbps[] = {
+static const struct imx258_reg mipi_1272mbps_24mhz[] = {
+ { 0x0136, 0x18 },
+ { 0x0137, 0x00 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0xD4 },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x13 },
+ { 0x0821, 0x4C },
+ { 0x0822, 0xCC },
+ { 0x0823, 0xCC },
+};
+
+static const struct imx258_reg mipi_640mbps_19_2mhz[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
{ 0x0301, 0x05 },
{ 0x0303, 0x02 },
{ 0x0305, 0x03 },
@@ -151,9 +172,27 @@ static const struct imx258_reg mipi_data_rate_640mbps[] = {
{ 0x0823, 0x00 },
};
+static const struct imx258_reg mipi_642mbps_24mhz[] = {
+ { 0x0136, 0x18 },
+ { 0x0137, 0x00 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x6B },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+ { 0x0820, 0x0A },
+ { 0x0821, 0x00 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+};
+
static const struct imx258_reg mode_common_regs[] = {
- { 0x0136, 0x13 },
- { 0x0137, 0x33 },
{ 0x3051, 0x00 },
{ 0x3052, 0x00 },
{ 0x4E21, 0x14 },
@@ -313,10 +352,6 @@ static const char * const imx258_supply_name[] = {
#define IMX258_NUM_SUPPLIES ARRAY_SIZE(imx258_supply_name)
-/* Configurations for supported link frequencies */
-#define IMX258_LINK_FREQ_634MHZ 633600000ULL
-#define IMX258_LINK_FREQ_320MHZ 320000000ULL
-
enum {
IMX258_LINK_FREQ_1267MBPS,
IMX258_LINK_FREQ_640MBPS,
@@ -335,25 +370,55 @@ static u64 link_freq_to_pixel_rate(u64 f)
}
/* Menu items for LINK_FREQ V4L2 control */
-static const s64 link_freq_menu_items[] = {
+/* Configurations for supported link frequencies */
+#define IMX258_LINK_FREQ_634MHZ 633600000ULL
+#define IMX258_LINK_FREQ_320MHZ 320000000ULL
+
+static const s64 link_freq_menu_items_19_2[] = {
IMX258_LINK_FREQ_634MHZ,
IMX258_LINK_FREQ_320MHZ,
};
+/* Configurations for supported link frequencies */
+#define IMX258_LINK_FREQ_636MHZ 636000000ULL
+#define IMX258_LINK_FREQ_321MHZ 321000000ULL
+
+static const s64 link_freq_menu_items_24[] = {
+ IMX258_LINK_FREQ_636MHZ,
+ IMX258_LINK_FREQ_321MHZ,
+};
+
/* Link frequency configs */
-static const struct imx258_link_freq_config link_freq_configs[] = {
+static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
[IMX258_LINK_FREQ_1267MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_data_rate_1267mbps),
- .regs = mipi_data_rate_1267mbps,
+ .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz),
+ .regs = mipi_1267mbps_19_2mhz,
}
},
[IMX258_LINK_FREQ_640MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_data_rate_640mbps),
- .regs = mipi_data_rate_640mbps,
+ .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz),
+ .regs = mipi_640mbps_19_2mhz,
+ }
+ },
+};
+
+static const struct imx258_link_freq_config link_freq_configs_24[] = {
+ [IMX258_LINK_FREQ_1267MBPS] = {
+ .pixels_per_line = IMX258_PPL_DEFAULT,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz),
+ .regs = mipi_1272mbps_24mhz,
+ }
+ },
+ [IMX258_LINK_FREQ_640MBPS] = {
+ .pixels_per_line = IMX258_PPL_DEFAULT,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz),
+ .regs = mipi_642mbps_24mhz,
}
},
};
@@ -410,6 +475,9 @@ struct imx258 {
/* Current mode */
const struct imx258_mode *cur_mode;
+ const struct imx258_link_freq_config *link_freq_configs;
+ const s64 *link_freq_menu_items;
+
/*
* Mutex for serialized access:
* Protect sensor module set pad format and start/stop streaming safely.
@@ -713,7 +781,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
imx258->cur_mode = mode;
__v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
- link_freq = link_freq_menu_items[mode->link_freq_index];
+ link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
pixel_rate = link_freq_to_pixel_rate(link_freq);
__v4l2_ctrl_s_ctrl_int64(imx258->pixel_rate, pixel_rate);
/* Update limits and set FPS to default */
@@ -727,7 +795,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
vblank_def);
__v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def);
h_blank =
- link_freq_configs[mode->link_freq_index].pixels_per_line
+ imx258->link_freq_configs[mode->link_freq_index].pixels_per_line
- imx258->cur_mode->width;
__v4l2_ctrl_modify_range(imx258->hblank, h_blank,
h_blank, 1, h_blank);
@@ -747,7 +815,7 @@ static int imx258_start_streaming(struct imx258 *imx258)
/* Setup PLL */
link_freq_index = imx258->cur_mode->link_freq_index;
- reg_list = &link_freq_configs[link_freq_index].reg_list;
+ reg_list = &imx258->link_freq_configs[link_freq_index].reg_list;
ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
if (ret) {
dev_err(&client->dev, "%s failed to set plls\n", __func__);
@@ -946,9 +1014,9 @@ static int imx258_init_controls(struct imx258 *imx258)
imx258->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
&imx258_ctrl_ops,
V4L2_CID_LINK_FREQ,
- ARRAY_SIZE(link_freq_menu_items) - 1,
+ ARRAY_SIZE(link_freq_menu_items_19_2) - 1,
0,
- link_freq_menu_items);
+ imx258->link_freq_menu_items);
if (imx258->link_freq)
imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
@@ -964,8 +1032,10 @@ static int imx258_init_controls(struct imx258 *imx258)
if (vflip)
vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
- pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
+ pixel_rate_max =
+ link_freq_to_pixel_rate(imx258->link_freq_menu_items[0]);
+ pixel_rate_min =
+ link_freq_to_pixel_rate(imx258->link_freq_menu_items[1]);
/* By default, PIXEL_RATE is read only */
imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
V4L2_CID_PIXEL_RATE,
@@ -1086,8 +1156,19 @@ static int imx258_probe(struct i2c_client *client)
} else {
val = clk_get_rate(imx258->clk);
}
- if (val != IMX258_INPUT_CLOCK_FREQ) {
- dev_err(&client->dev, "input clock frequency not supported\n");
+
+ switch (val) {
+ case 19200000:
+ imx258->link_freq_configs = link_freq_configs_19_2;
+ imx258->link_freq_menu_items = link_freq_menu_items_19_2;
+ break;
+ case 24000000:
+ imx258->link_freq_configs = link_freq_configs_24;
+ imx258->link_freq_menu_items = link_freq_menu_items_24;
+ break;
+ default:
+ dev_err(&client->dev, "input clock frequency of %u not supported\n",
+ val);
return -EINVAL;
}
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 09/23] media: i2c: imx258: Add support for running on 2 CSI data lanes
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (7 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 08/23] media: i2c: imx258: Add support for 24MHz clock git
@ 2024-03-27 22:20 ` git
2024-03-27 22:20 ` [PATCH 10/23] media: i2c: imx258: Follow normal V4L2 behaviours for clipping exposure git
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x, Luigi311
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Extends the driver to also support 2 data lanes.
Frame rates are obviously more restricted on 2 lanes, but some
hardware simply hasn't wired more up.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Luigi311 <git@luigi311.com>
---
drivers/media/i2c/imx258.c | 214 ++++++++++++++++++++++++++++++++-----
1 file changed, 190 insertions(+), 24 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 6ee7de079454..c65b9aad3b0a 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -86,12 +86,18 @@ struct imx258_reg_list {
const struct imx258_reg *regs;
};
+enum {
+ IMX258_2_LANE_MODE,
+ IMX258_4_LANE_MODE,
+ IMX258_LANE_CONFIGS,
+};
+
/* Link frequency config */
struct imx258_link_freq_config {
u32 pixels_per_line;
/* PLL registers for this link frequency */
- struct imx258_reg_list reg_list;
+ struct imx258_reg_list reg_list[IMX258_LANE_CONFIGS];
};
/* Mode : resolution and related config&values */
@@ -111,8 +117,34 @@ struct imx258_mode {
struct imx258_reg_list reg_list;
};
-/* 4208x3120 needs 1267Mbps/lane, 4 lanes */
-static const struct imx258_reg mipi_1267mbps_19_2mhz[] = {
+/*
+ * 4208x3120 @ 30 fps needs 1267Mbps/lane, 4 lanes.
+ * To avoid further computation of clock settings, adopt the same per
+ * lane data rate when using 2 lanes, thus allowing a maximum of 15fps.
+ */
+static const struct imx258_reg mipi_1267mbps_19_2mhz_2l[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
+ { 0x0301, 0x0A },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x03 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0xC6 },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+
+ { 0x0114, 0x01 },
+ { 0x0820, 0x09 },
+ { 0x0821, 0xa6 },
+ { 0x0822, 0x66 },
+ { 0x0823, 0x66 },
+};
+
+static const struct imx258_reg mipi_1267mbps_19_2mhz_4l[] = {
{ 0x0136, 0x13 },
{ 0x0137, 0x33 },
{ 0x0301, 0x05 },
@@ -126,16 +158,18 @@ static const struct imx258_reg mipi_1267mbps_19_2mhz[] = {
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
+
+ { 0x0114, 0x03 },
{ 0x0820, 0x13 },
{ 0x0821, 0x4C },
{ 0x0822, 0xCC },
{ 0x0823, 0xCC },
};
-static const struct imx258_reg mipi_1272mbps_24mhz[] = {
+static const struct imx258_reg mipi_1272mbps_24mhz_2l[] = {
{ 0x0136, 0x18 },
{ 0x0137, 0x00 },
- { 0x0301, 0x05 },
+ { 0x0301, 0x0a },
{ 0x0303, 0x02 },
{ 0x0305, 0x04 },
{ 0x0306, 0x00 },
@@ -146,13 +180,59 @@ static const struct imx258_reg mipi_1272mbps_24mhz[] = {
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
+
+ { 0x0114, 0x01 },
{ 0x0820, 0x13 },
{ 0x0821, 0x4C },
{ 0x0822, 0xCC },
{ 0x0823, 0xCC },
};
-static const struct imx258_reg mipi_640mbps_19_2mhz[] = {
+static const struct imx258_reg mipi_1272mbps_24mhz_4l[] = {
+ { 0x0136, 0x18 },
+ { 0x0137, 0x00 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0xD4 },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+
+ { 0x0114, 0x03 },
+ { 0x0820, 0x13 },
+ { 0x0821, 0xE0 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+};
+
+static const struct imx258_reg mipi_640mbps_19_2mhz_2l[] = {
+ { 0x0136, 0x13 },
+ { 0x0137, 0x33 },
+ { 0x0301, 0x05 },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x03 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x64 },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+
+ { 0x0114, 0x01 },
+ { 0x0820, 0x05 },
+ { 0x0821, 0x00 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+};
+
+static const struct imx258_reg mipi_640mbps_19_2mhz_4l[] = {
{ 0x0136, 0x13 },
{ 0x0137, 0x33 },
{ 0x0301, 0x05 },
@@ -166,13 +246,37 @@ static const struct imx258_reg mipi_640mbps_19_2mhz[] = {
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
+
+ { 0x0114, 0x03 },
+ { 0x0820, 0x0A },
+ { 0x0821, 0x00 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+};
+
+static const struct imx258_reg mipi_642mbps_24mhz_2l[] = {
+ { 0x0136, 0x18 },
+ { 0x0137, 0x00 },
+ { 0x0301, 0x0A },
+ { 0x0303, 0x02 },
+ { 0x0305, 0x04 },
+ { 0x0306, 0x00 },
+ { 0x0307, 0x6B },
+ { 0x0309, 0x0A },
+ { 0x030B, 0x01 },
+ { 0x030D, 0x02 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0xD8 },
+ { 0x0310, 0x00 },
+
+ { 0x0114, 0x01 },
{ 0x0820, 0x0A },
{ 0x0821, 0x00 },
{ 0x0822, 0x00 },
{ 0x0823, 0x00 },
};
-static const struct imx258_reg mipi_642mbps_24mhz[] = {
+static const struct imx258_reg mipi_642mbps_24mhz_4l[] = {
{ 0x0136, 0x18 },
{ 0x0137, 0x00 },
{ 0x0301, 0x05 },
@@ -186,6 +290,8 @@ static const struct imx258_reg mipi_642mbps_24mhz[] = {
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
+
+ { 0x0114, 0x03 },
{ 0x0820, 0x0A },
{ 0x0821, 0x00 },
{ 0x0822, 0x00 },
@@ -240,7 +346,6 @@ static const struct imx258_reg mode_common_regs[] = {
{ 0x5F05, 0xED },
{ 0x0112, 0x0A },
{ 0x0113, 0x0A },
- { 0x0114, 0x03 },
{ 0x0342, 0x14 },
{ 0x0343, 0xE8 },
{ 0x0344, 0x00 },
@@ -359,11 +464,13 @@ enum {
/*
* 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
+ * data rate => double data rate;
+ * number of lanes => (configurable 2 or 4);
+ * bits per pixel => 10
*/
-static u64 link_freq_to_pixel_rate(u64 f)
+static u64 link_freq_to_pixel_rate(u64 f, unsigned int nlanes)
{
- f *= 2 * 4;
+ f *= 2 * nlanes;
do_div(f, 10);
return f;
@@ -393,15 +500,27 @@ static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
[IMX258_LINK_FREQ_1267MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz),
- .regs = mipi_1267mbps_19_2mhz,
+ [IMX258_2_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_2l),
+ .regs = mipi_1267mbps_19_2mhz_2l,
+ },
+ [IMX258_4_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_4l),
+ .regs = mipi_1267mbps_19_2mhz_4l,
+ },
}
},
[IMX258_LINK_FREQ_640MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz),
- .regs = mipi_640mbps_19_2mhz,
+ [IMX258_2_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_2l),
+ .regs = mipi_640mbps_19_2mhz_2l,
+ },
+ [IMX258_4_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_4l),
+ .regs = mipi_640mbps_19_2mhz_4l,
+ },
}
},
};
@@ -410,15 +529,27 @@ static const struct imx258_link_freq_config link_freq_configs_24[] = {
[IMX258_LINK_FREQ_1267MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz),
- .regs = mipi_1272mbps_24mhz,
+ [IMX258_2_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_2l),
+ .regs = mipi_1272mbps_24mhz_2l,
+ },
+ [IMX258_4_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_4l),
+ .regs = mipi_1272mbps_24mhz_4l,
+ },
}
},
[IMX258_LINK_FREQ_640MBPS] = {
.pixels_per_line = IMX258_PPL_DEFAULT,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz),
- .regs = mipi_642mbps_24mhz,
+ [IMX258_2_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_2l),
+ .regs = mipi_642mbps_24mhz_2l,
+ },
+ [IMX258_4_LANE_MODE] = {
+ .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_4l),
+ .regs = mipi_642mbps_24mhz_4l,
+ },
}
},
};
@@ -477,6 +608,7 @@ struct imx258 {
const struct imx258_link_freq_config *link_freq_configs;
const s64 *link_freq_menu_items;
+ unsigned int nlanes;
/*
* Mutex for serialized access:
@@ -782,7 +914,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
__v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
link_freq = imx258->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, imx258->nlanes);
__v4l2_ctrl_s_ctrl_int64(imx258->pixel_rate, pixel_rate);
/* Update limits and set FPS to default */
vblank_def = imx258->cur_mode->vts_def -
@@ -811,11 +943,13 @@ static int imx258_start_streaming(struct imx258 *imx258)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
const struct imx258_reg_list *reg_list;
+ const struct imx258_link_freq_config *link_freq_cfg;
int ret, link_freq_index;
/* Setup PLL */
link_freq_index = imx258->cur_mode->link_freq_index;
- reg_list = &imx258->link_freq_configs[link_freq_index].reg_list;
+ link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
+ reg_list = &link_freq_cfg->reg_list[imx258->nlanes == 2 ? 0 : 1];
ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
if (ret) {
dev_err(&client->dev, "%s failed to set plls\n", __func__);
@@ -1033,9 +1167,11 @@ static int imx258_init_controls(struct imx258 *imx258)
vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
pixel_rate_max =
- link_freq_to_pixel_rate(imx258->link_freq_menu_items[0]);
+ link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
+ imx258->nlanes);
pixel_rate_min =
- link_freq_to_pixel_rate(imx258->link_freq_menu_items[1]);
+ link_freq_to_pixel_rate(imx258->link_freq_menu_items[1],
+ imx258->nlanes);
/* By default, PIXEL_RATE is read only */
imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
V4L2_CID_PIXEL_RATE,
@@ -1132,6 +1268,10 @@ static int imx258_get_regulators(struct imx258 *imx258,
static int imx258_probe(struct i2c_client *client)
{
struct imx258 *imx258;
+ struct fwnode_handle *endpoint;
+ struct v4l2_fwnode_endpoint ep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
int ret;
u32 val = 0;
@@ -1172,13 +1312,35 @@ static int imx258_probe(struct i2c_client *client)
return -EINVAL;
}
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
+ if (!endpoint) {
+ dev_err(&client->dev, "Endpoint node not found\n");
+ return -EINVAL;
+ }
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
+ fwnode_handle_put(endpoint);
+ if (ret) {
+ dev_err(&client->dev, "Parsing endpoint node failed\n");
+ return ret;
+ }
+
+ /* Get number of data lanes */
+ imx258->nlanes = ep.bus.mipi_csi2.num_data_lanes;
+ if (imx258->nlanes != 2 && imx258->nlanes != 4) {
+ dev_err(&client->dev, "Invalid data lanes: %u\n",
+ imx258->nlanes);
+ ret = -EINVAL;
+ goto error_endpoint_free;
+ }
+
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
/* Will be powered off via pm_runtime_idle */
ret = imx258_power_on(&client->dev);
if (ret)
- return ret;
+ goto error_endpoint_free;
/* Check module identity */
ret = imx258_identify_module(imx258);
@@ -1211,6 +1373,7 @@ static int imx258_probe(struct i2c_client *client)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
+ v4l2_fwnode_endpoint_free(&ep);
return 0;
@@ -1223,6 +1386,9 @@ static int imx258_probe(struct i2c_client *client)
error_identify:
imx258_power_off(&client->dev);
+error_endpoint_free:
+ v4l2_fwnode_endpoint_free(&ep);
+
return ret;
}
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 10/23] media: i2c: imx258: Follow normal V4L2 behaviours for clipping exposure
2024-03-27 22:20 [PATCH 00/23] v2: imx258 improvement series git
` (8 preceding siblings ...)
2024-03-27 22:20 ` [PATCH 09/23] media: i2c: imx258: Add support for running on 2 CSI data lanes git
@ 2024-03-27 22:20 ` git
9 siblings, 0 replies; 13+ messages in thread
From: git @ 2024-03-27 22:20 UTC (permalink / raw)
To: linux-media
Cc: dave.stevenson, jacopo.mondi, mchehab, robh,
krzysztof.kozlowski+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, sakari.ailus, devicetree, imx, linux-arm-kernel,
linux-kernel, x
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
V4L2 sensor drivers are expected are expected to clip the supported
exposure range based on the VBLANK configured.
IMX258 wasn't doing that as register 0x350 (FRM_LENGTH_CTL)
switches it to a mode where frame length tracks coarse exposure time.
Disable this mode and clip the range for V4L2_CID_EXPOSURE appropriately
based on V4L2_CID_VBLANK.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index c65b9aad3b0a..1f5fb980cfbe 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -37,10 +37,11 @@
/* Exposure control */
#define IMX258_REG_EXPOSURE 0x0202
+#define IMX258_EXPOSURE_OFFSET 10
#define IMX258_EXPOSURE_MIN 4
#define IMX258_EXPOSURE_STEP 1
#define IMX258_EXPOSURE_DEFAULT 0x640
-#define IMX258_EXPOSURE_MAX 65535
+#define IMX258_EXPOSURE_MAX (IMX258_VTS_MAX - IMX258_EXPOSURE_OFFSET)
/* Analog gain control */
#define IMX258_REG_ANALOG_GAIN 0x0204
@@ -371,7 +372,7 @@ static const struct imx258_reg mode_common_regs[] = {
{ 0x303A, 0x00 },
{ 0x303B, 0x10 },
{ 0x300D, 0x00 },
- { 0x0350, 0x01 },
+ { 0x0350, 0x00 },
{ 0x0204, 0x00 },
{ 0x0205, 0x00 },
{ 0x020E, 0x01 },
@@ -741,6 +742,19 @@ static int imx258_update_digital_gain(struct imx258 *imx258, u32 len, u32 val)
return 0;
}
+static void imx258_adjust_exposure_range(struct imx258 *imx258)
+{
+ int exposure_max, exposure_def;
+
+ /* Honour the VBLANK limits when setting exposure. */
+ exposure_max = imx258->cur_mode->height + imx258->vblank->val -
+ IMX258_EXPOSURE_OFFSET;
+ exposure_def = min(exposure_max, imx258->exposure->val);
+ __v4l2_ctrl_modify_range(imx258->exposure, imx258->exposure->minimum,
+ exposure_max, imx258->exposure->step,
+ exposure_def);
+}
+
static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct imx258 *imx258 =
@@ -748,6 +762,13 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
int ret = 0;
+ /*
+ * The VBLANK control may change the limits of usable exposure, so check
+ * and adjust if necessary.
+ */
+ if (ctrl->id == V4L2_CID_VBLANK)
+ imx258_adjust_exposure_range(imx258);
+
/*
* Applying V4L2 control value only happens
* when power is up for streaming
--
2.42.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread