Skip to content

imx219 support for 4 CSI2 data lanes #6615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arch/arm/boot/dts/overlays/README
Original file line number Diff line number Diff line change
Expand Up @@ -2795,6 +2795,8 @@ Params: rotation Mounting rotation of the camera sensor (0 or
cam0 Adopt the default configuration for CAM0 on a
Compute Module (CSI0, i2c_vc, and cam0_reg).
vcm Configure a VCM focus drive on the sensor.
4lane Enable 4 CSI2 lanes. This requires a Compute
Module (1, 3, 4, or 5) or Pi 5.


Name: imx258
Expand Down
17 changes: 17 additions & 0 deletions arch/arm/boot/dts/overlays/imx219-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@
};
};

fragment@201 {
target = <&csi_ep>;
__dormant__ {
data-lanes = <1 2 3 4>;
};
};

fragment@202 {
target = <&cam_endpoint>;
__dormant__ {
data-lanes = <1 2 3 4>;
link-frequencies =
/bits/ 64 <363000000>;
};
};

__overrides__ {
rotation = <&cam_node>,"rotation:0";
orientation = <&cam_node>,"orientation:0";
Expand All @@ -83,6 +99,7 @@
<&vcm>, "VANA-supply:0=", <&cam0_reg>;
vcm = <&vcm>, "status=okay",
<&cam_node>,"lens-focus:0=", <&vcm>;
4lane = <0>, "+201+202";
};
};

Expand Down
78 changes: 61 additions & 17 deletions drivers/media/i2c/imx219.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,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 @@ -169,15 +170,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 All @@ -202,6 +194,34 @@ static const struct cci_reg_sequence imx219_common_regs[] = {
{ IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) },
};

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 @@ -663,9 +683,11 @@ static int imx219_set_framefmt(struct imx219 *imx219,

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 @@ -1043,6 +1065,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 @@ -1069,9 +1092,30 @@ 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))) {
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]);
Expand Down
Loading