[libcamera-devel] [PATCH] imx258: Read analog gain register values

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Jul 20 01:52:23 CEST 2021


Hi Umang,

Thank you for the patch.

As this is meant for testing but not integration, adding a [DNI] or
similar prefix in the subject line would be nice.

On Mon, Jul 19, 2021 at 03:44:37PM +0530, Umang Jain wrote:
> Also copy and tweak imx258_read_reg() to allow signed int values.
> (These constants are signed ints).
> 
> ---
>  drivers/media/i2c/imx258.c | 78 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 78 insertions(+)
> 
> diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
> index f86ae18bc104..d029706f4d51 100644
> --- a/drivers/media/i2c/imx258.c
> +++ b/drivers/media/i2c/imx258.c
> @@ -21,6 +21,13 @@
>  #define IMX258_REG_CHIP_ID		0x0016
>  #define IMX258_CHIP_ID			0x0258
>  
> +/* Gain constant registers */
> +#define IMX258_REG_GAIN_CAP		0x0080
> +#define IMX258_REG_C0			0x008E

Lowercase for hex constants please.

> +#define IMX258_REG_M0			0x008C
> +#define IMX258_REG_C1			0x0092
> +#define IMX258_REG_M1			0x0090

It would be useful to also read the limits.

> +
>  /* V_TIMING internal */
>  #define IMX258_VTS_30FPS		0x0c98
>  #define IMX258_VTS_30FPS_2K		0x0638
> @@ -650,6 +657,38 @@ static int imx258_read_reg(struct imx258 *imx258, u16 reg, u32 len, u32 *val)
>  	return 0;
>  }
>  
> +static int imx258_read_reg_signed(struct imx258 *imx258, u16 reg, u32 len, int16_t *val)

The 16-bit signed type in the kernel is s16.

> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
> +	struct i2c_msg msgs[2];
> +	u8 addr_buf[2] = { reg >> 8, reg & 0xff };
> +	u8 data_buf[4] = { 0, };
> +	int ret;
> +
> +	if (len > 4)
> +		return -EINVAL;
> +
> +	/* Write register address */
> +	msgs[0].addr = client->addr;
> +	msgs[0].flags = 0;
> +	msgs[0].len = ARRAY_SIZE(addr_buf);
> +	msgs[0].buf = addr_buf;
> +
> +	/* Read data from register */
> +	msgs[1].addr = client->addr;
> +	msgs[1].flags = I2C_M_RD;
> +	msgs[1].len = len;
> +	msgs[1].buf = &data_buf[4 - len];
> +
> +	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
> +	if (ret != ARRAY_SIZE(msgs))
> +		return -EIO;
> +
> +	*val = get_unaligned_be32(data_buf);
> +
> +	return 0;
> +}

Instead of duplicating all the code, you could implement this as a
wrapper around imx258_read_reg().

> +
>  /* Write registers up to 2 at a time */
>  static int imx258_write_reg(struct imx258 *imx258, u16 reg, u32 len, u32 val)
>  {
> @@ -1055,6 +1094,7 @@ static int imx258_identify_module(struct imx258 *imx258)
>  	struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
>  	int ret;
>  	u32 val;
> +	int16_t value;
>  
>  	ret = imx258_read_reg(imx258, IMX258_REG_CHIP_ID,
>  			      IMX258_REG_VALUE_16BIT, &val);
> @@ -1070,6 +1110,44 @@ static int imx258_identify_module(struct imx258 *imx258)
>  		return -EIO;
>  	}
>  
> +	// Hijack this to also read analog gain registers and print values
> +	dev_info(&client->dev, "Reading analog gain registers...\n");
> +
> +	ret = imx258_read_reg(imx258, IMX258_REG_GAIN_CAP, IMX258_REG_VALUE_16BIT, &val);
> +	if (ret) {
> +		dev_err(&client->dev, "failed to read GAIN_CAP %x\n",
> +			IMX258_REG_GAIN_CAP);
> +	}
> +	dev_info(&client->dev, "Value of analog Gain capability: %d\n", val);

Another option would be to write

	dev_info(&client->dev, "Value of analog Gain capability: %d\n", (s16)val);

and drop the imx258_read_reg_signed() function completely.

> +
> +	ret = imx258_read_reg_signed(imx258, IMX258_REG_C0, IMX258_REG_VALUE_16BIT, &value);
> +	if (ret) {
> +		dev_err(&client->dev, "failed to read C0 %x\n",
> +			IMX258_REG_C0);
> +	}
> +	dev_info(&client->dev, "Value of C0: %d\n", value);
> +
> +	ret = imx258_read_reg_signed(imx258, IMX258_REG_M0, IMX258_REG_VALUE_16BIT, &value);
> +	if (ret) {
> +		dev_err(&client->dev, "failed to read M0 %x\n",
> +			IMX258_REG_M0);
> +	}
> +	dev_info(&client->dev, "Value of M0: %d\n", value);
> +
> +	ret = imx258_read_reg_signed(imx258, IMX258_REG_C1, IMX258_REG_VALUE_16BIT, &value);
> +	if (ret) {
> +		dev_err(&client->dev, "failed to read C1 %x\n",
> +			IMX258_REG_C1);
> +	}
> +	dev_info(&client->dev, "Value of C1: %d\n", value);
> +
> +	ret = imx258_read_reg_signed(imx258, IMX258_REG_M1, IMX258_REG_VALUE_16BIT, &value);
> +	if (ret) {
> +		dev_err(&client->dev, "failed to read M1 %x\n",
> +			IMX258_REG_M1);
> +	}
> +	dev_info(&client->dev, "Value of M1: %d\n", value);
> +
>  	return 0;
>  }
>  

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list