Skip to content

Commit

Permalink
media: imx219: Adjust PLL settings based on the number of MIPI lanes
Browse files Browse the repository at this point in the history
Commit ceddfd4 ("media: i2c: imx219: Support four-lane operation")
added support for device tree to allow configuration of the sensor to
use 4 lanes with a link frequency of 363MHz, and amended the advertised
pixel rate to 280.8MPix/s.

However it didn't change any of the PLL settings, so actually it would
have been running effectively overclocked in the MIPI block, and with
the frame rate and exposure calculations being wrong.

The pixel rate and link frequency advertised were taken from the "Clock
Setting Example" section of the datasheet. However those are based on an
external clock of 12MHz, and are unachievable with a clock of 24MHz (it
seems PREPLLCLK_VT_DIV and PREPLLCK_OP_DIV can ONLY be set via the
automatic configuration doumented in "9-1-2 EXCK_FREQ setting depend on
INCK frequency).

Dropping all support for the 363MHz link frequency would cause problems
for existing users, so allow it from device tree, but log a warning that
the requested value is not being truly applied.

Fixes: ceddfd4 ("media: i2c: imx219: Support four-lane operation")
Co-developed-by: Peyton Howe <peyton.howe@bellsouth.net>
Signed-off-by: Peyton Howe <peyton.howe@bellsouth.net>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
  • Loading branch information
6by9 authored and pelwell committed Jan 20, 2025
1 parent 545cb71 commit 5b958ef
Showing 1 changed file with 64 additions and 19 deletions.
83 changes: 64 additions & 19 deletions drivers/media/i2c/imx219.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,11 @@

/* Pixel rate is fixed for all the modes */
#define IMX219_PIXEL_RATE 182400000
#define IMX219_PIXEL_RATE_4LANE 280800000
#define IMX219_PIXEL_RATE_4LANE 281600000

#define IMX219_DEFAULT_LINK_FREQ 456000000
#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
#define IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED 363000000
#define IMX219_DEFAULT_LINK_FREQ_4LANE 364000000

/* IMX219 native and active pixel array size. */
#define IMX219_NATIVE_WIDTH 3296U
Expand Down Expand Up @@ -224,15 +225,6 @@ static const struct cci_reg_sequence imx219_common_regs[] = {
{ CCI_REG8(0x30eb), 0x05 },
{ CCI_REG8(0x30eb), 0x09 },

/* PLL Clock Table */
{ IMX219_REG_VTPXCK_DIV, 5 },
{ IMX219_REG_VTSYCK_DIV, 1 },
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PLL_VT_MPY, 57 },
{ IMX219_REG_OPSYCK_DIV, 1 },
{ IMX219_REG_PLL_OP_MPY, 114 },

/* Undocumented registers */
{ CCI_REG8(0x455e), 0x00 },
{ CCI_REG8(0x471e), 0x4b },
Expand Down Expand Up @@ -316,6 +308,34 @@ static const struct cci_reg_sequence raw10_framefmt_regs[] = {
{ IMX219_REG_OPPXCK_DIV, 10 },
};

static const struct cci_reg_sequence imx219_2lane_regs[] = {
/* PLL Clock Table */
{ IMX219_REG_VTPXCK_DIV, 5 },
{ IMX219_REG_VTSYCK_DIV, 1 },
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PLL_VT_MPY, 57 },
{ IMX219_REG_OPSYCK_DIV, 1 },
{ IMX219_REG_PLL_OP_MPY, 114 },

/* 2-Lane CSI Mode */
{ IMX219_REG_CSI_LANE_MODE, IMX219_CSI_2_LANE_MODE },
};

static const struct cci_reg_sequence imx219_4lane_regs[] = {
/* PLL Clock Table */
{ IMX219_REG_VTPXCK_DIV, 5 },
{ IMX219_REG_VTSYCK_DIV, 1 },
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PLL_VT_MPY, 88 },
{ IMX219_REG_OPSYCK_DIV, 1 },
{ IMX219_REG_PLL_OP_MPY, 91 },

/* 4-Lane CSI Mode */
{ IMX219_REG_CSI_LANE_MODE, IMX219_CSI_4_LANE_MODE },
};

static const s64 imx219_link_freq_menu[] = {
IMX219_DEFAULT_LINK_FREQ,
};
Expand Down Expand Up @@ -941,9 +961,11 @@ static int imx219_get_selection(struct v4l2_subdev *sd,

static int imx219_configure_lanes(struct imx219 *imx219)
{
return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE :
IMX219_CSI_4_LANE_MODE, NULL);
/* Write the appropriate PLL settings for the number of MIPI lanes */
return cci_multi_reg_write(imx219->regmap,
imx219->lanes == 2 ? imx219_2lane_regs : imx219_4lane_regs,
imx219->lanes == 2 ? ARRAY_SIZE(imx219_2lane_regs) :
ARRAY_SIZE(imx219_4lane_regs), NULL);
};

static int imx219_start_streaming(struct imx219 *imx219,
Expand Down Expand Up @@ -1334,6 +1356,7 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
.bus_type = V4L2_MBUS_CSI2_DPHY
};
int ret = -EINVAL;
bool link_frequency_valid = false;

endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
if (!endpoint) {
Expand All @@ -1360,11 +1383,33 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
goto error_out;
}

if (ep_cfg.nr_of_link_frequencies != 1 ||
(ep_cfg.link_frequencies[0] != ((imx219->lanes == 2) ?
IMX219_DEFAULT_LINK_FREQ : IMX219_DEFAULT_LINK_FREQ_4LANE))) {
dev_err(dev, "Link frequency not supported: %lld\n",
ep_cfg.link_frequencies[0]);
if (ep_cfg.nr_of_link_frequencies == 1) {
switch (imx219->lanes) {
case 2:
if (ep_cfg.link_frequencies[0] ==
IMX219_DEFAULT_LINK_FREQ)
link_frequency_valid = true;
break;
case 4:
if (ep_cfg.link_frequencies[0] ==
IMX219_DEFAULT_LINK_FREQ_4LANE)
link_frequency_valid = true;
else if (ep_cfg.link_frequencies[0] ==
IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED) {
dev_warn(dev, "Link frequency of %d not supported, but has been incorrectly advertised previously\n",
IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED);
dev_warn(dev, "Using link frequency of %d\n",
IMX219_DEFAULT_LINK_FREQ_4LANE);
link_frequency_valid = true;
}
break;
}
}

if (!link_frequency_valid) {
dev_err_probe(dev, -EINVAL,
"Link frequency not supported: %lld\n",
ep_cfg.link_frequencies[0]);
goto error_out;
}

Expand Down

0 comments on commit 5b958ef

Please sign in to comment.