Skip to content

Commit 1b8e758

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 c5317ee commit 1b8e758

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
@@ -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. */
@@ -174,7 +176,7 @@ enum {
174176
IMX477_LINK_FREQ_498MHZ,
175177
};
176178

177-
static const s64 link_freqs[] = {
179+
static const u64 imx477_link_freq_menu[] = {
178180
[IMX477_LINK_FREQ_450MHZ] = 450000000,
179181
[IMX477_LINK_FREQ_453MHZ] = 453000000,
180182
[IMX477_LINK_FREQ_456MHZ] = 456000000,
@@ -183,6 +185,12 @@ static const s64 link_freqs[] = {
183185
[IMX477_LINK_FREQ_498MHZ] = 498000000,
184186
};
185187

188+
static const u64 imx477_double_link_freq_menu[] = {
189+
[IMX477_LINK_FREQ_450MHZ] = 450000000 * 2,
190+
[IMX477_LINK_FREQ_453MHZ] = 453000000 * 2,
191+
[IMX477_LINK_FREQ_456MHZ] = 456000000 * 2,
192+
};
193+
186194
/* 450MHz is the nominal "default" link frequency */
187195
static const struct imx477_reg link_450Mhz_regs[] = {
188196
{0x030E, 0x00},
@@ -565,7 +573,6 @@ static const struct imx477_reg mode_common_regs[] = {
565573
{0x9e9f, 0x00},
566574
{0x0301, 0x05},
567575
{0x0303, 0x02},
568-
{0x030b, 0x02},
569576
{0x030d, 0x02},
570577
{0x0310, 0x01},
571578
{0x0820, 0x07},
@@ -858,7 +865,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
858865
/* 12MPix 10fps mode */
859866
.width = 4056,
860867
.height = 3040,
861-
.line_length_pix = 0x5dc0,
868+
.line_length_pix = 24000,
862869
.crop = {
863870
.left = IMX477_PIXEL_ARRAY_LEFT,
864871
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -875,7 +882,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
875882
/* 2x2 binned 40fps mode */
876883
.width = 2028,
877884
.height = 1520,
878-
.line_length_pix = 0x31c4,
885+
.line_length_pix = 12740,
879886
.crop = {
880887
.left = IMX477_PIXEL_ARRAY_LEFT,
881888
.top = IMX477_PIXEL_ARRAY_TOP,
@@ -892,7 +899,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
892899
/* 1080p 50fps cropped mode */
893900
.width = 2028,
894901
.height = 1080,
895-
.line_length_pix = 0x31c4,
902+
.line_length_pix = 12740,
896903
.crop = {
897904
.left = IMX477_PIXEL_ARRAY_LEFT,
898905
.top = IMX477_PIXEL_ARRAY_TOP + 440,
@@ -1043,6 +1050,12 @@ struct imx477 {
10431050
*/
10441051
unsigned int csi2_flags;
10451052

1053+
/*
1054+
* Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1055+
* line_length_pix can be halved in that case.
1056+
*/
1057+
bool double_link_freq;
1058+
10461059
/* Rewrite common registers on stream on? */
10471060
bool common_regs_written;
10481061

@@ -1486,6 +1499,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14861499
{
14871500
unsigned int frm_length_default, hblank_min;
14881501
const struct imx477_mode *mode = imx477->mode;
1502+
unsigned int line_length_pix;
14891503

14901504
frm_length_default =
14911505
imx477_get_frame_length(mode, mode->framerate_default);
@@ -1502,7 +1516,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
15021516
/* Setting this will adjust the exposure limits as well. */
15031517
__v4l2_ctrl_s_ctrl(imx477->vblank, frm_length_default - mode->height);
15041518

1505-
hblank_min = mode->line_length_pix - mode->width;
1519+
line_length_pix = mode->line_length_pix;
1520+
if (imx477->double_link_freq)
1521+
line_length_pix /= 2;
1522+
hblank_min = line_length_pix - mode->width;
15061523
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
15071524
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
15081525
__v4l2_ctrl_s_ctrl(imx477->hblank, hblank_min);
@@ -1649,6 +1666,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16491666
imx477->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16501667
1 : 0);
16511668

1669+
imx477_write_reg(imx477, IMX477_REG_DIV_IOP_PX,
1670+
IMX477_REG_VALUE_08BIT,
1671+
imx477->double_link_freq ? 1 : 2);
1672+
16521673
imx477->common_regs_written = true;
16531674
}
16541675

@@ -1906,6 +1927,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19061927
struct v4l2_ctrl_handler *ctrl_hdlr;
19071928
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
19081929
struct v4l2_fwnode_device_properties props;
1930+
const u64 *link_freq_menu;
19091931
unsigned int i;
19101932
int ret;
19111933

@@ -1927,10 +1949,15 @@ static int imx477_init_controls(struct imx477 *imx477)
19271949
imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
19281950

19291951
/* LINK_FREQ is also read only */
1952+
if (imx477->double_link_freq)
1953+
link_freq_menu = &imx477_double_link_freq_menu[imx477->link_freq_idx];
1954+
else
1955+
link_freq_menu = &imx477_link_freq_menu[imx477->link_freq_idx];
1956+
19301957
imx477->link_freq =
19311958
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
19321959
V4L2_CID_LINK_FREQ, 0, 0,
1933-
&link_freqs[imx477->link_freq_idx]);
1960+
link_freq_menu);
19341961
if (imx477->link_freq)
19351962
imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
19361963

@@ -2060,14 +2087,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20602087
goto error_out;
20612088
}
20622089

2063-
for (i = 0; i < ARRAY_SIZE(link_freqs); i++) {
2064-
if (link_freqs[i] == ep_cfg.link_frequencies[0]) {
2090+
for (i = 0; i < ARRAY_SIZE(imx477_link_freq_menu); i++) {
2091+
if (imx477_link_freq_menu[i] == ep_cfg.link_frequencies[0] ||
2092+
imx477_double_link_freq_menu[i] ==
2093+
ep_cfg.link_frequencies[0]) {
20652094
imx477->link_freq_idx = i;
2095+
2096+
if (imx477_double_link_freq_menu[i] ==
2097+
ep_cfg.link_frequencies[0])
2098+
imx477->double_link_freq = true;
2099+
20662100
break;
20672101
}
20682102
}
20692103

2070-
if (i == ARRAY_SIZE(link_freqs)) {
2104+
if (i == ARRAY_SIZE(imx477_link_freq_menu)) {
20712105
dev_err(dev, "Link frequency not supported: %lld\n",
20722106
ep_cfg.link_frequencies[0]);
20732107
ret = -EINVAL;

0 commit comments

Comments
 (0)