Skip to content

Commit 5786c2a

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 85dbfdc commit 5786c2a

File tree

1 file changed

+36
-8
lines changed

1 file changed

+36
-8
lines changed

drivers/media/i2c/imx477.c

Lines changed: 36 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. */
@@ -168,6 +170,10 @@ static const s64 imx477_link_freq_menu[] = {
168170
IMX477_DEFAULT_LINK_FREQ,
169171
};
170172

173+
static const s64 imx477_double_link_freq_menu[] = {
174+
IMX477_DEFAULT_LINK_FREQ * 2,
175+
};
176+
171177
static const struct imx477_reg mode_common_regs[] = {
172178
{0x0136, 0x18},
173179
{0x0137, 0x00},
@@ -492,7 +498,6 @@ static const struct imx477_reg mode_common_regs[] = {
492498
{0x9e9f, 0x00},
493499
{0x0301, 0x05},
494500
{0x0303, 0x02},
495-
{0x030b, 0x02},
496501
{0x030d, 0x02},
497502
{0x030e, 0x00},
498503
{0x030f, 0x96},
@@ -787,7 +792,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
787792
/* 12MPix 10fps mode */
788793
.width = 4056,
789794
.height = 3040,
790-
.line_length_pix = 0x5dc0,
795+
.line_length_pix = 24000,
791796
.crop = {
792797
.left = IMX477_PIXEL_ARRAY_LEFT,
793798
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -804,7 +809,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
804809
/* 2x2 binned 40fps mode */
805810
.width = 2028,
806811
.height = 1520,
807-
.line_length_pix = 0x31c4,
812+
.line_length_pix = 12740,
808813
.crop = {
809814
.left = IMX477_PIXEL_ARRAY_LEFT,
810815
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -821,7 +826,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
821826
/* 1080p 50fps cropped mode */
822827
.width = 2028,
823828
.height = 1080,
824-
.line_length_pix = 0x31c4,
829+
.line_length_pix = 12740,
825830
.crop = {
826831
.left = IMX477_PIXEL_ARRAY_LEFT,
827832
.top = IMX477_PIXEL_ARRAY_TOP + 440,
@@ -970,6 +975,12 @@ struct imx477 {
970975
*/
971976
unsigned int csi2_flags;
972977

978+
/*
979+
* Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
980+
* line_length_pix can be halved in that case.
981+
*/
982+
bool double_link_freq;
983+
973984
/* Rewrite common registers on stream on? */
974985
bool common_regs_written;
975986

@@ -1413,6 +1424,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14131424
{
14141425
unsigned int frm_length_default, hblank_min;
14151426
const struct imx477_mode *mode = imx477->mode;
1427+
unsigned int line_length_pix;
14161428

14171429
frm_length_default =
14181430
imx477_get_frame_length(mode, mode->framerate_default);
@@ -1429,7 +1441,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14291441
/* Setting this will adjust the exposure limits as well. */
14301442
__v4l2_ctrl_s_ctrl(imx477->vblank, frm_length_default - mode->height);
14311443

1432-
hblank_min = mode->line_length_pix - mode->width;
1444+
line_length_pix = mode->line_length_pix;
1445+
if (imx477->double_link_freq)
1446+
line_length_pix /= 2;
1447+
hblank_min = line_length_pix - mode->width;
14331448
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
14341449
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
14351450
__v4l2_ctrl_s_ctrl(imx477->hblank, hblank_min);
@@ -1569,6 +1584,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
15691584
imx477->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
15701585
1 : 0);
15711586

1587+
imx477_write_reg(imx477, IMX477_REG_DIV_IOP_PX,
1588+
IMX477_REG_VALUE_08BIT,
1589+
imx477->double_link_freq ? 1 : 2);
1590+
15721591
imx477->common_regs_written = true;
15731592
}
15741593

@@ -1826,6 +1845,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18261845
struct v4l2_ctrl_handler *ctrl_hdlr;
18271846
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
18281847
struct v4l2_fwnode_device_properties props;
1848+
const u64 *link_freq_menu;
18291849
unsigned int i;
18301850
int ret;
18311851

@@ -1847,11 +1867,16 @@ static int imx477_init_controls(struct imx477 *imx477)
18471867
imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
18481868

18491869
/* LINK_FREQ is also read only */
1870+
if (imx477->double_link_freq)
1871+
link_freq_menu = imx477_double_link_freq_menu;
1872+
else
1873+
link_freq_menu = imx477_link_freq_menu;
1874+
18501875
imx477->link_freq =
18511876
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
18521877
V4L2_CID_LINK_FREQ,
18531878
ARRAY_SIZE(imx477_link_freq_menu) - 1, 0,
1854-
imx477_link_freq_menu);
1879+
link_freq_menu);
18551880
if (imx477->link_freq)
18561881
imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
18571882

@@ -1981,11 +2006,14 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
19812006
}
19822007

19832008
if (ep_cfg.nr_of_link_frequencies != 1 ||
1984-
ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ) {
2009+
(ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ &&
2010+
ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ * 2)) {
19852011
dev_err(dev, "Link frequency not supported: %lld\n",
19862012
ep_cfg.link_frequencies[0]);
19872013
goto error_out;
19882014
}
2015+
if (ep_cfg.link_frequencies[0] == IMX477_DEFAULT_LINK_FREQ * 2)
2016+
imx477->double_link_freq = true;
19892017

19902018
imx477->csi2_flags = ep_cfg.bus.mipi_csi2.flags;
19912019

0 commit comments

Comments
 (0)