* [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies @ 2025-05-05 21:05 André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 1/4] media: i2c: imx214: Reorder imx214_parse_fwnode call André Apitzsch via B4 Relay ` (3 more replies) 0 siblings, 4 replies; 16+ messages in thread From: André Apitzsch via B4 Relay @ 2025-05-05 21:05 UTC (permalink / raw) To: Ricardo Ribalda, Sakari Ailus, Mauro Carvalho Chehab Cc: ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, André Apitzsch, Ricardo Ribalda The imx214 driver currently supports only a 24 MHz external clock. But there are devices, like Qualcomm-MSM8916-based phones, which cannot provide this frequency. To make the sensor usable by those devices, add support for additional clock frequencies. This series supersedes https://lore.kernel.org/linux-media/20250308-imx214_clk_freq-v1-0-467a4c083c35@apitzsch.eu/ Signed-off-by: André Apitzsch <git@apitzsch.eu> --- Changes in v2: - Add A-b tags - Switch to v4l2_ctrl_s_ctrl_int64() to acquire the control handler mutex - Add error handling for v4l2_ctrl_s_ctrl_int64() and imx214_pll_update() - Replace "read clock frequency from dt" patch by "remove hard-coded external clock frequency" patch - Link to v1: https://lore.kernel.org/r/20250415-imx214_ccs_pll-v1-0-d3d7748e5fbd@apitzsch.eu --- André Apitzsch (4): media: i2c: imx214: Reorder imx214_parse_fwnode call media: i2c: imx214: Prepare for variable clock frequency media: i2c: imx214: Make use of CCS PLL calculator media: i2c: imx214: Remove hard-coded external clock frequency drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/imx214.c | 266 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 204 insertions(+), 63 deletions(-) --- base-commit: 4d4cc73d2632e07451c98c77fdb04aead3f78b00 change-id: 20250406-imx214_ccs_pll-e4aed0e9e532 Best regards, -- André Apitzsch <git@apitzsch.eu> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 1/4] media: i2c: imx214: Reorder imx214_parse_fwnode call 2025-05-05 21:05 [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies André Apitzsch via B4 Relay @ 2025-05-05 21:05 ` André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 2/4] media: i2c: imx214: Prepare for variable clock frequency André Apitzsch via B4 Relay ` (2 subsequent siblings) 3 siblings, 0 replies; 16+ messages in thread From: André Apitzsch via B4 Relay @ 2025-05-05 21:05 UTC (permalink / raw) To: Ricardo Ribalda, Sakari Ailus, Mauro Carvalho Chehab Cc: ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, André Apitzsch, Ricardo Ribalda From: André Apitzsch <git@apitzsch.eu> Reorder imx214_parse_fwnode call to reduce goto paths in upcoming patches. No functional change intended. Acked-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: André Apitzsch <git@apitzsch.eu> --- drivers/media/i2c/imx214.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index dd7bc45523d8b5fcb3ec95728a6d32c4fddede72..0199195dcb7d12dc2ff253fe3eb77ddbcd0812a9 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1261,10 +1261,6 @@ static int imx214_probe(struct i2c_client *client) struct imx214 *imx214; int ret; - ret = imx214_parse_fwnode(dev); - if (ret) - return ret; - imx214 = devm_kzalloc(dev, sizeof(*imx214), GFP_KERNEL); if (!imx214) return -ENOMEM; @@ -1295,6 +1291,10 @@ static int imx214_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(imx214->regmap), "failed to initialize CCI\n"); + ret = imx214_parse_fwnode(dev); + if (ret) + return ret; + v4l2_i2c_subdev_init(&imx214->sd, client, &imx214_subdev_ops); imx214->sd.internal_ops = &imx214_internal_ops; -- 2.49.0 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 2/4] media: i2c: imx214: Prepare for variable clock frequency 2025-05-05 21:05 [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 1/4] media: i2c: imx214: Reorder imx214_parse_fwnode call André Apitzsch via B4 Relay @ 2025-05-05 21:05 ` André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency André Apitzsch via B4 Relay 3 siblings, 0 replies; 16+ messages in thread From: André Apitzsch via B4 Relay @ 2025-05-05 21:05 UTC (permalink / raw) To: Ricardo Ribalda, Sakari Ailus, Mauro Carvalho Chehab Cc: ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, André Apitzsch, Ricardo Ribalda From: André Apitzsch <git@apitzsch.eu> Move clock frequency related parameters out of the constant register sequences, such that the hard coded external clock frequency can be replaced by a variable in the upcoming patches. Acked-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: André Apitzsch <git@apitzsch.eu> --- drivers/media/i2c/imx214.c | 54 ++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 0199195dcb7d12dc2ff253fe3eb77ddbcd0812a9..3aca6ebb02d649c1b7f0b6a6049c1e3aa3d08951 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -299,16 +299,6 @@ static const struct cci_reg_sequence mode_4096x2304[] = { { IMX214_REG_DIG_CROP_WIDTH, 4096 }, { IMX214_REG_DIG_CROP_HEIGHT, 2304 }, - { IMX214_REG_VTPXCK_DIV, 5 }, - { IMX214_REG_VTSYCK_DIV, 2 }, - { IMX214_REG_PREPLLCK_VT_DIV, 3 }, - { IMX214_REG_PLL_VT_MPY, 150 }, - { IMX214_REG_OPPXCK_DIV, 10 }, - { IMX214_REG_OPSYCK_DIV, 1 }, - { IMX214_REG_PLL_MULT_DRIV, IMX214_PLL_SINGLE }, - - { IMX214_REG_REQ_LINK_BIT_RATE, IMX214_LINK_BIT_RATE_MBPS(4800) }, - { CCI_REG8(0x3A03), 0x09 }, { CCI_REG8(0x3A04), 0x50 }, { CCI_REG8(0x3A05), 0x01 }, @@ -362,16 +352,6 @@ static const struct cci_reg_sequence mode_1920x1080[] = { { IMX214_REG_DIG_CROP_WIDTH, 1920 }, { IMX214_REG_DIG_CROP_HEIGHT, 1080 }, - { IMX214_REG_VTPXCK_DIV, 5 }, - { IMX214_REG_VTSYCK_DIV, 2 }, - { IMX214_REG_PREPLLCK_VT_DIV, 3 }, - { IMX214_REG_PLL_VT_MPY, 150 }, - { IMX214_REG_OPPXCK_DIV, 10 }, - { IMX214_REG_OPSYCK_DIV, 1 }, - { IMX214_REG_PLL_MULT_DRIV, IMX214_PLL_SINGLE }, - - { IMX214_REG_REQ_LINK_BIT_RATE, IMX214_LINK_BIT_RATE_MBPS(4800) }, - { CCI_REG8(0x3A03), 0x04 }, { CCI_REG8(0x3A04), 0xF8 }, { CCI_REG8(0x3A05), 0x02 }, @@ -405,9 +385,6 @@ static const struct cci_reg_sequence mode_table_common[] = { /* ATR setting */ { IMX214_REG_ATR_FAST_MOVE, 2 }, - /* external clock setting */ - { IMX214_REG_EXCK_FREQ, IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / 1000000) }, - /* global setting */ /* basic config */ { IMX214_REG_MASK_CORR_FRAMES, IMX214_CORR_FRAMES_MASK }, @@ -777,6 +754,24 @@ static int imx214_entity_init_state(struct v4l2_subdev *subdev, return 0; } +static int imx214_configure_pll(struct imx214 *imx214) +{ + int ret = 0; + + cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, 5, &ret); + cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, 2, &ret); + cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, 3, &ret); + cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, 150, &ret); + cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, 10, &ret); + cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, 1, &ret); + cci_write(imx214->regmap, IMX214_REG_PLL_MULT_DRIV, + IMX214_PLL_SINGLE, &ret); + cci_write(imx214->regmap, IMX214_REG_EXCK_FREQ, + IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / 1000000), &ret); + + return ret; +} + static int imx214_update_digital_gain(struct imx214 *imx214, u32 val) { int ret = 0; @@ -1020,6 +1015,19 @@ static int imx214_start_streaming(struct imx214 *imx214) return ret; } + ret = imx214_configure_pll(imx214); + if (ret) { + dev_err(imx214->dev, "failed to configure PLL %d\n", ret); + return ret; + } + + ret = cci_write(imx214->regmap, IMX214_REG_REQ_LINK_BIT_RATE, + IMX214_LINK_BIT_RATE_MBPS(4800), NULL); + if (ret) { + dev_err(imx214->dev, "failed to configure link bit rate\n"); + return ret; + } + ret = cci_write(imx214->regmap, IMX214_REG_CSI_LANE_MODE, IMX214_CSI_4_LANE_MODE, NULL); if (ret) { -- 2.49.0 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator 2025-05-05 21:05 [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 1/4] media: i2c: imx214: Reorder imx214_parse_fwnode call André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 2/4] media: i2c: imx214: Prepare for variable clock frequency André Apitzsch via B4 Relay @ 2025-05-05 21:05 ` André Apitzsch via B4 Relay 2025-05-06 8:05 ` Sakari Ailus 2025-05-05 21:05 ` [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency André Apitzsch via B4 Relay 3 siblings, 1 reply; 16+ messages in thread From: André Apitzsch via B4 Relay @ 2025-05-05 21:05 UTC (permalink / raw) To: Ricardo Ribalda, Sakari Ailus, Mauro Carvalho Chehab Cc: ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, André Apitzsch, Ricardo Ribalda From: André Apitzsch <git@apitzsch.eu> Calculate PLL parameters based on clock frequency and link frequency. Acked-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: André Apitzsch <git@apitzsch.eu> --- drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/imx214.c | 216 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 178 insertions(+), 39 deletions(-) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index e576b213084d232e90b7e556a7a855a3bb95544c..c8e24c42e0c4ea169f1b6cdc4f2631234a51c7d9 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -141,6 +141,7 @@ config VIDEO_IMX214 depends on GPIOLIB select REGMAP_I2C select V4L2_CCI_I2C + select VIDEO_CCS_PLL help This is a Video4Linux2 sensor driver for the Sony IMX214 camera. diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 3aca6ebb02d649c1b7f0b6a6049c1e3aa3d08951..9e9be47394ec768a5b34d44b06b5bbb0988da5a1 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -20,6 +20,8 @@ #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> +#include "ccs-pll.h" + /* Chip ID */ #define IMX214_REG_CHIP_ID CCI_REG16(0x0016) #define IMX214_CHIP_ID 0x0214 @@ -34,7 +36,6 @@ #define IMX214_DEFAULT_LINK_FREQ 600000000 /* Keep wrong link frequency for backward compatibility */ #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 -#define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10) #define IMX214_FPS 30 /* V-TIMING internal */ @@ -84,6 +85,7 @@ #define IMX214_CSI_DATA_FORMAT_RAW10 0x0A0A #define IMX214_CSI_DATA_FORMAT_COMP6 0x0A06 #define IMX214_CSI_DATA_FORMAT_COMP8 0x0A08 +#define IMX214_BITS_PER_PIXEL_MASK 0xFF #define IMX214_REG_CSI_LANE_MODE CCI_REG8(0x0114) #define IMX214_CSI_2_LANE_MODE 1 @@ -249,6 +251,10 @@ struct imx214 { struct clk *xclk; struct regmap *regmap; + struct ccs_pll pll; + + struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_subdev sd; struct media_pad pad; @@ -758,16 +764,22 @@ static int imx214_configure_pll(struct imx214 *imx214) { int ret = 0; - cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, 5, &ret); - cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, 2, &ret); - cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, 3, &ret); - cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, 150, &ret); - cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, 10, &ret); - cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, 1, &ret); + cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, + imx214->pll.vt_bk.pix_clk_div, &ret); + cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, + imx214->pll.vt_bk.sys_clk_div, &ret); + cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, + imx214->pll.vt_fr.pre_pll_clk_div, &ret); + cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, + imx214->pll.vt_fr.pll_multiplier, &ret); + cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, + imx214->pll.op_bk.pix_clk_div, &ret); + cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, + imx214->pll.op_bk.sys_clk_div, &ret); cci_write(imx214->regmap, IMX214_REG_PLL_MULT_DRIV, IMX214_PLL_SINGLE, &ret); cci_write(imx214->regmap, IMX214_REG_EXCK_FREQ, - IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / 1000000), &ret); + IMX214_EXCK_FREQ(imx214->pll.ext_clk_freq_hz / 1000000), &ret); return ret; } @@ -872,9 +884,6 @@ static const struct v4l2_ctrl_ops imx214_ctrl_ops = { static int imx214_ctrls_init(struct imx214 *imx214) { - static const s64 link_freq[] = { - IMX214_DEFAULT_LINK_FREQ - }; static const struct v4l2_area unit_size = { .width = 1120, .height = 1120, @@ -895,15 +904,14 @@ static int imx214_ctrls_init(struct imx214 *imx214) if (ret) return ret; - imx214->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL, - V4L2_CID_PIXEL_RATE, 0, - IMX214_DEFAULT_PIXEL_RATE, 1, - IMX214_DEFAULT_PIXEL_RATE); + imx214->pixel_rate = + v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_PIXEL_RATE, 1, + INT_MAX, 1, 1); imx214->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, NULL, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(link_freq) - 1, - 0, link_freq); + imx214->bus_cfg.nr_of_link_frequencies - 1, + 0, imx214->bus_cfg.link_frequencies); if (imx214->link_freq) imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; @@ -1006,6 +1014,7 @@ static int imx214_start_streaming(struct imx214 *imx214) const struct v4l2_mbus_framefmt *fmt; struct v4l2_subdev_state *state; const struct imx214_mode *mode; + int bit_rate_mbps; int ret; ret = cci_multi_reg_write(imx214->regmap, mode_table_common, @@ -1021,8 +1030,10 @@ static int imx214_start_streaming(struct imx214 *imx214) return ret; } + bit_rate_mbps = (imx214->pll.pixel_rate_pixel_array / 1000000) + * imx214->pll.bits_per_pixel; ret = cci_write(imx214->regmap, IMX214_REG_REQ_LINK_BIT_RATE, - IMX214_LINK_BIT_RATE_MBPS(4800), NULL); + IMX214_LINK_BIT_RATE_MBPS(bit_rate_mbps), NULL); if (ret) { dev_err(imx214->dev, "failed to configure link bit rate\n"); return ret; @@ -1105,6 +1116,112 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) return ret; } +static int imx214_pll_calculate(struct imx214 *imx214, struct ccs_pll *pll, + unsigned int link_freq) +{ + struct ccs_pll_limits limits = { + .min_ext_clk_freq_hz = 6000000, + .max_ext_clk_freq_hz = 27000000, + + .vt_fr = { + .min_pre_pll_clk_div = 1, + .max_pre_pll_clk_div = 15, + /* min_pll_op_clk_freq_hz / max_pll_multiplier */ + .min_pll_ip_clk_freq_hz = 281667, + /* max_pll_op_clk_freq_hz / min_pll_multiplier */ + .max_pll_ip_clk_freq_hz = 100000000, + .min_pll_multiplier = 12, + .max_pll_multiplier = 1200, + .min_pll_op_clk_freq_hz = 338000000, + .max_pll_op_clk_freq_hz = 1200000000, + }, + .vt_bk = { + .min_sys_clk_div = 2, + .max_sys_clk_div = 4, + .min_pix_clk_div = 5, + .max_pix_clk_div = 10, + .min_pix_clk_freq_hz = 30000000, + .max_pix_clk_freq_hz = 120000000, + }, + .op_bk = { + .min_sys_clk_div = 1, + .max_sys_clk_div = 2, + .min_pix_clk_div = 6, + .max_pix_clk_div = 10, + .min_pix_clk_freq_hz = 30000000, + .max_pix_clk_freq_hz = 120000000, + }, + + .min_line_length_pck_bin = IMX214_PPL_DEFAULT, + .min_line_length_pck = IMX214_PPL_DEFAULT, + }; + unsigned int num_lanes = imx214->bus_cfg.bus.mipi_csi2.num_data_lanes; + int ret; + + /* + * There are no documented constraints on the sys clock frequency, for + * either branch. Recover them based on the PLL output clock frequency + * and sys_clk_div limits on one hand, and the pix clock frequency and + * the pix_clk_div limits on the other hand. + */ + limits.vt_bk.min_sys_clk_freq_hz = + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.vt_bk.max_sys_clk_div, + limits.vt_bk.min_pix_clk_freq_hz * limits.vt_bk.min_pix_clk_div); + limits.vt_bk.max_sys_clk_freq_hz = + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.vt_bk.min_sys_clk_div, + limits.vt_bk.max_pix_clk_freq_hz * limits.vt_bk.max_pix_clk_div); + + limits.op_bk.min_sys_clk_freq_hz = + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.op_bk.max_sys_clk_div, + limits.op_bk.min_pix_clk_freq_hz * limits.op_bk.min_pix_clk_div); + limits.op_bk.max_sys_clk_freq_hz = + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.op_bk.min_sys_clk_div, + limits.op_bk.max_pix_clk_freq_hz * limits.op_bk.max_pix_clk_div); + + memset(pll, 0, sizeof(*pll)); + + pll->bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; + pll->op_lanes = num_lanes; + pll->vt_lanes = num_lanes; + pll->csi2.lanes = num_lanes; + + pll->binning_horizontal = 1; + pll->binning_vertical = 1; + pll->scale_m = 1; + pll->scale_n = 1; + pll->bits_per_pixel = + IMX214_CSI_DATA_FORMAT_RAW10 & IMX214_BITS_PER_PIXEL_MASK; + pll->flags = CCS_PLL_FLAG_LANE_SPEED_MODEL; + pll->link_freq = link_freq; + pll->ext_clk_freq_hz = clk_get_rate(imx214->xclk); + + ret = ccs_pll_calculate(imx214->dev, &limits, pll); + + return ret; +} + +static int imx214_pll_update(struct imx214 *imx214) +{ + u64 link_freq; + int ret; + + link_freq = imx214->bus_cfg.link_frequencies[imx214->link_freq->val]; + ret = imx214_pll_calculate(imx214, &imx214->pll, link_freq); + if (ret) { + dev_err(imx214->dev, "PLL calculations failed: %d\n", ret); + return ret; + } + + ret = v4l2_ctrl_s_ctrl_int64(imx214->pixel_rate, + imx214->pll.pixel_rate_pixel_array); + if (ret) { + dev_err(imx214->dev, "failed to set pixel rate\n"); + return ret; + } + + return 0; +} + static int imx214_get_frame_interval(struct v4l2_subdev *subdev, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fival) @@ -1211,12 +1328,10 @@ static int imx214_identify_module(struct imx214 *imx214) return 0; } -static int imx214_parse_fwnode(struct device *dev) +static int imx214_parse_fwnode(struct device *dev, struct imx214 *imx214) { + struct v4l2_fwnode_endpoint *bus_cfg = &imx214->bus_cfg; struct fwnode_handle *endpoint; - struct v4l2_fwnode_endpoint bus_cfg = { - .bus_type = V4L2_MBUS_CSI2_DPHY, - }; unsigned int i; int ret; @@ -1224,42 +1339,52 @@ static int imx214_parse_fwnode(struct device *dev) if (!endpoint) return dev_err_probe(dev, -EINVAL, "endpoint node not found\n"); - ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg); + bus_cfg->bus_type = V4L2_MBUS_CSI2_DPHY; + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, bus_cfg); + fwnode_handle_put(endpoint); if (ret) { dev_err_probe(dev, ret, "parsing endpoint node failed\n"); - goto done; + goto error; } /* Check the number of MIPI CSI2 data lanes */ - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { + if (bus_cfg->bus.mipi_csi2.num_data_lanes != 4) { ret = dev_err_probe(dev, -EINVAL, "only 4 data lanes are currently supported\n"); - goto done; + goto error; } - if (bus_cfg.nr_of_link_frequencies != 1) + if (bus_cfg->nr_of_link_frequencies != 1) dev_warn(dev, "Only one link-frequency supported, please review your DT. Continuing anyway\n"); - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { - if (bus_cfg.link_frequencies[i] == IMX214_DEFAULT_LINK_FREQ) + for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) { + u64 freq = bus_cfg->link_frequencies[i]; + struct ccs_pll pll; + + if (!imx214_pll_calculate(imx214, &pll, freq)) break; - if (bus_cfg.link_frequencies[i] == - IMX214_DEFAULT_LINK_FREQ_LEGACY) { + if (freq == IMX214_DEFAULT_LINK_FREQ_LEGACY) { dev_warn(dev, "link-frequencies %d not supported, please review your DT. Continuing anyway\n", IMX214_DEFAULT_LINK_FREQ); + freq = IMX214_DEFAULT_LINK_FREQ; + if (imx214_pll_calculate(imx214, &pll, freq)) + continue; + bus_cfg->link_frequencies[i] = freq; break; } } - if (i == bus_cfg.nr_of_link_frequencies) + if (i == bus_cfg->nr_of_link_frequencies) ret = dev_err_probe(dev, -EINVAL, - "link-frequencies %d not supported, please review your DT\n", - IMX214_DEFAULT_LINK_FREQ); + "link-frequencies %lld not supported, please review your DT\n", + bus_cfg->nr_of_link_frequencies ? + bus_cfg->link_frequencies[0] : 0); -done: - v4l2_fwnode_endpoint_free(&bus_cfg); - fwnode_handle_put(endpoint); + return 0; + +error: + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); return ret; } @@ -1299,7 +1424,7 @@ static int imx214_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(imx214->regmap), "failed to initialize CCI\n"); - ret = imx214_parse_fwnode(dev); + ret = imx214_parse_fwnode(dev, imx214); if (ret) return ret; @@ -1310,7 +1435,9 @@ static int imx214_probe(struct i2c_client *client) * Enable power initially, to avoid warnings * from clk_disable on power_off */ - imx214_power_on(imx214->dev); + ret = imx214_power_on(imx214->dev); + if (ret < 0) + goto error_fwnode; ret = imx214_identify_module(imx214); if (ret) @@ -1341,6 +1468,12 @@ static int imx214_probe(struct i2c_client *client) pm_runtime_set_active(imx214->dev); pm_runtime_enable(imx214->dev); + ret = imx214_pll_update(imx214); + if (ret < 0) { + dev_err_probe(dev, ret, "failed to update PLL\n"); + goto error_subdev_cleanup; + } + ret = v4l2_async_register_subdev_sensor(&imx214->sd); if (ret < 0) { dev_err_probe(dev, ret, @@ -1366,6 +1499,9 @@ static int imx214_probe(struct i2c_client *client) error_power_off: imx214_power_off(imx214->dev); +error_fwnode: + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); + return ret; } @@ -1378,6 +1514,8 @@ static void imx214_remove(struct i2c_client *client) v4l2_subdev_cleanup(sd); media_entity_cleanup(&imx214->sd.entity); v4l2_ctrl_handler_free(&imx214->ctrls); + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); + pm_runtime_disable(&client->dev); if (!pm_runtime_status_suspended(&client->dev)) { imx214_power_off(imx214->dev); -- 2.49.0 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator 2025-05-05 21:05 ` [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator André Apitzsch via B4 Relay @ 2025-05-06 8:05 ` Sakari Ailus 2025-05-06 20:16 ` André Apitzsch 0 siblings, 1 reply; 16+ messages in thread From: Sakari Ailus @ 2025-05-06 8:05 UTC (permalink / raw) To: git Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, Ricardo Ribalda Hi André, A few more comments below. On Mon, May 05, 2025 at 11:05:55PM +0200, André Apitzsch via B4 Relay wrote: > From: André Apitzsch <git@apitzsch.eu> > > Calculate PLL parameters based on clock frequency and link frequency. > > Acked-by: Ricardo Ribalda <ribalda@chromium.org> > Signed-off-by: André Apitzsch <git@apitzsch.eu> > --- > drivers/media/i2c/Kconfig | 1 + > drivers/media/i2c/imx214.c | 216 +++++++++++++++++++++++++++++++++++++-------- > 2 files changed, 178 insertions(+), 39 deletions(-) > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > index e576b213084d232e90b7e556a7a855a3bb95544c..c8e24c42e0c4ea169f1b6cdc4f2631234a51c7d9 100644 > --- a/drivers/media/i2c/Kconfig > +++ b/drivers/media/i2c/Kconfig > @@ -141,6 +141,7 @@ config VIDEO_IMX214 > depends on GPIOLIB > select REGMAP_I2C > select V4L2_CCI_I2C > + select VIDEO_CCS_PLL > help > This is a Video4Linux2 sensor driver for the Sony > IMX214 camera. > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > index 3aca6ebb02d649c1b7f0b6a6049c1e3aa3d08951..9e9be47394ec768a5b34d44b06b5bbb0988da5a1 100644 > --- a/drivers/media/i2c/imx214.c > +++ b/drivers/media/i2c/imx214.c > @@ -20,6 +20,8 @@ > #include <media/v4l2-fwnode.h> > #include <media/v4l2-subdev.h> > > +#include "ccs-pll.h" > + > /* Chip ID */ > #define IMX214_REG_CHIP_ID CCI_REG16(0x0016) > #define IMX214_CHIP_ID 0x0214 > @@ -34,7 +36,6 @@ > #define IMX214_DEFAULT_LINK_FREQ 600000000 > /* Keep wrong link frequency for backward compatibility */ > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > -#define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10) > #define IMX214_FPS 30 > > /* V-TIMING internal */ > @@ -84,6 +85,7 @@ > #define IMX214_CSI_DATA_FORMAT_RAW10 0x0A0A > #define IMX214_CSI_DATA_FORMAT_COMP6 0x0A06 > #define IMX214_CSI_DATA_FORMAT_COMP8 0x0A08 > +#define IMX214_BITS_PER_PIXEL_MASK 0xFF > > #define IMX214_REG_CSI_LANE_MODE CCI_REG8(0x0114) > #define IMX214_CSI_2_LANE_MODE 1 > @@ -249,6 +251,10 @@ struct imx214 { > struct clk *xclk; > struct regmap *regmap; > > + struct ccs_pll pll; > + > + struct v4l2_fwnode_endpoint bus_cfg; > + > struct v4l2_subdev sd; > struct media_pad pad; > > @@ -758,16 +764,22 @@ static int imx214_configure_pll(struct imx214 *imx214) > { > int ret = 0; > > - cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, 5, &ret); > - cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, 2, &ret); > - cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, 3, &ret); > - cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, 150, &ret); > - cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, 10, &ret); > - cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, 1, &ret); > + cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, > + imx214->pll.vt_bk.pix_clk_div, &ret); > + cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, > + imx214->pll.vt_bk.sys_clk_div, &ret); > + cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, > + imx214->pll.vt_fr.pre_pll_clk_div, &ret); > + cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, > + imx214->pll.vt_fr.pll_multiplier, &ret); > + cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, > + imx214->pll.op_bk.pix_clk_div, &ret); > + cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, > + imx214->pll.op_bk.sys_clk_div, &ret); > cci_write(imx214->regmap, IMX214_REG_PLL_MULT_DRIV, > IMX214_PLL_SINGLE, &ret); > cci_write(imx214->regmap, IMX214_REG_EXCK_FREQ, > - IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / 1000000), &ret); > + IMX214_EXCK_FREQ(imx214->pll.ext_clk_freq_hz / 1000000), &ret); > > return ret; > } > @@ -872,9 +884,6 @@ static const struct v4l2_ctrl_ops imx214_ctrl_ops = { > > static int imx214_ctrls_init(struct imx214 *imx214) > { > - static const s64 link_freq[] = { > - IMX214_DEFAULT_LINK_FREQ > - }; > static const struct v4l2_area unit_size = { > .width = 1120, > .height = 1120, > @@ -895,15 +904,14 @@ static int imx214_ctrls_init(struct imx214 *imx214) > if (ret) > return ret; > > - imx214->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL, > - V4L2_CID_PIXEL_RATE, 0, > - IMX214_DEFAULT_PIXEL_RATE, 1, > - IMX214_DEFAULT_PIXEL_RATE); > + imx214->pixel_rate = > + v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_PIXEL_RATE, 1, > + INT_MAX, 1, 1); > > imx214->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, NULL, > V4L2_CID_LINK_FREQ, > - ARRAY_SIZE(link_freq) - 1, > - 0, link_freq); > + imx214->bus_cfg.nr_of_link_frequencies - 1, > + 0, imx214->bus_cfg.link_frequencies); > if (imx214->link_freq) > imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; > > @@ -1006,6 +1014,7 @@ static int imx214_start_streaming(struct imx214 *imx214) > const struct v4l2_mbus_framefmt *fmt; > struct v4l2_subdev_state *state; > const struct imx214_mode *mode; > + int bit_rate_mbps; > int ret; > > ret = cci_multi_reg_write(imx214->regmap, mode_table_common, > @@ -1021,8 +1030,10 @@ static int imx214_start_streaming(struct imx214 *imx214) > return ret; > } > > + bit_rate_mbps = (imx214->pll.pixel_rate_pixel_array / 1000000) > + * imx214->pll.bits_per_pixel; > ret = cci_write(imx214->regmap, IMX214_REG_REQ_LINK_BIT_RATE, > - IMX214_LINK_BIT_RATE_MBPS(4800), NULL); > + IMX214_LINK_BIT_RATE_MBPS(bit_rate_mbps), NULL); > if (ret) { > dev_err(imx214->dev, "failed to configure link bit rate\n"); > return ret; > @@ -1105,6 +1116,112 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) > return ret; > } > > +static int imx214_pll_calculate(struct imx214 *imx214, struct ccs_pll *pll, > + unsigned int link_freq) > +{ > + struct ccs_pll_limits limits = { > + .min_ext_clk_freq_hz = 6000000, > + .max_ext_clk_freq_hz = 27000000, > + > + .vt_fr = { > + .min_pre_pll_clk_div = 1, > + .max_pre_pll_clk_div = 15, > + /* min_pll_op_clk_freq_hz / max_pll_multiplier */ > + .min_pll_ip_clk_freq_hz = 281667, > + /* max_pll_op_clk_freq_hz / min_pll_multiplier */ > + .max_pll_ip_clk_freq_hz = 100000000, Regarding these limits -- the pll_ip_clk_freq_hz limits are likely between around 6 MHz (lower limit) and between 12 MHz and 27 MHz. I'd use 6 for lower and 12 for higher if they yield correct configuration currently and loosen them up only if needed. > + .min_pll_multiplier = 12, > + .max_pll_multiplier = 1200, > + .min_pll_op_clk_freq_hz = 338000000, > + .max_pll_op_clk_freq_hz = 1200000000, > + }, > + .vt_bk = { > + .min_sys_clk_div = 2, > + .max_sys_clk_div = 4, > + .min_pix_clk_div = 5, > + .max_pix_clk_div = 10, > + .min_pix_clk_freq_hz = 30000000, > + .max_pix_clk_freq_hz = 120000000, > + }, > + .op_bk = { > + .min_sys_clk_div = 1, > + .max_sys_clk_div = 2, > + .min_pix_clk_div = 6, > + .max_pix_clk_div = 10, > + .min_pix_clk_freq_hz = 30000000, > + .max_pix_clk_freq_hz = 120000000, > + }, > + > + .min_line_length_pck_bin = IMX214_PPL_DEFAULT, > + .min_line_length_pck = IMX214_PPL_DEFAULT, > + }; > + unsigned int num_lanes = imx214->bus_cfg.bus.mipi_csi2.num_data_lanes; > + int ret; > + > + /* > + * There are no documented constraints on the sys clock frequency, for > + * either branch. Recover them based on the PLL output clock frequency > + * and sys_clk_div limits on one hand, and the pix clock frequency and > + * the pix_clk_div limits on the other hand. > + */ > + limits.vt_bk.min_sys_clk_freq_hz = > + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.vt_bk.max_sys_clk_div, > + limits.vt_bk.min_pix_clk_freq_hz * limits.vt_bk.min_pix_clk_div); > + limits.vt_bk.max_sys_clk_freq_hz = > + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.vt_bk.min_sys_clk_div, > + limits.vt_bk.max_pix_clk_freq_hz * limits.vt_bk.max_pix_clk_div); > + > + limits.op_bk.min_sys_clk_freq_hz = > + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.op_bk.max_sys_clk_div, > + limits.op_bk.min_pix_clk_freq_hz * limits.op_bk.min_pix_clk_div); > + limits.op_bk.max_sys_clk_freq_hz = > + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.op_bk.min_sys_clk_div, > + limits.op_bk.max_pix_clk_freq_hz * limits.op_bk.max_pix_clk_div); > + > + memset(pll, 0, sizeof(*pll)); > + > + pll->bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; > + pll->op_lanes = num_lanes; > + pll->vt_lanes = num_lanes; > + pll->csi2.lanes = num_lanes; > + > + pll->binning_horizontal = 1; > + pll->binning_vertical = 1; > + pll->scale_m = 1; > + pll->scale_n = 1; > + pll->bits_per_pixel = > + IMX214_CSI_DATA_FORMAT_RAW10 & IMX214_BITS_PER_PIXEL_MASK; > + pll->flags = CCS_PLL_FLAG_LANE_SPEED_MODEL; > + pll->link_freq = link_freq; > + pll->ext_clk_freq_hz = clk_get_rate(imx214->xclk); > + > + ret = ccs_pll_calculate(imx214->dev, &limits, pll); > + > + return ret; You can drop ret here. > +} > + > +static int imx214_pll_update(struct imx214 *imx214) > +{ > + u64 link_freq; > + int ret; > + > + link_freq = imx214->bus_cfg.link_frequencies[imx214->link_freq->val]; > + ret = imx214_pll_calculate(imx214, &imx214->pll, link_freq); > + if (ret) { > + dev_err(imx214->dev, "PLL calculations failed: %d\n", ret); > + return ret; > + } > + > + ret = v4l2_ctrl_s_ctrl_int64(imx214->pixel_rate, > + imx214->pll.pixel_rate_pixel_array); > + if (ret) { > + dev_err(imx214->dev, "failed to set pixel rate\n"); > + return ret; > + } > + > + return 0; > +} > + > static int imx214_get_frame_interval(struct v4l2_subdev *subdev, > struct v4l2_subdev_state *sd_state, > struct v4l2_subdev_frame_interval *fival) > @@ -1211,12 +1328,10 @@ static int imx214_identify_module(struct imx214 *imx214) > return 0; > } > > -static int imx214_parse_fwnode(struct device *dev) > +static int imx214_parse_fwnode(struct device *dev, struct imx214 *imx214) > { > + struct v4l2_fwnode_endpoint *bus_cfg = &imx214->bus_cfg; > struct fwnode_handle *endpoint; > - struct v4l2_fwnode_endpoint bus_cfg = { > - .bus_type = V4L2_MBUS_CSI2_DPHY, > - }; > unsigned int i; > int ret; > > @@ -1224,42 +1339,52 @@ static int imx214_parse_fwnode(struct device *dev) > if (!endpoint) > return dev_err_probe(dev, -EINVAL, "endpoint node not found\n"); > > - ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg); > + bus_cfg->bus_type = V4L2_MBUS_CSI2_DPHY; > + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, bus_cfg); > + fwnode_handle_put(endpoint); > if (ret) { > dev_err_probe(dev, ret, "parsing endpoint node failed\n"); > - goto done; > + goto error; > } > > /* Check the number of MIPI CSI2 data lanes */ > - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { > + if (bus_cfg->bus.mipi_csi2.num_data_lanes != 4) { > ret = dev_err_probe(dev, -EINVAL, > "only 4 data lanes are currently supported\n"); > - goto done; > + goto error; > } > > - if (bus_cfg.nr_of_link_frequencies != 1) > + if (bus_cfg->nr_of_link_frequencies != 1) > dev_warn(dev, "Only one link-frequency supported, please review your DT. Continuing anyway\n"); > > - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { > - if (bus_cfg.link_frequencies[i] == IMX214_DEFAULT_LINK_FREQ) > + for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) { > + u64 freq = bus_cfg->link_frequencies[i]; > + struct ccs_pll pll; > + > + if (!imx214_pll_calculate(imx214, &pll, freq)) > break; > - if (bus_cfg.link_frequencies[i] == > - IMX214_DEFAULT_LINK_FREQ_LEGACY) { > + if (freq == IMX214_DEFAULT_LINK_FREQ_LEGACY) { > dev_warn(dev, > "link-frequencies %d not supported, please review your DT. Continuing anyway\n", > IMX214_DEFAULT_LINK_FREQ); > + freq = IMX214_DEFAULT_LINK_FREQ; > + if (imx214_pll_calculate(imx214, &pll, freq)) > + continue; > + bus_cfg->link_frequencies[i] = freq; > break; > } > } > > - if (i == bus_cfg.nr_of_link_frequencies) > + if (i == bus_cfg->nr_of_link_frequencies) > ret = dev_err_probe(dev, -EINVAL, > - "link-frequencies %d not supported, please review your DT\n", > - IMX214_DEFAULT_LINK_FREQ); > + "link-frequencies %lld not supported, please review your DT\n", > + bus_cfg->nr_of_link_frequencies ? > + bus_cfg->link_frequencies[0] : 0); > > -done: > - v4l2_fwnode_endpoint_free(&bus_cfg); > - fwnode_handle_put(endpoint); > + return 0; > + > +error: > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > return ret; > } > > @@ -1299,7 +1424,7 @@ static int imx214_probe(struct i2c_client *client) > return dev_err_probe(dev, PTR_ERR(imx214->regmap), > "failed to initialize CCI\n"); > > - ret = imx214_parse_fwnode(dev); > + ret = imx214_parse_fwnode(dev, imx214); > if (ret) > return ret; > > @@ -1310,7 +1435,9 @@ static int imx214_probe(struct i2c_client *client) > * Enable power initially, to avoid warnings > * from clk_disable on power_off > */ > - imx214_power_on(imx214->dev); > + ret = imx214_power_on(imx214->dev); > + if (ret < 0) > + goto error_fwnode; > > ret = imx214_identify_module(imx214); > if (ret) > @@ -1341,6 +1468,12 @@ static int imx214_probe(struct i2c_client *client) > pm_runtime_set_active(imx214->dev); > pm_runtime_enable(imx214->dev); > > + ret = imx214_pll_update(imx214); > + if (ret < 0) { > + dev_err_probe(dev, ret, "failed to update PLL\n"); > + goto error_subdev_cleanup; > + } > + > ret = v4l2_async_register_subdev_sensor(&imx214->sd); > if (ret < 0) { > dev_err_probe(dev, ret, > @@ -1366,6 +1499,9 @@ static int imx214_probe(struct i2c_client *client) > error_power_off: > imx214_power_off(imx214->dev); > > +error_fwnode: > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > + > return ret; > } > > @@ -1378,6 +1514,8 @@ static void imx214_remove(struct i2c_client *client) > v4l2_subdev_cleanup(sd); > media_entity_cleanup(&imx214->sd.entity); > v4l2_ctrl_handler_free(&imx214->ctrls); > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > + > pm_runtime_disable(&client->dev); > if (!pm_runtime_status_suspended(&client->dev)) { > imx214_power_off(imx214->dev); > -- Regards, Sakari Ailus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator 2025-05-06 8:05 ` Sakari Ailus @ 2025-05-06 20:16 ` André Apitzsch 2025-05-06 20:53 ` Sakari Ailus 0 siblings, 1 reply; 16+ messages in thread From: André Apitzsch @ 2025-05-06 20:16 UTC (permalink / raw) To: Sakari Ailus Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, Ricardo Ribalda Hi Sakari, thanks for the feedback. One question below. Am Dienstag, dem 06.05.2025 um 08:05 +0000 schrieb Sakari Ailus: > Hi André, > > A few more comments below. > > On Mon, May 05, 2025 at 11:05:55PM +0200, André Apitzsch via B4 Relay > wrote: > > From: André Apitzsch <git@apitzsch.eu> > > > > Calculate PLL parameters based on clock frequency and link > > frequency. > > > > Acked-by: Ricardo Ribalda <ribalda@chromium.org> > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > --- > > drivers/media/i2c/Kconfig | 1 + > > drivers/media/i2c/imx214.c | 216 > > +++++++++++++++++++++++++++++++++++++-------- > > 2 files changed, 178 insertions(+), 39 deletions(-) > > > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > > index > > e576b213084d232e90b7e556a7a855a3bb95544c..c8e24c42e0c4ea169f1b6cdc4 > > f2631234a51c7d9 100644 > > --- a/drivers/media/i2c/Kconfig > > +++ b/drivers/media/i2c/Kconfig > > @@ -141,6 +141,7 @@ config VIDEO_IMX214 > > depends on GPIOLIB > > select REGMAP_I2C > > select V4L2_CCI_I2C > > + select VIDEO_CCS_PLL > > help > > This is a Video4Linux2 sensor driver for the Sony > > IMX214 camera. > > diff --git a/drivers/media/i2c/imx214.c > > b/drivers/media/i2c/imx214.c > > index > > 3aca6ebb02d649c1b7f0b6a6049c1e3aa3d08951..9e9be47394ec768a5b34d44b0 > > 6b5bbb0988da5a1 100644 > > --- a/drivers/media/i2c/imx214.c > > +++ b/drivers/media/i2c/imx214.c > > @@ -20,6 +20,8 @@ > > #include <media/v4l2-fwnode.h> > > #include <media/v4l2-subdev.h> > > > > +#include "ccs-pll.h" > > + > > /* Chip ID */ > > #define IMX214_REG_CHIP_ID CCI_REG16(0x0016) > > #define IMX214_CHIP_ID 0x0214 > > @@ -34,7 +36,6 @@ > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > /* Keep wrong link frequency for backward compatibility */ > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > -#define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * > > 8LL) / 10) > > #define IMX214_FPS 30 > > > > /* V-TIMING internal */ > > @@ -84,6 +85,7 @@ > > #define IMX214_CSI_DATA_FORMAT_RAW10 0x0A0A > > #define IMX214_CSI_DATA_FORMAT_COMP6 0x0A06 > > #define IMX214_CSI_DATA_FORMAT_COMP8 0x0A08 > > +#define IMX214_BITS_PER_PIXEL_MASK 0xFF > > > > #define IMX214_REG_CSI_LANE_MODE CCI_REG8(0x0114) > > #define IMX214_CSI_2_LANE_MODE 1 > > @@ -249,6 +251,10 @@ struct imx214 { > > struct clk *xclk; > > struct regmap *regmap; > > > > + struct ccs_pll pll; > > + > > + struct v4l2_fwnode_endpoint bus_cfg; > > + > > struct v4l2_subdev sd; > > struct media_pad pad; > > > > @@ -758,16 +764,22 @@ static int imx214_configure_pll(struct imx214 > > *imx214) > > { > > int ret = 0; > > > > - cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, 5, &ret); > > - cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, 2, &ret); > > - cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, 3, > > &ret); > > - cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, 150, > > &ret); > > - cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, 10, > > &ret); > > - cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, 1, &ret); > > + cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, > > + imx214->pll.vt_bk.pix_clk_div, &ret); > > + cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, > > + imx214->pll.vt_bk.sys_clk_div, &ret); > > + cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, > > + imx214->pll.vt_fr.pre_pll_clk_div, &ret); > > + cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, > > + imx214->pll.vt_fr.pll_multiplier, &ret); > > + cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, > > + imx214->pll.op_bk.pix_clk_div, &ret); > > + cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, > > + imx214->pll.op_bk.sys_clk_div, &ret); > > cci_write(imx214->regmap, IMX214_REG_PLL_MULT_DRIV, > > IMX214_PLL_SINGLE, &ret); > > cci_write(imx214->regmap, IMX214_REG_EXCK_FREQ, > > - IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / > > 1000000), &ret); > > + IMX214_EXCK_FREQ(imx214->pll.ext_clk_freq_hz / > > 1000000), &ret); > > > > return ret; > > } > > @@ -872,9 +884,6 @@ static const struct v4l2_ctrl_ops > > imx214_ctrl_ops = { > > > > static int imx214_ctrls_init(struct imx214 *imx214) > > { > > - static const s64 link_freq[] = { > > - IMX214_DEFAULT_LINK_FREQ > > - }; > > static const struct v4l2_area unit_size = { > > .width = 1120, > > .height = 1120, > > @@ -895,15 +904,14 @@ static int imx214_ctrls_init(struct imx214 > > *imx214) > > if (ret) > > return ret; > > > > - imx214->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL, > > - > > V4L2_CID_PIXEL_RATE, 0, > > - > > IMX214_DEFAULT_PIXEL_RATE, 1, > > - > > IMX214_DEFAULT_PIXEL_RATE); > > + imx214->pixel_rate = > > + v4l2_ctrl_new_std(ctrl_hdlr, NULL, > > V4L2_CID_PIXEL_RATE, 1, > > + INT_MAX, 1, 1); > > > > imx214->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, > > NULL, > > > > V4L2_CID_LINK_FREQ, > > - > > ARRAY_SIZE(link_freq) - 1, > > - 0, link_freq); > > + imx214- > > >bus_cfg.nr_of_link_frequencies - 1, > > + 0, imx214- > > >bus_cfg.link_frequencies); > > if (imx214->link_freq) > > imx214->link_freq->flags |= > > V4L2_CTRL_FLAG_READ_ONLY; > > > > @@ -1006,6 +1014,7 @@ static int imx214_start_streaming(struct > > imx214 *imx214) > > const struct v4l2_mbus_framefmt *fmt; > > struct v4l2_subdev_state *state; > > const struct imx214_mode *mode; > > + int bit_rate_mbps; > > int ret; > > > > ret = cci_multi_reg_write(imx214->regmap, > > mode_table_common, > > @@ -1021,8 +1030,10 @@ static int imx214_start_streaming(struct > > imx214 *imx214) > > return ret; > > } > > > > + bit_rate_mbps = (imx214->pll.pixel_rate_pixel_array / > > 1000000) > > + * imx214->pll.bits_per_pixel; > > ret = cci_write(imx214->regmap, > > IMX214_REG_REQ_LINK_BIT_RATE, > > - IMX214_LINK_BIT_RATE_MBPS(4800), NULL); > > + IMX214_LINK_BIT_RATE_MBPS(bit_rate_mbps), > > NULL); > > if (ret) { > > dev_err(imx214->dev, "failed to configure link bit > > rate\n"); > > return ret; > > @@ -1105,6 +1116,112 @@ static int imx214_s_stream(struct > > v4l2_subdev *subdev, int enable) > > return ret; > > } > > > > +static int imx214_pll_calculate(struct imx214 *imx214, struct > > ccs_pll *pll, > > + unsigned int link_freq) > > +{ > > + struct ccs_pll_limits limits = { > > + .min_ext_clk_freq_hz = 6000000, > > + .max_ext_clk_freq_hz = 27000000, > > + > > + .vt_fr = { > > + .min_pre_pll_clk_div = 1, > > + .max_pre_pll_clk_div = 15, > > + /* min_pll_op_clk_freq_hz / > > max_pll_multiplier */ > > + .min_pll_ip_clk_freq_hz = 281667, > > + /* max_pll_op_clk_freq_hz / > > min_pll_multiplier */ > > + .max_pll_ip_clk_freq_hz = 100000000, > > Regarding these limits -- the pll_ip_clk_freq_hz limits are likely > between around 6 MHz (lower limit) and between 12 MHz and 27 MHz. I'd > use 6 for lower and 12 for higher if they yield correct configuration > currently and loosen them up only if needed. The range 6-12 MHz seems to work. With the updated min/max values, the comments are no longer valid, should I just remove them or what alternative comments could be used? Best regards, André > > > + .min_pll_multiplier = 12, > > + .max_pll_multiplier = 1200, > > + .min_pll_op_clk_freq_hz = 338000000, > > + .max_pll_op_clk_freq_hz = 1200000000, > > + }, > > + .vt_bk = { > > + .min_sys_clk_div = 2, > > + .max_sys_clk_div = 4, > > + .min_pix_clk_div = 5, > > + .max_pix_clk_div = 10, > > + .min_pix_clk_freq_hz = 30000000, > > + .max_pix_clk_freq_hz = 120000000, > > + }, > > + .op_bk = { > > + .min_sys_clk_div = 1, > > + .max_sys_clk_div = 2, > > + .min_pix_clk_div = 6, > > + .max_pix_clk_div = 10, > > + .min_pix_clk_freq_hz = 30000000, > > + .max_pix_clk_freq_hz = 120000000, > > + }, > > + > > + .min_line_length_pck_bin = IMX214_PPL_DEFAULT, > > + .min_line_length_pck = IMX214_PPL_DEFAULT, > > + }; > > + unsigned int num_lanes = imx214- > > >bus_cfg.bus.mipi_csi2.num_data_lanes; > > + int ret; > > + > > + /* > > + * There are no documented constraints on the sys clock > > frequency, for > > + * either branch. Recover them based on the PLL output > > clock frequency > > + * and sys_clk_div limits on one hand, and the pix clock > > frequency and > > + * the pix_clk_div limits on the other hand. > > + */ > > + limits.vt_bk.min_sys_clk_freq_hz = > > + max(limits.vt_fr.min_pll_op_clk_freq_hz / > > limits.vt_bk.max_sys_clk_div, > > + limits.vt_bk.min_pix_clk_freq_hz * > > limits.vt_bk.min_pix_clk_div); > > + limits.vt_bk.max_sys_clk_freq_hz = > > + min(limits.vt_fr.max_pll_op_clk_freq_hz / > > limits.vt_bk.min_sys_clk_div, > > + limits.vt_bk.max_pix_clk_freq_hz * > > limits.vt_bk.max_pix_clk_div); > > + > > + limits.op_bk.min_sys_clk_freq_hz = > > + max(limits.vt_fr.min_pll_op_clk_freq_hz / > > limits.op_bk.max_sys_clk_div, > > + limits.op_bk.min_pix_clk_freq_hz * > > limits.op_bk.min_pix_clk_div); > > + limits.op_bk.max_sys_clk_freq_hz = > > + min(limits.vt_fr.max_pll_op_clk_freq_hz / > > limits.op_bk.min_sys_clk_div, > > + limits.op_bk.max_pix_clk_freq_hz * > > limits.op_bk.max_pix_clk_div); > > + > > + memset(pll, 0, sizeof(*pll)); > > + > > + pll->bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; > > + pll->op_lanes = num_lanes; > > + pll->vt_lanes = num_lanes; > > + pll->csi2.lanes = num_lanes; > > + > > + pll->binning_horizontal = 1; > > + pll->binning_vertical = 1; > > + pll->scale_m = 1; > > + pll->scale_n = 1; > > + pll->bits_per_pixel = > > + IMX214_CSI_DATA_FORMAT_RAW10 & > > IMX214_BITS_PER_PIXEL_MASK; > > + pll->flags = CCS_PLL_FLAG_LANE_SPEED_MODEL; > > + pll->link_freq = link_freq; > > + pll->ext_clk_freq_hz = clk_get_rate(imx214->xclk); > > + > > + ret = ccs_pll_calculate(imx214->dev, &limits, pll); > > + > > + return ret; > > You can drop ret here. > > > +} > > + > > +static int imx214_pll_update(struct imx214 *imx214) > > +{ > > + u64 link_freq; > > + int ret; > > + > > + link_freq = imx214->bus_cfg.link_frequencies[imx214- > > >link_freq->val]; > > + ret = imx214_pll_calculate(imx214, &imx214->pll, > > link_freq); > > + if (ret) { > > + dev_err(imx214->dev, "PLL calculations failed: > > %d\n", ret); > > + return ret; > > + } > > + > > + ret = v4l2_ctrl_s_ctrl_int64(imx214->pixel_rate, > > + imx214- > > >pll.pixel_rate_pixel_array); > > + if (ret) { > > + dev_err(imx214->dev, "failed to set pixel > > rate\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > static int imx214_get_frame_interval(struct v4l2_subdev *subdev, > > struct v4l2_subdev_state > > *sd_state, > > struct > > v4l2_subdev_frame_interval *fival) > > @@ -1211,12 +1328,10 @@ static int imx214_identify_module(struct > > imx214 *imx214) > > return 0; > > } > > > > -static int imx214_parse_fwnode(struct device *dev) > > +static int imx214_parse_fwnode(struct device *dev, struct imx214 > > *imx214) > > { > > + struct v4l2_fwnode_endpoint *bus_cfg = &imx214->bus_cfg; > > struct fwnode_handle *endpoint; > > - struct v4l2_fwnode_endpoint bus_cfg = { > > - .bus_type = V4L2_MBUS_CSI2_DPHY, > > - }; > > unsigned int i; > > int ret; > > > > @@ -1224,42 +1339,52 @@ static int imx214_parse_fwnode(struct > > device *dev) > > if (!endpoint) > > return dev_err_probe(dev, -EINVAL, "endpoint node > > not found\n"); > > > > - ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, > > &bus_cfg); > > + bus_cfg->bus_type = V4L2_MBUS_CSI2_DPHY; > > + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, bus_cfg); > > + fwnode_handle_put(endpoint); > > if (ret) { > > dev_err_probe(dev, ret, "parsing endpoint node > > failed\n"); > > - goto done; > > + goto error; > > } > > > > /* Check the number of MIPI CSI2 data lanes */ > > - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { > > + if (bus_cfg->bus.mipi_csi2.num_data_lanes != 4) { > > ret = dev_err_probe(dev, -EINVAL, > > "only 4 data lanes are > > currently supported\n"); > > - goto done; > > + goto error; > > } > > > > - if (bus_cfg.nr_of_link_frequencies != 1) > > + if (bus_cfg->nr_of_link_frequencies != 1) > > dev_warn(dev, "Only one link-frequency supported, > > please review your DT. Continuing anyway\n"); > > > > - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { > > - if (bus_cfg.link_frequencies[i] == > > IMX214_DEFAULT_LINK_FREQ) > > + for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) { > > + u64 freq = bus_cfg->link_frequencies[i]; > > + struct ccs_pll pll; > > + > > + if (!imx214_pll_calculate(imx214, &pll, freq)) > > break; > > - if (bus_cfg.link_frequencies[i] == > > - IMX214_DEFAULT_LINK_FREQ_LEGACY) { > > + if (freq == IMX214_DEFAULT_LINK_FREQ_LEGACY) { > > dev_warn(dev, > > "link-frequencies %d not > > supported, please review your DT. Continuing anyway\n", > > IMX214_DEFAULT_LINK_FREQ); > > + freq = IMX214_DEFAULT_LINK_FREQ; > > + if (imx214_pll_calculate(imx214, &pll, > > freq)) > > + continue; > > + bus_cfg->link_frequencies[i] = freq; > > break; > > } > > } > > > > - if (i == bus_cfg.nr_of_link_frequencies) > > + if (i == bus_cfg->nr_of_link_frequencies) > > ret = dev_err_probe(dev, -EINVAL, > > - "link-frequencies %d not > > supported, please review your DT\n", > > - IMX214_DEFAULT_LINK_FREQ); > > + "link-frequencies %lld not > > supported, please review your DT\n", > > + bus_cfg- > > >nr_of_link_frequencies ? > > + bus_cfg->link_frequencies[0] : > > 0); > > > > -done: > > - v4l2_fwnode_endpoint_free(&bus_cfg); > > - fwnode_handle_put(endpoint); > > + return 0; > > + > > +error: > > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > > return ret; > > } > > > > @@ -1299,7 +1424,7 @@ static int imx214_probe(struct i2c_client > > *client) > > return dev_err_probe(dev, PTR_ERR(imx214->regmap), > > "failed to initialize > > CCI\n"); > > > > - ret = imx214_parse_fwnode(dev); > > + ret = imx214_parse_fwnode(dev, imx214); > > if (ret) > > return ret; > > > > @@ -1310,7 +1435,9 @@ static int imx214_probe(struct i2c_client > > *client) > > * Enable power initially, to avoid warnings > > * from clk_disable on power_off > > */ > > - imx214_power_on(imx214->dev); > > + ret = imx214_power_on(imx214->dev); > > + if (ret < 0) > > + goto error_fwnode; > > > > ret = imx214_identify_module(imx214); > > if (ret) > > @@ -1341,6 +1468,12 @@ static int imx214_probe(struct i2c_client > > *client) > > pm_runtime_set_active(imx214->dev); > > pm_runtime_enable(imx214->dev); > > > > + ret = imx214_pll_update(imx214); > > + if (ret < 0) { > > + dev_err_probe(dev, ret, "failed to update PLL\n"); > > + goto error_subdev_cleanup; > > + } > > + > > ret = v4l2_async_register_subdev_sensor(&imx214->sd); > > if (ret < 0) { > > dev_err_probe(dev, ret, > > @@ -1366,6 +1499,9 @@ static int imx214_probe(struct i2c_client > > *client) > > error_power_off: > > imx214_power_off(imx214->dev); > > > > +error_fwnode: > > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > > + > > return ret; > > } > > > > @@ -1378,6 +1514,8 @@ static void imx214_remove(struct i2c_client > > *client) > > v4l2_subdev_cleanup(sd); > > media_entity_cleanup(&imx214->sd.entity); > > v4l2_ctrl_handler_free(&imx214->ctrls); > > + v4l2_fwnode_endpoint_free(&imx214->bus_cfg); > > + > > pm_runtime_disable(&client->dev); > > if (!pm_runtime_status_suspended(&client->dev)) { > > imx214_power_off(imx214->dev); > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator 2025-05-06 20:16 ` André Apitzsch @ 2025-05-06 20:53 ` Sakari Ailus 0 siblings, 0 replies; 16+ messages in thread From: Sakari Ailus @ 2025-05-06 20:53 UTC (permalink / raw) To: André Apitzsch Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, Ricardo Ribalda Hi André, On Tue, May 06, 2025 at 10:16:23PM +0200, André Apitzsch wrote: > Hi Sakari, > > thanks for the feedback. One question below. > > Am Dienstag, dem 06.05.2025 um 08:05 +0000 schrieb Sakari Ailus: > > Hi André, > > > > A few more comments below. > > > > On Mon, May 05, 2025 at 11:05:55PM +0200, André Apitzsch via B4 Relay > > wrote: > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > Calculate PLL parameters based on clock frequency and link > > > frequency. > > > > > > Acked-by: Ricardo Ribalda <ribalda@chromium.org> > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > --- > > > drivers/media/i2c/Kconfig | 1 + > > > drivers/media/i2c/imx214.c | 216 > > > +++++++++++++++++++++++++++++++++++++-------- > > > 2 files changed, 178 insertions(+), 39 deletions(-) > > > > > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > > > index > > > e576b213084d232e90b7e556a7a855a3bb95544c..c8e24c42e0c4ea169f1b6cdc4 > > > f2631234a51c7d9 100644 > > > --- a/drivers/media/i2c/Kconfig > > > +++ b/drivers/media/i2c/Kconfig > > > @@ -141,6 +141,7 @@ config VIDEO_IMX214 > > > depends on GPIOLIB > > > select REGMAP_I2C > > > select V4L2_CCI_I2C > > > + select VIDEO_CCS_PLL > > > help > > > This is a Video4Linux2 sensor driver for the Sony > > > IMX214 camera. > > > diff --git a/drivers/media/i2c/imx214.c > > > b/drivers/media/i2c/imx214.c > > > index > > > 3aca6ebb02d649c1b7f0b6a6049c1e3aa3d08951..9e9be47394ec768a5b34d44b0 > > > 6b5bbb0988da5a1 100644 > > > --- a/drivers/media/i2c/imx214.c > > > +++ b/drivers/media/i2c/imx214.c > > > @@ -20,6 +20,8 @@ > > > #include <media/v4l2-fwnode.h> > > > #include <media/v4l2-subdev.h> > > > > > > +#include "ccs-pll.h" > > > + > > > /* Chip ID */ > > > #define IMX214_REG_CHIP_ID CCI_REG16(0x0016) > > > #define IMX214_CHIP_ID 0x0214 > > > @@ -34,7 +36,6 @@ > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > /* Keep wrong link frequency for backward compatibility */ > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > -#define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * > > > 8LL) / 10) > > > #define IMX214_FPS 30 > > > > > > /* V-TIMING internal */ > > > @@ -84,6 +85,7 @@ > > > #define IMX214_CSI_DATA_FORMAT_RAW10 0x0A0A > > > #define IMX214_CSI_DATA_FORMAT_COMP6 0x0A06 > > > #define IMX214_CSI_DATA_FORMAT_COMP8 0x0A08 > > > +#define IMX214_BITS_PER_PIXEL_MASK 0xFF > > > > > > #define IMX214_REG_CSI_LANE_MODE CCI_REG8(0x0114) > > > #define IMX214_CSI_2_LANE_MODE 1 > > > @@ -249,6 +251,10 @@ struct imx214 { > > > struct clk *xclk; > > > struct regmap *regmap; > > > > > > + struct ccs_pll pll; > > > + > > > + struct v4l2_fwnode_endpoint bus_cfg; > > > + > > > struct v4l2_subdev sd; > > > struct media_pad pad; > > > > > > @@ -758,16 +764,22 @@ static int imx214_configure_pll(struct imx214 > > > *imx214) > > > { > > > int ret = 0; > > > > > > - cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, 5, &ret); > > > - cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, 2, &ret); > > > - cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, 3, > > > &ret); > > > - cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, 150, > > > &ret); > > > - cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, 10, > > > &ret); > > > - cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, 1, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_VTPXCK_DIV, > > > + imx214->pll.vt_bk.pix_clk_div, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_VTSYCK_DIV, > > > + imx214->pll.vt_bk.sys_clk_div, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_PREPLLCK_VT_DIV, > > > + imx214->pll.vt_fr.pre_pll_clk_div, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_PLL_VT_MPY, > > > + imx214->pll.vt_fr.pll_multiplier, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_OPPXCK_DIV, > > > + imx214->pll.op_bk.pix_clk_div, &ret); > > > + cci_write(imx214->regmap, IMX214_REG_OPSYCK_DIV, > > > + imx214->pll.op_bk.sys_clk_div, &ret); > > > cci_write(imx214->regmap, IMX214_REG_PLL_MULT_DRIV, > > > IMX214_PLL_SINGLE, &ret); > > > cci_write(imx214->regmap, IMX214_REG_EXCK_FREQ, > > > - IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / > > > 1000000), &ret); > > > + IMX214_EXCK_FREQ(imx214->pll.ext_clk_freq_hz / > > > 1000000), &ret); > > > > > > return ret; > > > } > > > @@ -872,9 +884,6 @@ static const struct v4l2_ctrl_ops > > > imx214_ctrl_ops = { > > > > > > static int imx214_ctrls_init(struct imx214 *imx214) > > > { > > > - static const s64 link_freq[] = { > > > - IMX214_DEFAULT_LINK_FREQ > > > - }; > > > static const struct v4l2_area unit_size = { > > > .width = 1120, > > > .height = 1120, > > > @@ -895,15 +904,14 @@ static int imx214_ctrls_init(struct imx214 > > > *imx214) > > > if (ret) > > > return ret; > > > > > > - imx214->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL, > > > - > > > V4L2_CID_PIXEL_RATE, 0, > > > - > > > IMX214_DEFAULT_PIXEL_RATE, 1, > > > - > > > IMX214_DEFAULT_PIXEL_RATE); > > > + imx214->pixel_rate = > > > + v4l2_ctrl_new_std(ctrl_hdlr, NULL, > > > V4L2_CID_PIXEL_RATE, 1, > > > + INT_MAX, 1, 1); > > > > > > imx214->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, > > > NULL, > > > > > > V4L2_CID_LINK_FREQ, > > > - > > > ARRAY_SIZE(link_freq) - 1, > > > - 0, link_freq); > > > + imx214- > > > >bus_cfg.nr_of_link_frequencies - 1, > > > + 0, imx214- > > > >bus_cfg.link_frequencies); > > > if (imx214->link_freq) > > > imx214->link_freq->flags |= > > > V4L2_CTRL_FLAG_READ_ONLY; > > > > > > @@ -1006,6 +1014,7 @@ static int imx214_start_streaming(struct > > > imx214 *imx214) > > > const struct v4l2_mbus_framefmt *fmt; > > > struct v4l2_subdev_state *state; > > > const struct imx214_mode *mode; > > > + int bit_rate_mbps; > > > int ret; > > > > > > ret = cci_multi_reg_write(imx214->regmap, > > > mode_table_common, > > > @@ -1021,8 +1030,10 @@ static int imx214_start_streaming(struct > > > imx214 *imx214) > > > return ret; > > > } > > > > > > + bit_rate_mbps = (imx214->pll.pixel_rate_pixel_array / You should btw. use pll.pixel_rate_csi here instead: this is on the link, not the pixel array. > > > 1000000) > > > + * imx214->pll.bits_per_pixel; > > > ret = cci_write(imx214->regmap, > > > IMX214_REG_REQ_LINK_BIT_RATE, > > > - IMX214_LINK_BIT_RATE_MBPS(4800), NULL); > > > + IMX214_LINK_BIT_RATE_MBPS(bit_rate_mbps), > > > NULL); > > > if (ret) { > > > dev_err(imx214->dev, "failed to configure link bit > > > rate\n"); > > > return ret; > > > @@ -1105,6 +1116,112 @@ static int imx214_s_stream(struct > > > v4l2_subdev *subdev, int enable) > > > return ret; > > > } > > > > > > +static int imx214_pll_calculate(struct imx214 *imx214, struct > > > ccs_pll *pll, > > > + unsigned int link_freq) > > > +{ > > > + struct ccs_pll_limits limits = { > > > + .min_ext_clk_freq_hz = 6000000, > > > + .max_ext_clk_freq_hz = 27000000, > > > + > > > + .vt_fr = { > > > + .min_pre_pll_clk_div = 1, > > > + .max_pre_pll_clk_div = 15, > > > + /* min_pll_op_clk_freq_hz / > > > max_pll_multiplier */ > > > + .min_pll_ip_clk_freq_hz = 281667, > > > + /* max_pll_op_clk_freq_hz / > > > min_pll_multiplier */ > > > + .max_pll_ip_clk_freq_hz = 100000000, > > > > Regarding these limits -- the pll_ip_clk_freq_hz limits are likely > > between around 6 MHz (lower limit) and between 12 MHz and 27 MHz. I'd > > use 6 for lower and 12 for higher if they yield correct configuration > > currently and loosen them up only if needed. > > The range 6-12 MHz seems to work. > With the updated min/max values, the comments are no longer valid, > should I just remove them or what alternative comments could be used? I'd still leave there the fact these are just educated guesses, not manufacturer-defined values. -- Regards, Sakari Ailus ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-05 21:05 [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies André Apitzsch via B4 Relay ` (2 preceding siblings ...) 2025-05-05 21:05 ` [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator André Apitzsch via B4 Relay @ 2025-05-05 21:05 ` André Apitzsch via B4 Relay 2025-05-06 8:24 ` Sakari Ailus 3 siblings, 1 reply; 16+ messages in thread From: André Apitzsch via B4 Relay @ 2025-05-05 21:05 UTC (permalink / raw) To: Ricardo Ribalda, Sakari Ailus, Mauro Carvalho Chehab Cc: ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, André Apitzsch From: André Apitzsch <git@apitzsch.eu> Instead rely on the rate set on the clock (using assigned-clock-rates etc.) Signed-off-by: André Apitzsch <git@apitzsch.eu> --- drivers/media/i2c/imx214.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -32,7 +32,6 @@ #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) -#define IMX214_DEFAULT_CLK_FREQ 24000000 #define IMX214_DEFAULT_LINK_FREQ 600000000 /* Keep wrong link frequency for backward compatibility */ #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(imx214->xclk), "failed to get xclk\n"); - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); - if (ret) - return dev_err_probe(dev, ret, - "failed to set xclk frequency\n"); - ret = imx214_get_regulators(dev, imx214); if (ret < 0) return dev_err_probe(dev, ret, "failed to get regulators\n"); -- 2.49.0 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-05 21:05 ` [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency André Apitzsch via B4 Relay @ 2025-05-06 8:24 ` Sakari Ailus 2025-05-14 6:46 ` André Apitzsch 2025-05-15 8:58 ` Laurent Pinchart 0 siblings, 2 replies; 16+ messages in thread From: Sakari Ailus @ 2025-05-06 8:24 UTC (permalink / raw) To: git Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, laurent.pinchart Hi André, On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay wrote: > From: André Apitzsch <git@apitzsch.eu> > > Instead rely on the rate set on the clock (using assigned-clock-rates > etc.) > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > --- > drivers/media/i2c/imx214.c | 6 ------ > 1 file changed, 6 deletions(-) > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > --- a/drivers/media/i2c/imx214.c > +++ b/drivers/media/i2c/imx214.c > @@ -32,7 +32,6 @@ > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > #define IMX214_DEFAULT_LINK_FREQ 600000000 > /* Keep wrong link frequency for backward compatibility */ > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > "failed to get xclk\n"); > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > - if (ret) > - return dev_err_probe(dev, ret, > - "failed to set xclk frequency\n"); > - Oops. I missed this is what the driver was doing already. Indeed, this is one of the historic sensor drivers that do set the frequency in DT systems. The driver never used the clock-frequency property and instead used a fixed frequency. Changing the behaviour now could be problematic. There are options here that I think we could do: 1) use your v1 patch (4) which uses "clock-frequency" if it exists and otherwise uses the default, fixed frequency or 2) set the frequency only if the "clock-frequency" property exists. The DT currently requires clock-frequency and the YAML conversion was done in 2020 whereas the driver is from 2018. If we do this, the clock-frequency should be deprecated (or even removed from bingings). I wonder what others think. Cc'd Laurent in any case. > ret = imx214_get_regulators(dev, imx214); > if (ret < 0) > return dev_err_probe(dev, ret, "failed to get regulators\n"); > -- Regards, Sakari Ailus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-06 8:24 ` Sakari Ailus @ 2025-05-14 6:46 ` André Apitzsch 2025-05-15 8:58 ` Laurent Pinchart 1 sibling, 0 replies; 16+ messages in thread From: André Apitzsch @ 2025-05-14 6:46 UTC (permalink / raw) To: Sakari Ailus Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel, laurent.pinchart Hello Sakari, Am Dienstag, dem 06.05.2025 um 08:24 +0000 schrieb Sakari Ailus: > Hi André, > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay > wrote: > > From: André Apitzsch <git@apitzsch.eu> > > > > Instead rely on the rate set on the clock (using assigned-clock- > > rates > > etc.) > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > --- > > drivers/media/i2c/imx214.c | 6 ------ > > 1 file changed, 6 deletions(-) > > > > diff --git a/drivers/media/i2c/imx214.c > > b/drivers/media/i2c/imx214.c > > index > > 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254 > > f1e0d14dc064423 100644 > > --- a/drivers/media/i2c/imx214.c > > +++ b/drivers/media/i2c/imx214.c > > @@ -32,7 +32,6 @@ > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > /* Keep wrong link frequency for backward compatibility */ > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client > > *client) > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > "failed to get xclk\n"); > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > - if (ret) > > - return dev_err_probe(dev, ret, > > - "failed to set xclk > > frequency\n"); > > - > > Oops. I missed this is what the driver was doing already. Indeed, > this is one of the historic sensor drivers that do set the frequency > in DT systems. > > The driver never used the clock-frequency property and instead used a > fixed frequency. Changing the behaviour now could be problematic. > > There are options here that I think we could do: > > 1) use your v1 patch (4) which uses "clock-frequency" if it exists > and otherwise uses the default, fixed frequency or > > 2) set the frequency only if the "clock-frequency" property exists. > The DT currently requires clock-frequency and the YAML conversion was > done in 2020 whereas the driver is from 2018. If we do this, the > clock-frequency should be deprecated (or even removed from bingings). > > I wonder what others think. Cc'd Laurent in any case. I would go with option 2 and add a patch which updates the bindings, i.e. which deprecates 'clock-frequency', to this series. Best regards, André > > > ret = imx214_get_regulators(dev, imx214); > > if (ret < 0) > > return dev_err_probe(dev, ret, "failed to get > > regulators\n"); > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-06 8:24 ` Sakari Ailus 2025-05-14 6:46 ` André Apitzsch @ 2025-05-15 8:58 ` Laurent Pinchart 2025-05-15 11:54 ` Sakari Ailus 1 sibling, 1 reply; 16+ messages in thread From: Laurent Pinchart @ 2025-05-15 8:58 UTC (permalink / raw) To: Sakari Ailus Cc: git, Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel Hi Sakari, On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay wrote: > > From: André Apitzsch <git@apitzsch.eu> > > > > Instead rely on the rate set on the clock (using assigned-clock-rates > > etc.) > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > --- > > drivers/media/i2c/imx214.c | 6 ------ > > 1 file changed, 6 deletions(-) > > > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > > --- a/drivers/media/i2c/imx214.c > > +++ b/drivers/media/i2c/imx214.c > > @@ -32,7 +32,6 @@ > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > /* Keep wrong link frequency for backward compatibility */ > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > "failed to get xclk\n"); > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > - if (ret) > > - return dev_err_probe(dev, ret, > > - "failed to set xclk frequency\n"); > > - > > Oops. I missed this is what the driver was doing already. Indeed, this is > one of the historic sensor drivers that do set the frequency in DT systems. > > The driver never used the clock-frequency property and instead used a fixed > frequency. Changing the behaviour now could be problematic. > > There are options here that I think we could do: > > 1) use your v1 patch (4) which uses "clock-frequency" if it exists and > otherwise uses the default, fixed frequency or > > 2) set the frequency only if the "clock-frequency" property exists. The DT > currently requires clock-frequency and the YAML conversion was done in 2020 > whereas the driver is from 2018. If we do this, the clock-frequency should > be deprecated (or even removed from bingings). > > I wonder what others think. Cc'd Laurent in any case. Maybe I'm missing something, but I don't really see the issue here. The clock-frequency DT property is currently ignored, and this patch doesn't change that situation, does it ? The change of behaviour here is related to the assigned-clock-rates property. If that property is specified today, it will set the clock rate, and the driver will override it to 24MHz right after. With this patch, the clock rate won't be overridden. I think the risk of regression is very low here, as I don't expect systems to set assigned-clock-rates in DT to a value different than 24MHz and expect the driver to override it. > > ret = imx214_get_regulators(dev, imx214); > > if (ret < 0) > > return dev_err_probe(dev, ret, "failed to get regulators\n"); -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-15 8:58 ` Laurent Pinchart @ 2025-05-15 11:54 ` Sakari Ailus 2025-05-15 13:03 ` Laurent Pinchart 0 siblings, 1 reply; 16+ messages in thread From: Sakari Ailus @ 2025-05-15 11:54 UTC (permalink / raw) To: Laurent Pinchart Cc: git, Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel Hi Laurent, On Thu, May 15, 2025 at 10:58:46AM +0200, Laurent Pinchart wrote: > Hi Sakari, > > On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay wrote: > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > Instead rely on the rate set on the clock (using assigned-clock-rates > > > etc.) > > > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > --- > > > drivers/media/i2c/imx214.c | 6 ------ > > > 1 file changed, 6 deletions(-) > > > > > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > > > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > > > --- a/drivers/media/i2c/imx214.c > > > +++ b/drivers/media/i2c/imx214.c > > > @@ -32,7 +32,6 @@ > > > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > /* Keep wrong link frequency for backward compatibility */ > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > > "failed to get xclk\n"); > > > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > > - if (ret) > > > - return dev_err_probe(dev, ret, > > > - "failed to set xclk frequency\n"); > > > - > > > > Oops. I missed this is what the driver was doing already. Indeed, this is > > one of the historic sensor drivers that do set the frequency in DT systems. > > > > The driver never used the clock-frequency property and instead used a fixed > > frequency. Changing the behaviour now could be problematic. > > > > There are options here that I think we could do: > > > > 1) use your v1 patch (4) which uses "clock-frequency" if it exists and > > otherwise uses the default, fixed frequency or > > > > 2) set the frequency only if the "clock-frequency" property exists. The DT > > currently requires clock-frequency and the YAML conversion was done in 2020 > > whereas the driver is from 2018. If we do this, the clock-frequency should > > be deprecated (or even removed from bingings). > > > > I wonder what others think. Cc'd Laurent in any case. > > Maybe I'm missing something, but I don't really see the issue here. The > clock-frequency DT property is currently ignored, and this patch doesn't > change that situation, does it ? > > The change of behaviour here is related to the assigned-clock-rates > property. If that property is specified today, it will set the clock > rate, and the driver will override it to 24MHz right after. With this > patch, the clock rate won't be overridden. I think the risk of > regression is very low here, as I don't expect systems to set > assigned-clock-rates in DT to a value different than 24MHz and expect > the driver to override it. If the DTS had assigned-clock-rates set correctly, then yes. How much can we trust the older DTS did have that? -- Regards, Sakari Ailus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-15 11:54 ` Sakari Ailus @ 2025-05-15 13:03 ` Laurent Pinchart 2025-05-15 21:02 ` Sakari Ailus 0 siblings, 1 reply; 16+ messages in thread From: Laurent Pinchart @ 2025-05-15 13:03 UTC (permalink / raw) To: Sakari Ailus Cc: git, Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel On Thu, May 15, 2025 at 02:54:54PM +0300, Sakari Ailus wrote: > On Thu, May 15, 2025 at 10:58:46AM +0200, Laurent Pinchart wrote: > > On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay wrote: > > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > > > Instead rely on the rate set on the clock (using assigned-clock-rates > > > > etc.) > > > > > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > > --- > > > > drivers/media/i2c/imx214.c | 6 ------ > > > > 1 file changed, 6 deletions(-) > > > > > > > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > > > > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > > > > --- a/drivers/media/i2c/imx214.c > > > > +++ b/drivers/media/i2c/imx214.c > > > > @@ -32,7 +32,6 @@ > > > > > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > > /* Keep wrong link frequency for backward compatibility */ > > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > > > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > > > "failed to get xclk\n"); > > > > > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > > > - if (ret) > > > > - return dev_err_probe(dev, ret, > > > > - "failed to set xclk frequency\n"); > > > > - > > > > > > Oops. I missed this is what the driver was doing already. Indeed, this is > > > one of the historic sensor drivers that do set the frequency in DT systems. > > > > > > The driver never used the clock-frequency property and instead used a fixed > > > frequency. Changing the behaviour now could be problematic. > > > > > > There are options here that I think we could do: > > > > > > 1) use your v1 patch (4) which uses "clock-frequency" if it exists and > > > otherwise uses the default, fixed frequency or > > > > > > 2) set the frequency only if the "clock-frequency" property exists. The DT > > > currently requires clock-frequency and the YAML conversion was done in 2020 > > > whereas the driver is from 2018. If we do this, the clock-frequency should > > > be deprecated (or even removed from bingings). > > > > > > I wonder what others think. Cc'd Laurent in any case. > > > > Maybe I'm missing something, but I don't really see the issue here. The > > clock-frequency DT property is currently ignored, and this patch doesn't > > change that situation, does it ? > > > > The change of behaviour here is related to the assigned-clock-rates > > property. If that property is specified today, it will set the clock > > rate, and the driver will override it to 24MHz right after. With this > > patch, the clock rate won't be overridden. I think the risk of > > regression is very low here, as I don't expect systems to set > > assigned-clock-rates in DT to a value different than 24MHz and expect > > the driver to override it. > > If the DTS had assigned-clock-rates set correctly, then yes. How much can > we trust the older DTS did have that? I am relatively confident that DT-based systems wouldn't have an assigned-clock-rates property with a frequency that doesn't match IMX214_DEFAULT_CLK_FREQ. The real question is whether or not I'm over-confident :-) -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-15 13:03 ` Laurent Pinchart @ 2025-05-15 21:02 ` Sakari Ailus 2025-05-15 21:21 ` André Apitzsch 0 siblings, 1 reply; 16+ messages in thread From: Sakari Ailus @ 2025-05-15 21:02 UTC (permalink / raw) To: Laurent Pinchart Cc: git, Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel Hi Laurent, On Thu, May 15, 2025 at 03:03:40PM +0200, Laurent Pinchart wrote: > On Thu, May 15, 2025 at 02:54:54PM +0300, Sakari Ailus wrote: > > On Thu, May 15, 2025 at 10:58:46AM +0200, Laurent Pinchart wrote: > > > On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > > > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via B4 Relay wrote: > > > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > > > > > Instead rely on the rate set on the clock (using assigned-clock-rates > > > > > etc.) > > > > > > > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > > > --- > > > > > drivers/media/i2c/imx214.c | 6 ------ > > > > > 1 file changed, 6 deletions(-) > > > > > > > > > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > > > > > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > > > > > --- a/drivers/media/i2c/imx214.c > > > > > +++ b/drivers/media/i2c/imx214.c > > > > > @@ -32,7 +32,6 @@ > > > > > > > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > > > > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > > > /* Keep wrong link frequency for backward compatibility */ > > > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > > > > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > > > > "failed to get xclk\n"); > > > > > > > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > > > > - if (ret) > > > > > - return dev_err_probe(dev, ret, > > > > > - "failed to set xclk frequency\n"); > > > > > - > > > > > > > > Oops. I missed this is what the driver was doing already. Indeed, this is > > > > one of the historic sensor drivers that do set the frequency in DT systems. > > > > > > > > The driver never used the clock-frequency property and instead used a fixed > > > > frequency. Changing the behaviour now could be problematic. > > > > > > > > There are options here that I think we could do: > > > > > > > > 1) use your v1 patch (4) which uses "clock-frequency" if it exists and > > > > otherwise uses the default, fixed frequency or > > > > > > > > 2) set the frequency only if the "clock-frequency" property exists. The DT > > > > currently requires clock-frequency and the YAML conversion was done in 2020 > > > > whereas the driver is from 2018. If we do this, the clock-frequency should > > > > be deprecated (or even removed from bingings). > > > > > > > > I wonder what others think. Cc'd Laurent in any case. > > > > > > Maybe I'm missing something, but I don't really see the issue here. The > > > clock-frequency DT property is currently ignored, and this patch doesn't > > > change that situation, does it ? > > > > > > The change of behaviour here is related to the assigned-clock-rates > > > property. If that property is specified today, it will set the clock > > > rate, and the driver will override it to 24MHz right after. With this > > > patch, the clock rate won't be overridden. I think the risk of > > > regression is very low here, as I don't expect systems to set > > > assigned-clock-rates in DT to a value different than 24MHz and expect > > > the driver to override it. > > > > If the DTS had assigned-clock-rates set correctly, then yes. How much can > > we trust the older DTS did have that? > > I am relatively confident that DT-based systems wouldn't have an > assigned-clock-rates property with a frequency that doesn't match > IMX214_DEFAULT_CLK_FREQ. The real question is whether or not I'm > over-confident :-) The assigned-clock stuff wasn't always there. But nowadays I guess a lot of things in practice depends on it. So I guess doing this should be fine then. -- Sakari Ailus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-15 21:02 ` Sakari Ailus @ 2025-05-15 21:21 ` André Apitzsch 2025-05-21 16:50 ` Laurent Pinchart 0 siblings, 1 reply; 16+ messages in thread From: André Apitzsch @ 2025-05-15 21:21 UTC (permalink / raw) To: Sakari Ailus, Laurent Pinchart Cc: Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel Hi Sakari, Hi Laurent, Am Freitag, dem 16.05.2025 um 00:02 +0300 schrieb Sakari Ailus: > Hi Laurent, > > On Thu, May 15, 2025 at 03:03:40PM +0200, Laurent Pinchart wrote: > > On Thu, May 15, 2025 at 02:54:54PM +0300, Sakari Ailus wrote: > > > On Thu, May 15, 2025 at 10:58:46AM +0200, Laurent Pinchart wrote: > > > > On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > > > > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via > > > > > B4 Relay wrote: > > > > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > > > > > > > Instead rely on the rate set on the clock (using assigned- > > > > > > clock-rates > > > > > > etc.) > > > > > > > > > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > > > > --- > > > > > > drivers/media/i2c/imx214.c | 6 ------ > > > > > > 1 file changed, 6 deletions(-) > > > > > > > > > > > > diff --git a/drivers/media/i2c/imx214.c > > > > > > b/drivers/media/i2c/imx214.c > > > > > > index > > > > > > 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb1 > > > > > > 8c608254f1e0d14dc064423 100644 > > > > > > --- a/drivers/media/i2c/imx214.c > > > > > > +++ b/drivers/media/i2c/imx214.c > > > > > > @@ -32,7 +32,6 @@ > > > > > > > > > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > > > > > > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > > > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > > > > /* Keep wrong link frequency for backward compatibility */ > > > > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > > > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct > > > > > > i2c_client *client) > > > > > > return dev_err_probe(dev, PTR_ERR(imx214- > > > > > > >xclk), > > > > > > "failed to get > > > > > > xclk\n"); > > > > > > > > > > > > - ret = clk_set_rate(imx214->xclk, > > > > > > IMX214_DEFAULT_CLK_FREQ); > > > > > > - if (ret) > > > > > > - return dev_err_probe(dev, ret, > > > > > > - "failed to set xclk > > > > > > frequency\n"); > > > > > > - > > > > > > > > > > Oops. I missed this is what the driver was doing already. > > > > > Indeed, this is one of the historic sensor drivers that do > > > > > set the frequency in DT systems. > > > > > > > > > > The driver never used the clock-frequency property and > > > > > instead used a fixed frequency. Changing the behaviour now > > > > > could be problematic. > > > > > > > > > > There are options here that I think we could do: > > > > > > > > > > 1) use your v1 patch (4) which uses "clock-frequency" if it > > > > > exists and otherwise uses the default, fixed frequency or > > > > > > > > > > 2) set the frequency only if the "clock-frequency" property > > > > > exists. The DT currently requires clock-frequency and the > > > > > YAML conversion was done in 2020 whereas the driver is from > > > > > 2018. If we do this, the clock-frequency should > > > > > be deprecated (or even removed from bingings). > > > > > > > > > > I wonder what others think. Cc'd Laurent in any case. > > > > > > > > Maybe I'm missing something, but I don't really see the issue > > > > here. The clock-frequency DT property is currently ignored, and > > > > this patch doesn't change that situation, does it ? > > > > > > > > The change of behaviour here is related to the assigned-clock- > > > > rates property. If that property is specified today, it will > > > > set the clock rate, and the driver will override it to 24MHz > > > > right after. > > > > With this patch, the clock rate won't be overridden. I think > > > > the risk of regression is very low here, as I don't expect > > > > systems to set assigned-clock-rates in DT to a value different > > > > than 24MHz and expect the driver to override it. > > > > > > If the DTS had assigned-clock-rates set correctly, then yes. How > > > much can we trust the older DTS did have that? > > > > I am relatively confident that DT-based systems wouldn't have an > > assigned-clock-rates property with a frequency that doesn't match > > IMX214_DEFAULT_CLK_FREQ. The real question is whether or not I'm > > over-confident :-) > > The assigned-clock stuff wasn't always there. But nowadays I guess a > lot of things in practice depends on it. > > So I guess doing this should be fine then. Just to be clear, this patch is fine and no changes are needed? Should the bindings be updated in this series or can that be done later? Best regards, André ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency 2025-05-15 21:21 ` André Apitzsch @ 2025-05-21 16:50 ` Laurent Pinchart 0 siblings, 0 replies; 16+ messages in thread From: Laurent Pinchart @ 2025-05-21 16:50 UTC (permalink / raw) To: André Apitzsch Cc: Sakari Ailus, Ricardo Ribalda, Mauro Carvalho Chehab, ~postmarketos/upstreaming, phone-devel, linux-media, linux-kernel Hi André, On Thu, May 15, 2025 at 11:21:42PM +0200, André Apitzsch wrote: > Am Freitag, dem 16.05.2025 um 00:02 +0300 schrieb Sakari Ailus: > > On Thu, May 15, 2025 at 03:03:40PM +0200, Laurent Pinchart wrote: > > > On Thu, May 15, 2025 at 02:54:54PM +0300, Sakari Ailus wrote: > > > > On Thu, May 15, 2025 at 10:58:46AM +0200, Laurent Pinchart wrote: > > > > > On Tue, May 06, 2025 at 08:24:03AM +0000, Sakari Ailus wrote: > > > > > > On Mon, May 05, 2025 at 11:05:56PM +0200, André Apitzsch via > > > > > > B4 Relay wrote: > > > > > > > From: André Apitzsch <git@apitzsch.eu> > > > > > > > > > > > > > > Instead rely on the rate set on the clock (using assigned-clock-rates > > > > > > > etc.) > > > > > > > > > > > > > > Signed-off-by: André Apitzsch <git@apitzsch.eu> > > > > > > > --- > > > > > > > drivers/media/i2c/imx214.c | 6 ------ > > > > > > > 1 file changed, 6 deletions(-) > > > > > > > > > > > > > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > > > > > > > index 9e9be47394ec768a5b34d44b06b5bbb0988da5a1..c12996e294dccebb18c608254f1e0d14dc064423 100644 > > > > > > > --- a/drivers/media/i2c/imx214.c > > > > > > > +++ b/drivers/media/i2c/imx214.c > > > > > > > @@ -32,7 +32,6 @@ > > > > > > > > > > > > > > #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106) > > > > > > > > > > > > > > -#define IMX214_DEFAULT_CLK_FREQ 24000000 > > > > > > > #define IMX214_DEFAULT_LINK_FREQ 600000000 > > > > > > > /* Keep wrong link frequency for backward compatibility */ > > > > > > > #define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000 > > > > > > > @@ -1405,11 +1404,6 @@ static int imx214_probe(struct i2c_client *client) > > > > > > > return dev_err_probe(dev, PTR_ERR(imx214->xclk), > > > > > > > "failed to get xclk\n"); > > > > > > > > > > > > > > - ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ); > > > > > > > - if (ret) > > > > > > > - return dev_err_probe(dev, ret, > > > > > > > - "failed to set xclk frequency\n"); > > > > > > > - > > > > > > > > > > > > Oops. I missed this is what the driver was doing already. > > > > > > Indeed, this is one of the historic sensor drivers that do > > > > > > set the frequency in DT systems. > > > > > > > > > > > > The driver never used the clock-frequency property and > > > > > > instead used a fixed frequency. Changing the behaviour now > > > > > > could be problematic. > > > > > > > > > > > > There are options here that I think we could do: > > > > > > > > > > > > 1) use your v1 patch (4) which uses "clock-frequency" if it > > > > > > exists and otherwise uses the default, fixed frequency or > > > > > > > > > > > > 2) set the frequency only if the "clock-frequency" property > > > > > > exists. The DT currently requires clock-frequency and the > > > > > > YAML conversion was done in 2020 whereas the driver is from > > > > > > 2018. If we do this, the clock-frequency should > > > > > > be deprecated (or even removed from bingings). > > > > > > > > > > > > I wonder what others think. Cc'd Laurent in any case. > > > > > > > > > > Maybe I'm missing something, but I don't really see the issue > > > > > here. The clock-frequency DT property is currently ignored, and > > > > > this patch doesn't change that situation, does it ? > > > > > > > > > > The change of behaviour here is related to the assigned-clock- > > > > > rates property. If that property is specified today, it will > > > > > set the clock rate, and the driver will override it to 24MHz > > > > > right after. > > > > > With this patch, the clock rate won't be overridden. I think > > > > > the risk of regression is very low here, as I don't expect > > > > > systems to set assigned-clock-rates in DT to a value different > > > > > than 24MHz and expect the driver to override it. > > > > > > > > If the DTS had assigned-clock-rates set correctly, then yes. How > > > > much can we trust the older DTS did have that? > > > > > > I am relatively confident that DT-based systems wouldn't have an > > > assigned-clock-rates property with a frequency that doesn't match > > > IMX214_DEFAULT_CLK_FREQ. The real question is whether or not I'm > > > over-confident :-) > > > > The assigned-clock stuff wasn't always there. But nowadays I guess a > > lot of things in practice depends on it. > > > > So I guess doing this should be fine then. > > Just to be clear, this patch is fine and no changes are needed? I'm fine with it. > Should the bindings be updated in this series or can that be done > later? If you could do it in the same series it would be very appreciated. It should be in a separate patch. -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-05-21 16:50 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-05 21:05 [PATCH v2 0/4] media: i2c: imx214: Add support for more clock frequencies André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 1/4] media: i2c: imx214: Reorder imx214_parse_fwnode call André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 2/4] media: i2c: imx214: Prepare for variable clock frequency André Apitzsch via B4 Relay 2025-05-05 21:05 ` [PATCH v2 3/4] media: i2c: imx214: Make use of CCS PLL calculator André Apitzsch via B4 Relay 2025-05-06 8:05 ` Sakari Ailus 2025-05-06 20:16 ` André Apitzsch 2025-05-06 20:53 ` Sakari Ailus 2025-05-05 21:05 ` [PATCH v2 4/4] media: i2c: imx214: Remove hard-coded external clock frequency André Apitzsch via B4 Relay 2025-05-06 8:24 ` Sakari Ailus 2025-05-14 6:46 ` André Apitzsch 2025-05-15 8:58 ` Laurent Pinchart 2025-05-15 11:54 ` Sakari Ailus 2025-05-15 13:03 ` Laurent Pinchart 2025-05-15 21:02 ` Sakari Ailus 2025-05-15 21:21 ` André Apitzsch 2025-05-21 16:50 ` Laurent Pinchart
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).