Skip to content

Commit 5d285d3

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 62c38c0 commit 5d285d3

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
@@ -85,6 +85,8 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8585
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8686
#define IMX477_DGTL_GAIN_STEP 1
8787

88+
#define IMX477_REG_DIV_IOP_PX 0x030b
89+
8890
/* Test Pattern Control */
8991
#define IMX477_REG_TEST_PATTERN 0x0600
9092
#define IMX477_TEST_PATTERN_DISABLE 0
@@ -150,7 +152,7 @@ struct imx477_mode {
150152
/* Frame height */
151153
unsigned int height;
152154

153-
/* H-timing in pixels */
155+
/* H-timing in pixels when at 450MHz link freq */
154156
unsigned int line_length_pix;
155157

156158
/* Analog crop rectangle. */
@@ -167,6 +169,10 @@ static const s64 imx477_link_freq_menu[] = {
167169
IMX477_DEFAULT_LINK_FREQ,
168170
};
169171

172+
static const s64 imx477_double_link_freq_menu[] = {
173+
IMX477_DEFAULT_LINK_FREQ * 2,
174+
};
175+
170176
static const struct imx477_reg mode_common_regs[] = {
171177
{0x0136, 0x18},
172178
{0x0137, 0x00},
@@ -491,7 +497,6 @@ static const struct imx477_reg mode_common_regs[] = {
491497
{0x9e9f, 0x00},
492498
{0x0301, 0x05},
493499
{0x0303, 0x02},
494-
{0x030b, 0x02},
495500
{0x030d, 0x02},
496501
{0x030e, 0x00},
497502
{0x030f, 0x96},
@@ -786,7 +791,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
786791
/* 12MPix 10fps mode */
787792
.width = 4056,
788793
.height = 3040,
789-
.line_length_pix = 0x5dc0,
794+
.line_length_pix = 24000,
790795
.crop = {
791796
.left = IMX477_PIXEL_ARRAY_LEFT,
792797
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -803,7 +808,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
803808
/* 2x2 binned 40fps mode */
804809
.width = 2028,
805810
.height = 1520,
806-
.line_length_pix = 0x31c4,
811+
.line_length_pix = 12740,
807812
.crop = {
808813
.left = IMX477_PIXEL_ARRAY_LEFT,
809814
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -820,7 +825,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
820825
/* 1080p 50fps cropped mode */
821826
.width = 2028,
822827
.height = 1080,
823-
.line_length_pix = 0x31c4,
828+
.line_length_pix = 12740,
824829
.crop = {
825830
.left = IMX477_PIXEL_ARRAY_LEFT,
826831
.top = IMX477_PIXEL_ARRAY_TOP + 440,
@@ -969,6 +974,12 @@ struct imx477 {
969974
*/
970975
unsigned int csi2_flags;
971976

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

@@ -1412,6 +1423,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14121423
{
14131424
unsigned int frm_length_default, hblank_min;
14141425
const struct imx477_mode *mode = imx477->mode;
1426+
unsigned int line_length_pix;
14151427

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

1431-
hblank_min = mode->line_length_pix - mode->width;
1443+
line_length_pix = mode->line_length_pix;
1444+
if (imx477->double_link_freq)
1445+
line_length_pix /= 2;
1446+
hblank_min = line_length_pix - mode->width;
14321447
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
14331448
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
14341449
__v4l2_ctrl_s_ctrl(imx477->hblank, hblank_min);
@@ -1568,6 +1583,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
15681583
imx477->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
15691584
1 : 0);
15701585

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

@@ -1825,6 +1844,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18251844
struct v4l2_ctrl_handler *ctrl_hdlr;
18261845
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
18271846
struct v4l2_fwnode_device_properties props;
1847+
const u64 *link_freq_menu;
18281848
unsigned int i;
18291849
int ret;
18301850

@@ -1846,11 +1866,16 @@ static int imx477_init_controls(struct imx477 *imx477)
18461866
imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
18471867

18481868
/* LINK_FREQ is also read only */
1869+
if (imx477->double_link_freq)
1870+
link_freq_menu = imx477_double_link_freq_menu;
1871+
else
1872+
link_freq_menu = imx477_link_freq_menu;
1873+
18491874
imx477->link_freq =
18501875
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
18511876
V4L2_CID_LINK_FREQ,
18521877
ARRAY_SIZE(imx477_link_freq_menu) - 1, 0,
1853-
imx477_link_freq_menu);
1878+
link_freq_menu);
18541879
if (imx477->link_freq)
18551880
imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
18561881

@@ -1980,11 +2005,14 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
19802005
}
19812006

19822007
if (ep_cfg.nr_of_link_frequencies != 1 ||
1983-
ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ) {
2008+
(ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ &&
2009+
ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ * 2)) {
19842010
dev_err(dev, "Link frequency not supported: %lld\n",
19852011
ep_cfg.link_frequencies[0]);
19862012
goto error_out;
19872013
}
2014+
if (ep_cfg.link_frequencies[0] == IMX477_DEFAULT_LINK_FREQ * 2)
2015+
imx477->double_link_freq = true;
19882016

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

0 commit comments

Comments
 (0)