Re: [PATCH v3] media: i2c: imx335: Support multiple link frequency
From: Sakari Ailus
Date: Mon Jan 08 2024 - 05:03:23 EST
Hi Umang,
Thanks for the patch.
Note that Daniele and Paul are no longer maintaining the driver.
On Wed, Dec 13, 2023 at 02:47:12PM +0530, Umang Jain wrote:
> Support link frequency of 445MHz in addition to 594MHz.
> Break out the register set specific to each data lane rate and also add
> the general timing register set corresponding to the each data
> lane rate.
>
> Signed-off-by: Umang Jain <umang.jain@xxxxxxxxxxxxxxxx>
> ---
> Changes in v3:
> - Use tabspace for indent as denoted by checkpatch.
>
> Changes in v2:
> - Split out from [PATCH v3 0/8] media: Sony IMX335 improvements
> where original patch was introduced.
> - Add general timing registers to each data lane rate configuration
> - Reword commit message.
> ---
> drivers/media/i2c/imx335.c | 108 +++++++++++++++++++++++++++++--------
> 1 file changed, 87 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c
> index 7a37eb327ff4..ffceeb8a15c7 100644
> --- a/drivers/media/i2c/imx335.c
> +++ b/drivers/media/i2c/imx335.c
> @@ -49,7 +49,8 @@
> #define IMX335_INCLK_RATE 24000000
>
> /* CSI2 HW configuration */
> -#define IMX335_LINK_FREQ 594000000
> +#define IMX335_LINK_FREQ_594MHz 594000000
> +#define IMX335_LINK_FREQ_445MHz 445500000
> #define IMX335_NUM_DATA_LANES 4
>
> #define IMX335_REG_MIN 0x00
> @@ -99,7 +100,6 @@ static const char * const imx335_supply_name[] = {
> * @vblank_min: Minimum vertical blanking in lines
> * @vblank_max: Maximum vertical blanking in lines
> * @pclk: Sensor pixel clock
> - * @link_freq_idx: Link frequency index
> * @reg_list: Register list for sensor mode
> */
> struct imx335_mode {
> @@ -111,7 +111,6 @@ struct imx335_mode {
> u32 vblank_min;
> u32 vblank_max;
> u64 pclk;
> - u32 link_freq_idx;
> struct imx335_reg_list reg_list;
> };
>
> @@ -133,6 +132,7 @@ struct imx335_mode {
> * @again_ctrl: Pointer to analog gain control
> * @vblank: Vertical blanking in lines
> * @cur_mode: Pointer to current selected sensor mode
> + * @link_freq_idx: Selected link frequency index
> * @mutex: Mutex for serializing sensor controls
> * @cur_mbus_code: Currently selected media bus format code
> */
> @@ -156,20 +156,16 @@ struct imx335 {
> };
> u32 vblank;
> const struct imx335_mode *cur_mode;
> + u32 link_freq_idx;
> struct mutex mutex;
> u32 cur_mbus_code;
> };
>
> -static const s64 link_freq[] = {
> - IMX335_LINK_FREQ,
> -};
>
> /* Sensor mode registers */
> static const struct imx335_reg mode_2592x1940_regs[] = {
> {0x3000, 0x01},
> {0x3002, 0x00},
> - {0x300c, 0x3b},
> - {0x300d, 0x2a},
> {0x3018, 0x04},
> {0x302c, 0x3c},
> {0x302e, 0x20},
> @@ -177,10 +173,6 @@ static const struct imx335_reg mode_2592x1940_regs[] = {
> {0x3074, 0xc8},
> {0x3076, 0x28},
> {0x304c, 0x00},
> - {0x314c, 0xc6},
> - {0x315a, 0x02},
> - {0x3168, 0xa0},
> - {0x316a, 0x7e},
> {0x31a1, 0x00},
> {0x3288, 0x21},
> {0x328a, 0x02},
> @@ -266,6 +258,65 @@ static const struct imx335_reg raw12_framefmt_regs[] = {
> {0x341d, 0x00},
> };
>
> +static const struct imx335_reg mipi_data_rate_1188Mbps[] = {
> + {0x300c, 0x3b},
> + {0x300d, 0x2a},
> + {0x314c, 0xc6},
> + {0x314d, 0x00},
> + {0x315a, 0x02},
> + {0x3168, 0xa0},
> + {0x316a, 0x7e},
> + {0x319e, 0x01},
> + {0x3a18, 0x8f},
> + {0x3a1a, 0x4f},
> + {0x3a1c, 0x47},
> + {0x3a1e, 0x37},
> + {0x3a1f, 0x01},
> + {0x3a20, 0x4f},
> + {0x3a22, 0x87},
> + {0x3a24, 0x4f},
> + {0x3a26, 0x7f},
> + {0x3a28, 0x3f},
> +};
> +
> +static const struct imx335_reg mipi_data_rate_891Mbps[] = {
> + {0x300c, 0x3b},
> + {0x300d, 0x2a},
> + {0x314c, 0x29},
> + {0x314d, 0x01},
> + {0x315a, 0x06},
> + {0x3168, 0xa0},
> + {0x316a, 0x7e},
> + {0x319e, 0x02},
> + {0x3a18, 0x7f},
> + {0x3a1a, 0x37},
> + {0x3a1c, 0x37},
> + {0x3a1e, 0xf7},
> + {0x3a20, 0x3f},
> + {0x3a22, 0x6f},
> + {0x3a24, 0x3f},
> + {0x3a26, 0x5f},
> + {0x3a28, 0x2f},
> +};
> +
> +static const s64 link_freq[] = {
> + /* Corresponds to 1188Mbps data lane rate */
> + IMX335_LINK_FREQ_594MHz,
> + /* Corresponds to 891Mbps data lane rate */
> + IMX335_LINK_FREQ_445MHz,
> +};
> +
> +static const struct imx335_reg_list link_freq_reglist[] = {
> + {
> + .num_of_regs = ARRAY_SIZE(mipi_data_rate_1188Mbps),
> + .regs = mipi_data_rate_1188Mbps,
> + },
> + {
> + .num_of_regs = ARRAY_SIZE(mipi_data_rate_891Mbps),
> + .regs = mipi_data_rate_891Mbps,
> + },
> +};
> +
> static const u32 imx335_mbus_codes[] = {
> MEDIA_BUS_FMT_SRGGB12_1X12,
> MEDIA_BUS_FMT_SRGGB10_1X10,
> @@ -280,7 +331,6 @@ static const struct imx335_mode supported_mode = {
> .vblank_min = 2560,
> .vblank_max = 133060,
> .pclk = 396000000,
> - .link_freq_idx = 0,
> .reg_list = {
> .num_of_regs = ARRAY_SIZE(mode_2592x1940_regs),
> .regs = mode_2592x1940_regs,
> @@ -405,7 +455,7 @@ static int imx335_update_controls(struct imx335 *imx335,
> {
> int ret;
>
> - ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, mode->link_freq_idx);
> + ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, imx335->link_freq_idx);
> if (ret)
> return ret;
>
> @@ -755,6 +805,14 @@ static int imx335_start_streaming(struct imx335 *imx335)
> const struct imx335_reg_list *reg_list;
> int ret;
>
> + /* Setup PLL */
> + reg_list = &link_freq_reglist[imx335->link_freq_idx];
> + ret = imx335_write_regs(imx335, reg_list->regs, reg_list->num_of_regs);
> + if (ret) {
> + dev_err(imx335->dev, "%s failed to set plls\n", __func__);
> + return ret;
> + }
> +
> /* Write sensor mode registers */
> reg_list = &imx335->cur_mode->reg_list;
> ret = imx335_write_regs(imx335, reg_list->regs,
> @@ -881,7 +939,7 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
> };
> struct fwnode_handle *ep;
> unsigned long rate;
> - unsigned int i;
> + unsigned int i, j;
> int ret;
>
> if (!fwnode)
> @@ -945,13 +1003,21 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
> goto done_endpoint_free;
> }
>
> - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
> - if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ)
> - goto done_endpoint_free;
>
> - dev_err(imx335->dev, "no compatible link frequencies found\n");
> + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
> + for (j = 0; j < ARRAY_SIZE(link_freq); j++) {
> + if (bus_cfg.link_frequencies[i] == link_freq[j]) {
> + imx335->link_freq_idx = j;
> + break;
Instead of stabbing the old implementation, could you instead use
v4l2_link_freq_to_bitmap()
<URL:https://patchwork.linuxtv.org/project/linux-media/patch/20240108075221.15757-2-sakari.ailus@xxxxxxxxxxxxxxx/>?
> + }
> + }
>
> - ret = -EINVAL;
> + if (j == ARRAY_SIZE(link_freq)) {
> + ret = dev_err_probe(imx335->dev, -EINVAL,
> + "no supported link freq found\n");
> + goto done_endpoint_free;
> + }
> + }
>
> done_endpoint_free:
> v4l2_fwnode_endpoint_free(&bus_cfg);
> @@ -1101,7 +1167,7 @@ static int imx335_init_controls(struct imx335 *imx335)
> V4L2_CID_LINK_FREQ,
> ARRAY_SIZE(link_freq) -
> 1,
> - mode->link_freq_idx,
> + imx335->link_freq_idx,
> link_freq);
> if (imx335->link_freq_ctrl)
> imx335->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
--
Regards,
Sakari Ailus