Skip to content

Commit 83f5930

Browse files
committed
media: i2c: imx477: Add option for double link frequency (900MHz)
Pi5 can support higher CSI2 link frequencies than Pi 0-4, and hence higher framerates. The simplest change is to change the DIV_IOP_PX divider from the current value of 2 to 1 to double the frequency. This is slightly outside the max rate nominally supported by RP1, but seems reliable. Signed-off-by: Dave Stevenson <[email protected]>
1 parent 89c8f1a commit 83f5930

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

drivers/media/i2c/imx477.c

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8686
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8787
#define IMX477_DGTL_GAIN_STEP 1
8888

89+
#define IMX477_REG_DIV_IOP_PX 0x030b
90+
8991
/* Test Pattern Control */
9092
#define IMX477_REG_TEST_PATTERN 0x0600
9193
#define IMX477_TEST_PATTERN_DISABLE 0
@@ -154,7 +156,7 @@ struct imx477_mode {
154156
/* Frame height */
155157
unsigned int height;
156158

157-
/* H-timing in pixels */
159+
/* H-timing in pixels when at 450MHz link freq */
158160
unsigned int line_length_pix;
159161

160162
/* Analog crop rectangle. */
@@ -177,7 +179,7 @@ enum {
177179
IMX477_LINK_FREQ_498MHZ,
178180
};
179181

180-
static const s64 link_freqs[] = {
182+
static const u64 imx477_link_freq_menu[] = {
181183
[IMX477_LINK_FREQ_450MHZ] = 450000000,
182184
[IMX477_LINK_FREQ_453MHZ] = 453000000,
183185
[IMX477_LINK_FREQ_456MHZ] = 456000000,
@@ -186,6 +188,12 @@ static const s64 link_freqs[] = {
186188
[IMX477_LINK_FREQ_498MHZ] = 498000000,
187189
};
188190

191+
static const u64 imx477_double_link_freq_menu[] = {
192+
[IMX477_LINK_FREQ_450MHZ] = 450000000 * 2,
193+
[IMX477_LINK_FREQ_453MHZ] = 453000000 * 2,
194+
[IMX477_LINK_FREQ_456MHZ] = 456000000 * 2,
195+
};
196+
189197
/* 450MHz is the nominal "default" link frequency */
190198
static const struct imx477_reg link_450Mhz_regs[] = {
191199
{0x030E, 0x00},
@@ -568,7 +576,6 @@ static const struct imx477_reg mode_common_regs[] = {
568576
{0x9e9f, 0x00},
569577
{0x0301, 0x05},
570578
{0x0303, 0x02},
571-
{0x030b, 0x02},
572579
{0x030d, 0x02},
573580
{0x0310, 0x01},
574581
{0x0820, 0x07},
@@ -861,7 +868,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
861868
/* 12MPix 10fps mode */
862869
.width = 4056,
863870
.height = 3040,
864-
.line_length_pix = 0x5dc0,
871+
.line_length_pix = 24000,
865872
.crop = {
866873
.left = IMX477_PIXEL_ARRAY_LEFT,
867874
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -878,7 +885,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
878885
/* 2x2 binned 40fps mode */
879886
.width = 2028,
880887
.height = 1520,
881-
.line_length_pix = 0x31c4,
888+
.line_length_pix = 12740,
882889
.crop = {
883890
.left = IMX477_PIXEL_ARRAY_LEFT,
884891
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -895,7 +902,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
895902
/* 1080p 50fps cropped mode */
896903
.width = 2028,
897904
.height = 1080,
898-
.line_length_pix = 0x31c4,
905+
.line_length_pix = 12740,
899906
.crop = {
900907
.left = IMX477_PIXEL_ARRAY_LEFT,
901908
.top = IMX477_PIXEL_ARRAY_TOP + 440,
@@ -1046,6 +1053,12 @@ struct imx477 {
10461053
*/
10471054
unsigned int csi2_flags;
10481055

1056+
/*
1057+
* Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1058+
* line_length_pix can be halved in that case.
1059+
*/
1060+
bool double_link_freq;
1061+
10491062
/* Rewrite common registers on stream on? */
10501063
bool common_regs_written;
10511064

@@ -1496,6 +1509,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14961509
{
14971510
unsigned int frm_length_default, hblank_min;
14981511
const struct imx477_mode *mode = imx477->mode;
1512+
unsigned int line_length_pix;
14991513

15001514
frm_length_default =
15011515
imx477_get_frame_length(mode, mode->framerate_default);
@@ -1512,7 +1526,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
15121526
/* Setting this will adjust the exposure limits as well. */
15131527
__v4l2_ctrl_s_ctrl(imx477->vblank, frm_length_default - mode->height);
15141528

1515-
hblank_min = mode->line_length_pix - mode->width;
1529+
line_length_pix = mode->line_length_pix;
1530+
if (imx477->double_link_freq)
1531+
line_length_pix /= 2;
1532+
hblank_min = line_length_pix - mode->width;
15161533
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
15171534
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
15181535
__v4l2_ctrl_s_ctrl(imx477->hblank, hblank_min);
@@ -1659,6 +1676,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16591676
imx477->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16601677
1 : 0);
16611678

1679+
imx477_write_reg(imx477, IMX477_REG_DIV_IOP_PX,
1680+
IMX477_REG_VALUE_08BIT,
1681+
imx477->double_link_freq ? 1 : 2);
1682+
16621683
imx477->common_regs_written = true;
16631684
}
16641685

@@ -1926,6 +1947,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19261947
struct v4l2_ctrl_handler *ctrl_hdlr;
19271948
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
19281949
struct v4l2_fwnode_device_properties props;
1950+
const u64 *link_freq_menu;
19291951
unsigned int i;
19301952
int ret;
19311953

@@ -1947,10 +1969,15 @@ static int imx477_init_controls(struct imx477 *imx477)
19471969
imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
19481970

19491971
/* LINK_FREQ is also read only */
1972+
if (imx477->double_link_freq)
1973+
link_freq_menu = &imx477_double_link_freq_menu[imx477->link_freq_idx];
1974+
else
1975+
link_freq_menu = &imx477_link_freq_menu[imx477->link_freq_idx];
1976+
19501977
imx477->link_freq =
19511978
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
19521979
V4L2_CID_LINK_FREQ, 0, 0,
1953-
&link_freqs[imx477->link_freq_idx]);
1980+
link_freq_menu);
19541981
if (imx477->link_freq)
19551982
imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
19561983

@@ -2080,14 +2107,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20802107
goto error_out;
20812108
}
20822109

2083-
for (i = 0; i < ARRAY_SIZE(link_freqs); i++) {
2084-
if (link_freqs[i] == ep_cfg.link_frequencies[0]) {
2110+
for (i = 0; i < ARRAY_SIZE(imx477_link_freq_menu); i++) {
2111+
if (imx477_link_freq_menu[i] == ep_cfg.link_frequencies[0] ||
2112+
imx477_double_link_freq_menu[i] ==
2113+
ep_cfg.link_frequencies[0]) {
20852114
imx477->link_freq_idx = i;
2115+
2116+
if (imx477_double_link_freq_menu[i] ==
2117+
ep_cfg.link_frequencies[0])
2118+
imx477->double_link_freq = true;
2119+
20862120
break;
20872121
}
20882122
}
20892123

2090-
if (i == ARRAY_SIZE(link_freqs)) {
2124+
if (i == ARRAY_SIZE(imx477_link_freq_menu)) {
20912125
dev_err(dev, "Link frequency not supported: %lld\n",
20922126
ep_cfg.link_frequencies[0]);
20932127
ret = -EINVAL;

0 commit comments

Comments
 (0)