Message ID | 20250324-probe_fixes-v1-5-5cd5b9e1cfac@ideasonboard.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | media: ti, cdns: Multiple pixel support and misc fixes | expand |
Hi Jai, kernel test robot noticed the following build errors: [auto build test ERROR on 586de92313fcab8ed84ac5f78f4d2aae2db92c59] url: https://github.com/intel-lab-lkp/linux/commits/Jai-Luthra/media-ti-j721e-csi2rx-Use-devm_of_platform_populate/20250324-200457 base: 586de92313fcab8ed84ac5f78f4d2aae2db92c59 patch link: https://lore.kernel.org/r/20250324-probe_fixes-v1-5-5cd5b9e1cfac%40ideasonboard.com patch subject: [PATCH 5/6] media: cadence: cdns-csi2rx: Support multiple pixels per clock cycle config: hexagon-randconfig-001-20250324 (https://download.01.org/0day-ci/archive/20250324/202503242153.Yn1DfnS5-lkp@intel.com/config) compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project c2692afc0a92cd5da140dfcdfff7818a5b8ce997) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250324/202503242153.Yn1DfnS5-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202503242153.Yn1DfnS5-lkp@intel.com/ All errors (new ones prefixed by >>): >> drivers/media/platform/cadence/cdns-csi2rx.c:286:10: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 286 | reg |= FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, | ^ 1 error generated. vim +/FIELD_PREP +286 drivers/media/platform/cadence/cdns-csi2rx.c 214 215 static int csi2rx_start(struct csi2rx_priv *csi2rx) 216 { 217 unsigned int i; 218 unsigned long lanes_used = 0; 219 u32 reg; 220 int ret; 221 222 ret = clk_prepare_enable(csi2rx->p_clk); 223 if (ret) 224 return ret; 225 226 reset_control_deassert(csi2rx->p_rst); 227 csi2rx_reset(csi2rx); 228 229 reg = csi2rx->num_lanes << 8; 230 for (i = 0; i < csi2rx->num_lanes; i++) { 231 reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, csi2rx->lanes[i]); 232 set_bit(csi2rx->lanes[i], &lanes_used); 233 } 234 235 /* 236 * Even the unused lanes need to be mapped. In order to avoid 237 * to map twice to the same physical lane, keep the lanes used 238 * in the previous loop, and only map unused physical lanes to 239 * the rest of our logical lanes. 240 */ 241 for (i = csi2rx->num_lanes; i < csi2rx->max_lanes; i++) { 242 unsigned int idx = find_first_zero_bit(&lanes_used, 243 csi2rx->max_lanes); 244 set_bit(idx, &lanes_used); 245 reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, i + 1); 246 } 247 248 writel(reg, csi2rx->base + CSI2RX_STATIC_CFG_REG); 249 250 /* Enable DPHY clk and data lanes. */ 251 if (csi2rx->dphy) { 252 reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST; 253 for (i = 0; i < csi2rx->num_lanes; i++) { 254 reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1); 255 reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1); 256 } 257 258 writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); 259 260 ret = csi2rx_configure_ext_dphy(csi2rx); 261 if (ret) { 262 dev_err(csi2rx->dev, 263 "Failed to configure external DPHY: %d\n", ret); 264 goto err_disable_pclk; 265 } 266 } 267 268 /* 269 * Create a static mapping between the CSI virtual channels 270 * and the output stream. 271 * 272 * This should be enhanced, but v4l2 lacks the support for 273 * changing that mapping dynamically. 274 * 275 * We also cannot enable and disable independent streams here, 276 * hence the reference counting. 277 */ 278 for (i = 0; i < csi2rx->max_streams; i++) { 279 ret = clk_prepare_enable(csi2rx->pixel_clk[i]); 280 if (ret) 281 goto err_disable_pixclk; 282 283 reset_control_deassert(csi2rx->pixel_rst[i]); 284 285 reg = CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF; > 286 reg |= FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, 287 csi2rx->num_pixels[i]); 288 writel(reg, csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); 289 290 /* 291 * Enable one virtual channel. When multiple virtual channels 292 * are supported this will have to be changed. 293 */ 294 writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0), 295 csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i)); 296 297 writel(CSI2RX_STREAM_CTRL_START, 298 csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); 299 } 300 301 ret = clk_prepare_enable(csi2rx->sys_clk); 302 if (ret) 303 goto err_disable_pixclk; 304 305 reset_control_deassert(csi2rx->sys_rst); 306 307 ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true); 308 if (ret) 309 goto err_disable_sysclk; 310 311 clk_disable_unprepare(csi2rx->p_clk); 312 313 return 0; 314 315 err_disable_sysclk: 316 clk_disable_unprepare(csi2rx->sys_clk); 317 err_disable_pixclk: 318 for (; i > 0; i--) { 319 reset_control_assert(csi2rx->pixel_rst[i - 1]); 320 clk_disable_unprepare(csi2rx->pixel_clk[i - 1]); 321 } 322 323 if (csi2rx->dphy) { 324 writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); 325 phy_power_off(csi2rx->dphy); 326 } 327 err_disable_pclk: 328 clk_disable_unprepare(csi2rx->p_clk); 329 330 return ret; 331 } 332
Hi Jai, kernel test robot noticed the following build errors: [auto build test ERROR on 586de92313fcab8ed84ac5f78f4d2aae2db92c59] url: https://github.com/intel-lab-lkp/linux/commits/Jai-Luthra/media-ti-j721e-csi2rx-Use-devm_of_platform_populate/20250324-200457 base: 586de92313fcab8ed84ac5f78f4d2aae2db92c59 patch link: https://lore.kernel.org/r/20250324-probe_fixes-v1-5-5cd5b9e1cfac%40ideasonboard.com patch subject: [PATCH 5/6] media: cadence: cdns-csi2rx: Support multiple pixels per clock cycle config: sparc-randconfig-002-20250324 (https://download.01.org/0day-ci/archive/20250325/202503250056.MfBrAipQ-lkp@intel.com/config) compiler: sparc64-linux-gcc (GCC) 11.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250325/202503250056.MfBrAipQ-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202503250056.MfBrAipQ-lkp@intel.com/ All errors (new ones prefixed by >>): drivers/media/platform/cadence/cdns-csi2rx.c: In function 'csi2rx_start': >> drivers/media/platform/cadence/cdns-csi2rx.c:286:24: error: implicit declaration of function 'FIELD_PREP' [-Werror=implicit-function-declaration] 286 | reg |= FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, | ^~~~~~~~~~ cc1: some warnings being treated as errors vim +/FIELD_PREP +286 drivers/media/platform/cadence/cdns-csi2rx.c 214 215 static int csi2rx_start(struct csi2rx_priv *csi2rx) 216 { 217 unsigned int i; 218 unsigned long lanes_used = 0; 219 u32 reg; 220 int ret; 221 222 ret = clk_prepare_enable(csi2rx->p_clk); 223 if (ret) 224 return ret; 225 226 reset_control_deassert(csi2rx->p_rst); 227 csi2rx_reset(csi2rx); 228 229 reg = csi2rx->num_lanes << 8; 230 for (i = 0; i < csi2rx->num_lanes; i++) { 231 reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, csi2rx->lanes[i]); 232 set_bit(csi2rx->lanes[i], &lanes_used); 233 } 234 235 /* 236 * Even the unused lanes need to be mapped. In order to avoid 237 * to map twice to the same physical lane, keep the lanes used 238 * in the previous loop, and only map unused physical lanes to 239 * the rest of our logical lanes. 240 */ 241 for (i = csi2rx->num_lanes; i < csi2rx->max_lanes; i++) { 242 unsigned int idx = find_first_zero_bit(&lanes_used, 243 csi2rx->max_lanes); 244 set_bit(idx, &lanes_used); 245 reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, i + 1); 246 } 247 248 writel(reg, csi2rx->base + CSI2RX_STATIC_CFG_REG); 249 250 /* Enable DPHY clk and data lanes. */ 251 if (csi2rx->dphy) { 252 reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST; 253 for (i = 0; i < csi2rx->num_lanes; i++) { 254 reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1); 255 reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1); 256 } 257 258 writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); 259 260 ret = csi2rx_configure_ext_dphy(csi2rx); 261 if (ret) { 262 dev_err(csi2rx->dev, 263 "Failed to configure external DPHY: %d\n", ret); 264 goto err_disable_pclk; 265 } 266 } 267 268 /* 269 * Create a static mapping between the CSI virtual channels 270 * and the output stream. 271 * 272 * This should be enhanced, but v4l2 lacks the support for 273 * changing that mapping dynamically. 274 * 275 * We also cannot enable and disable independent streams here, 276 * hence the reference counting. 277 */ 278 for (i = 0; i < csi2rx->max_streams; i++) { 279 ret = clk_prepare_enable(csi2rx->pixel_clk[i]); 280 if (ret) 281 goto err_disable_pixclk; 282 283 reset_control_deassert(csi2rx->pixel_rst[i]); 284 285 reg = CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF; > 286 reg |= FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, 287 csi2rx->num_pixels[i]); 288 writel(reg, csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); 289 290 /* 291 * Enable one virtual channel. When multiple virtual channels 292 * are supported this will have to be changed. 293 */ 294 writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0), 295 csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i)); 296 297 writel(CSI2RX_STREAM_CTRL_START, 298 csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); 299 } 300 301 ret = clk_prepare_enable(csi2rx->sys_clk); 302 if (ret) 303 goto err_disable_pixclk; 304 305 reset_control_deassert(csi2rx->sys_rst); 306 307 ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true); 308 if (ret) 309 goto err_disable_sysclk; 310 311 clk_disable_unprepare(csi2rx->p_clk); 312 313 return 0; 314 315 err_disable_sysclk: 316 clk_disable_unprepare(csi2rx->sys_clk); 317 err_disable_pixclk: 318 for (; i > 0; i--) { 319 reset_control_assert(csi2rx->pixel_rst[i - 1]); 320 clk_disable_unprepare(csi2rx->pixel_clk[i - 1]); 321 } 322 323 if (csi2rx->dphy) { 324 writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); 325 phy_power_off(csi2rx->dphy); 326 } 327 err_disable_pclk: 328 clk_disable_unprepare(csi2rx->p_clk); 329 330 return ret; 331 } 332
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index b489967563cde96ac109c44a665b30e573125721..e394afe954fcdb7219dfd14df7a82e8e19cbd572 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -22,6 +22,8 @@ #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> +#include "cdns-csi2rx.h" + #define CSI2RX_DEVICE_CFG_REG 0x000 #define CSI2RX_SOFT_RESET_REG 0x004 @@ -53,6 +55,8 @@ #define CSI2RX_STREAM_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x00c) #define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF (1 << 8) +#define CSI2RX_STREAM_CFG_NUM_PIXELS_MASK GENMASK(5, 4) +#define CSI2RX_STREAM_CFG_NUM_PIXELS(n) ((n) >> 1) #define CSI2RX_LANES_MAX 4 #define CSI2RX_STREAMS_MAX 4 @@ -68,7 +72,10 @@ enum csi2rx_pads { struct csi2rx_fmt { u32 code; + /* width of a single pixel on CSI-2 bus */ u8 bpp; + /* max pixels per clock supported on output bus */ + u8 max_pixels; }; struct csi2rx_priv { @@ -90,6 +97,7 @@ struct csi2rx_priv { struct reset_control *pixel_rst[CSI2RX_STREAMS_MAX]; struct phy *dphy; + u8 num_pixels[CSI2RX_STREAMS_MAX]; u8 lanes[CSI2RX_LANES_MAX]; u8 num_lanes; u8 max_lanes; @@ -106,22 +114,22 @@ struct csi2rx_priv { }; static const struct csi2rx_fmt formats[] = { - { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, }, - { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, }, + { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, .max_pixels = 1, }, }; static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code) @@ -274,8 +282,10 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) reset_control_deassert(csi2rx->pixel_rst[i]); - writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF, - csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); + reg = CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF; + reg |= FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, + csi2rx->num_pixels[i]); + writel(reg, csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); /* * Enable one virtual channel. When multiple virtual channels @@ -456,6 +466,34 @@ static int csi2rx_init_state(struct v4l2_subdev *subdev, return csi2rx_set_fmt(subdev, state, &format); } +int cdns_csi2rx_negotiate_ppc(struct v4l2_subdev *subdev, unsigned int pad, + u8 *ppc) +{ + struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev); + const struct csi2rx_fmt *csi_fmt; + struct v4l2_subdev_state *state; + struct v4l2_mbus_framefmt *fmt; + int ret = 0; + + if (!ppc || pad < CSI2RX_PAD_SOURCE_STREAM0 || pad >= CSI2RX_PAD_MAX) + return -EINVAL; + + state = v4l2_subdev_lock_and_get_active_state(subdev); + fmt = v4l2_subdev_state_get_format(state, pad); + csi_fmt = csi2rx_get_fmt_by_code(fmt->code); + + /* Reduce requested PPC if it is too high */ + *ppc = min(*ppc, csi_fmt->max_pixels); + + v4l2_subdev_unlock_state(state); + + csi2rx->num_pixels[pad - CSI2RX_PAD_SOURCE_STREAM0] = + CSI2RX_STREAM_CFG_NUM_PIXELS(*ppc); + + return ret; +} +EXPORT_SYMBOL(cdns_csi2rx_negotiate_ppc); + static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = { .enum_mbus_code = csi2rx_enum_mbus_code, .get_fmt = v4l2_subdev_get_fmt, diff --git a/drivers/media/platform/cadence/cdns-csi2rx.h b/drivers/media/platform/cadence/cdns-csi2rx.h new file mode 100644 index 0000000000000000000000000000000000000000..128d47e8513c99c083f49e249e876be6d19389f6 --- /dev/null +++ b/drivers/media/platform/cadence/cdns-csi2rx.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef CDNS_CSI2RX_H +#define CDNS_CSI2RX_H + +#include <media/v4l2-subdev.h> + +/** + * cdns_csi2rx_negotiate_ppc - Negotiate pixel-per-clock on output interface + * + * @subdev: point to &struct v4l2_subdev + * @pad: pad number of the source pad + * @ppc: pointer to requested pixel-per-clock value + * + * Returns 0 on success, negative error code otherwise. + */ +int cdns_csi2rx_negotiate_ppc(struct v4l2_subdev *subdev, unsigned int pad, + u8 *ppc); + +#endif
The output pixel interface is a parallel bus (32 bits), which supports sending multiple pixels (1, 2 or 4) per clock cycle for smaller pixel widths like RAW8-RAW16. Dual-pixel and Quad-pixel modes can be a requirement if the export rate of the Cadence IP in Single-pixel mode maxes out before the maximum supported DPHY-RX frequency, which is the case with TI's integration of this IP [1]. So, we export a function that lets the downstream hardware block request a higher pixel-per-clock on a particular output pad. We check if we can support the requested pixels per clock given the known maximum for the currently configured format. If not, we set it to the highest feasible value and return this value to the caller. [1] Section 12.6.1.4.8.14 CSI_RX_IF Programming Restrictions of AM62 TRM Link: https://www.ti.com/lit/pdf/spruj16 Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com> --- drivers/media/platform/cadence/cdns-csi2rx.c | 74 +++++++++++++++++++++------- drivers/media/platform/cadence/cdns-csi2rx.h | 19 +++++++ 2 files changed, 75 insertions(+), 18 deletions(-)