Skip to content

Commit f9e84b2

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 <dave.stevenson@raspberrypi.com>
1 parent 60af5a2 commit f9e84b2

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

drivers/media/i2c/imx477.c

Lines changed: 42 additions & 8 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
@@ -151,7 +153,7 @@ struct imx477_mode {
151153
/* Frame height */
152154
unsigned int height;
153155

154-
/* H-timing in pixels */
156+
/* H-timing in pixels when at 450MHz link freq */
155157
unsigned int line_length_pix;
156158

157159
/* Analog crop rectangle. */
@@ -177,6 +179,12 @@ static const s64 link_freqs[] = {
177179
[IMX477_LINK_FREQ_456MHZ] = 456000000,
178180
};
179181

182+
static const s64 imx477_double_link_freq_menu[] = {
183+
[IMX477_LINK_FREQ_450MHZ] = 450000000 * 2,
184+
[IMX477_LINK_FREQ_453MHZ] = 453000000 * 2,
185+
[IMX477_LINK_FREQ_456MHZ] = 456000000 * 2,
186+
};
187+
180188
/* 450MHz is the nominal "default" link frequency */
181189
static const struct imx477_reg link_450Mhz_regs[] = {
182190
{0x030E, 0x00},
@@ -532,7 +540,6 @@ static const struct imx477_reg mode_common_regs[] = {
532540
{0x9e9f, 0x00},
533541
{0x0301, 0x05},
534542
{0x0303, 0x02},
535-
{0x030b, 0x02},
536543
{0x030d, 0x02},
537544
{0x0310, 0x01},
538545
{0x0820, 0x07},
@@ -825,7 +832,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
825832
/* 12MPix 10fps mode */
826833
.width = 4056,
827834
.height = 3040,
828-
.line_length_pix = 0x5dc0,
835+
.line_length_pix = 24000,
829836
.crop = {
830837
.left = IMX477_PIXEL_ARRAY_LEFT,
831838
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -842,7 +849,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
842849
/* 2x2 binned 40fps mode */
843850
.width = 2028,
844851
.height = 1520,
845-
.line_length_pix = 0x31c4,
852+
.line_length_pix = 12740,
846853
.crop = {
847854
.left = IMX477_PIXEL_ARRAY_LEFT,
848855
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -859,7 +866,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
859866
/* 1080p 50fps cropped mode */
860867
.width = 2028,
861868
.height = 1080,
862-
.line_length_pix = 0x31c4,
869+
.line_length_pix = 12740,
863870
.crop = {
864871
.left = IMX477_PIXEL_ARRAY_LEFT,
865872
.top = IMX477_PIXEL_ARRAY_TOP + 440,
@@ -1010,6 +1017,12 @@ struct imx477 {
10101017
*/
10111018
unsigned int csi2_flags;
10121019

1020+
/*
1021+
* Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1022+
* line_length_pix can be halved in that case.
1023+
*/
1024+
bool double_link_freq;
1025+
10131026
/* Rewrite common registers on stream on? */
10141027
bool common_regs_written;
10151028

@@ -1453,6 +1466,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14531466
{
14541467
unsigned int frm_length_default, hblank_min;
14551468
const struct imx477_mode *mode = imx477->mode;
1469+
unsigned int line_length_pix;
14561470

14571471
frm_length_default =
14581472
imx477_get_frame_length(mode, mode->framerate_default);
@@ -1469,7 +1483,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14691483
/* Setting this will adjust the exposure limits as well. */
14701484
__v4l2_ctrl_s_ctrl(imx477->vblank, frm_length_default - mode->height);
14711485

1472-
hblank_min = mode->line_length_pix - mode->width;
1486+
line_length_pix = mode->line_length_pix;
1487+
if (imx477->double_link_freq)
1488+
line_length_pix /= 2;
1489+
hblank_min = line_length_pix - mode->width;
14731490
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
14741491
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
14751492
__v4l2_ctrl_s_ctrl(imx477->hblank, hblank_min);
@@ -1616,6 +1633,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16161633
imx477->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16171634
1 : 0);
16181635

1636+
imx477_write_reg(imx477, IMX477_REG_DIV_IOP_PX,
1637+
IMX477_REG_VALUE_08BIT,
1638+
imx477->double_link_freq ? 1 : 2);
1639+
16191640
imx477->common_regs_written = true;
16201641
}
16211642

@@ -1873,6 +1894,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18731894
struct v4l2_ctrl_handler *ctrl_hdlr;
18741895
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
18751896
struct v4l2_fwnode_device_properties props;
1897+
const u64 *link_freq_menu;
18761898
unsigned int i;
18771899
int ret;
18781900

@@ -1894,10 +1916,15 @@ static int imx477_init_controls(struct imx477 *imx477)
18941916
imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
18951917

18961918
/* LINK_FREQ is also read only */
1919+
if (imx477->double_link_freq)
1920+
link_freq_menu = imx477_double_link_freq_menu[imx477->link_freq_idx];
1921+
else
1922+
link_freq_menu = imx477_link_freq_menu[imx477->link_freq_idx];
1923+
18971924
imx477->link_freq =
18981925
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
18991926
V4L2_CID_LINK_FREQ, 0, 0,
1900-
&link_freqs[imx477->link_freq_idx]);
1927+
link_freq_menu);
19011928
if (imx477->link_freq)
19021929
imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
19031930

@@ -2028,8 +2055,15 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20282055
}
20292056

20302057
for (i = 0; i < ARRAY_SIZE(link_freqs); i++) {
2031-
if (link_freqs[i] == ep_cfg.link_frequencies[0]) {
2058+
if (link_freqs[i] == ep_cfg.link_frequencies[0] ||
2059+
imx477_double_link_freq_menu[i] ==
2060+
ep_cfg.link_frequencies[0]) {
20322061
imx477->link_freq_idx = i;
2062+
2063+
if (imx477_double_link_freq_menu[i] ==
2064+
ep_cfg.link_frequencies[0])
2065+
imx477->double_link_freq = true;
2066+
20332067
break;
20342068
}
20352069
}

0 commit comments

Comments
 (0)