Skip to content

Commit 3edcbd7

Browse files
6by9pelwell
authored andcommitted
media: i2c: imx258: Support faster pixel rate on binned modes
With the binned modes, there is little point in faithfully reproducing the horizontal line length of 5352 pixels on the CSI2 bus, and the FIFO between the pixel array and MIPI serialiser allows us to remove that dependency. Allow the pixel array to run with the normal settings, with the MIPI serialiser at half the rate. This requires some additional information for the link frequency to pixel rate function that needs to be added to the configuration tables. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
1 parent bfeb930 commit 3edcbd7

File tree

1 file changed

+70
-37
lines changed

1 file changed

+70
-37
lines changed

drivers/media/i2c/imx258.c

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ struct imx258_reg_list {
104104
const struct imx258_reg *regs;
105105
};
106106

107+
struct imx258_link_cfg {
108+
unsigned int lf_to_pix_rate_factor;
109+
struct imx258_reg_list reg_list;
110+
};
111+
107112
#define IMX258_LANE_CONFIGS 2
108113
#define IMX258_2_LANE_MODE 0
109114
#define IMX258_4_LANE_MODE 1
@@ -113,8 +118,8 @@ struct imx258_link_freq_config {
113118
u64 link_frequency;
114119
u32 pixels_per_line;
115120

116-
/* PLL registers for this link frequency */
117-
struct imx258_reg_list reg_list[IMX258_LANE_CONFIGS];
121+
/* Configuration for this link frequency / num lanes selection */
122+
struct imx258_link_cfg link_cfg[IMX258_LANE_CONFIGS];
118123
};
119124

120125
/* Mode : resolution and related config&values */
@@ -273,7 +278,7 @@ static const struct imx258_reg mipi_640mbps_19_2mhz_4l[] = {
273278
static const struct imx258_reg mipi_642mbps_24mhz_2l[] = {
274279
{ 0x0136, 0x18 },
275280
{ 0x0137, 0x00 },
276-
{ 0x0301, 0x0A },
281+
{ 0x0301, 0x05 },
277282
{ 0x0303, 0x02 },
278283
{ 0x0305, 0x04 },
279284
{ 0x0306, 0x00 },
@@ -690,14 +695,22 @@ enum {
690695
};
691696

692697
/*
693-
* pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
694-
* data rate => double data rate;
695-
* number of lanes => (configurable 2 or 4);
696-
* bits per pixel => 10
698+
* Pixel rate does not necessarily relate to link frequency on this sensor as
699+
* there is a FIFO between the pixel array pipeline and the MIPI serializer.
700+
* The recommendation from Sony is that the pixel array is always run with a
701+
* line length of 5352 pixels, which means that there is a large amount of
702+
* blanking time for the 1048x780 mode. There is no need to replicate this
703+
* blanking on the CSI2 bus, and the configuration of register 0x0301 allows the
704+
* divider to be altered.
705+
*
706+
* The actual factor between link frequency and pixel rate is in the
707+
* imx258_link_cfg, so use this to convert between the two.
708+
* bits per pixel being 10, and D-PHY being DDR is assumed by this function, so
709+
* the value is only the combination of number of lanes and pixel clock divider.
697710
*/
698-
static u64 link_freq_to_pixel_rate(u64 f, unsigned int nlanes)
711+
static u64 link_freq_to_pixel_rate(u64 f, const struct imx258_link_cfg *link_cfg)
699712
{
700-
f *= 2 * nlanes;
713+
f *= 2 * link_cfg->lf_to_pix_rate_factor;
701714
do_div(f, 10);
702715

703716
return f;
@@ -722,31 +735,33 @@ static const s64 link_freq_menu_items_24[] = {
722735
IMX258_LINK_FREQ_321MHZ,
723736
};
724737

738+
#define REGS(_list) { .num_of_regs = ARRAY_SIZE(_list), .regs = _list, }
739+
725740
/* Link frequency configs */
726741
static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
727742
[IMX258_LINK_FREQ_1267MBPS] = {
728743
.pixels_per_line = IMX258_PPL_DEFAULT,
729-
.reg_list = {
744+
.link_cfg = {
730745
[IMX258_2_LANE_MODE] = {
731-
.num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_2l),
732-
.regs = mipi_1267mbps_19_2mhz_2l,
746+
.lf_to_pix_rate_factor = 2 * 2,
747+
.reg_list = REGS(mipi_1267mbps_19_2mhz_2l),
733748
},
734749
[IMX258_4_LANE_MODE] = {
735-
.num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_4l),
736-
.regs = mipi_1267mbps_19_2mhz_4l,
750+
.lf_to_pix_rate_factor = 4,
751+
.reg_list = REGS(mipi_1267mbps_19_2mhz_4l),
737752
},
738753
}
739754
},
740755
[IMX258_LINK_FREQ_640MBPS] = {
741756
.pixels_per_line = IMX258_PPL_DEFAULT,
742-
.reg_list = {
757+
.link_cfg = {
743758
[IMX258_2_LANE_MODE] = {
744-
.num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_2l),
745-
.regs = mipi_640mbps_19_2mhz_2l,
759+
.lf_to_pix_rate_factor = 2,
760+
.reg_list = REGS(mipi_640mbps_19_2mhz_2l),
746761
},
747762
[IMX258_4_LANE_MODE] = {
748-
.num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_4l),
749-
.regs = mipi_640mbps_19_2mhz_4l,
763+
.lf_to_pix_rate_factor = 4,
764+
.reg_list = REGS(mipi_640mbps_19_2mhz_4l),
750765
},
751766
}
752767
},
@@ -755,27 +770,27 @@ static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
755770
static const struct imx258_link_freq_config link_freq_configs_24[] = {
756771
[IMX258_LINK_FREQ_1267MBPS] = {
757772
.pixels_per_line = IMX258_PPL_DEFAULT,
758-
.reg_list = {
773+
.link_cfg = {
759774
[IMX258_2_LANE_MODE] = {
760-
.num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_2l),
761-
.regs = mipi_1272mbps_24mhz_2l,
775+
.lf_to_pix_rate_factor = 2,
776+
.reg_list = REGS(mipi_1272mbps_24mhz_2l),
762777
},
763778
[IMX258_4_LANE_MODE] = {
764-
.num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_4l),
765-
.regs = mipi_1272mbps_24mhz_4l,
779+
.lf_to_pix_rate_factor = 4,
780+
.reg_list = REGS(mipi_1272mbps_24mhz_4l),
766781
},
767782
}
768783
},
769784
[IMX258_LINK_FREQ_640MBPS] = {
770785
.pixels_per_line = IMX258_PPL_DEFAULT,
771-
.reg_list = {
786+
.link_cfg = {
772787
[IMX258_2_LANE_MODE] = {
773-
.num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_2l),
774-
.regs = mipi_642mbps_24mhz_2l,
788+
.lf_to_pix_rate_factor = 2 * 2,
789+
.reg_list = REGS(mipi_642mbps_24mhz_2l),
775790
},
776791
[IMX258_4_LANE_MODE] = {
777-
.num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_4l),
778-
.regs = mipi_642mbps_24mhz_4l,
792+
.lf_to_pix_rate_factor = 4,
793+
.reg_list = REGS(mipi_642mbps_24mhz_4l),
779794
},
780795
}
781796
},
@@ -857,7 +872,7 @@ struct imx258 {
857872

858873
const struct imx258_link_freq_config *link_freq_configs;
859874
const s64 *link_freq_menu_items;
860-
unsigned int nlanes;
875+
unsigned int lane_mode_idx;
861876
unsigned int csi2_flags;
862877

863878
/*
@@ -1212,8 +1227,10 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
12121227
struct v4l2_subdev_format *fmt)
12131228
{
12141229
struct imx258 *imx258 = to_imx258(sd);
1215-
const struct imx258_mode *mode;
1230+
const struct imx258_link_freq_config *link_freq_cfgs;
1231+
const struct imx258_link_cfg *link_cfg;
12161232
struct v4l2_mbus_framefmt *framefmt;
1233+
const struct imx258_mode *mode;
12171234
s32 vblank_def;
12181235
s32 vblank_min;
12191236
s64 h_blank;
@@ -1236,7 +1253,11 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
12361253
__v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
12371254

12381255
link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
1239-
pixel_rate = link_freq_to_pixel_rate(link_freq, imx258->nlanes);
1256+
link_freq_cfgs =
1257+
&imx258->link_freq_configs[mode->link_freq_index];
1258+
1259+
link_cfg = &link_freq_cfgs->link_cfg[imx258->lane_mode_idx];
1260+
pixel_rate = link_freq_to_pixel_rate(link_freq, link_cfg);
12401261
__v4l2_ctrl_modify_range(imx258->pixel_rate, pixel_rate,
12411262
pixel_rate, 1, pixel_rate);
12421263
/* Update limits and set FPS to default */
@@ -1333,7 +1354,8 @@ static int imx258_start_streaming(struct imx258 *imx258)
13331354
/* Setup PLL */
13341355
link_freq_index = imx258->cur_mode->link_freq_index;
13351356
link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
1336-
reg_list = &link_freq_cfg->reg_list[imx258->nlanes == 2 ? 0 : 1];
1357+
1358+
reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list;
13371359
ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
13381360
if (ret) {
13391361
dev_err(&client->dev, "%s failed to set plls\n", __func__);
@@ -1543,8 +1565,10 @@ static const struct v4l2_subdev_internal_ops imx258_internal_ops = {
15431565
static int imx258_init_controls(struct imx258 *imx258)
15441566
{
15451567
struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
1568+
const struct imx258_link_freq_config *link_freq_cfgs;
15461569
struct v4l2_fwnode_device_properties props;
15471570
struct v4l2_ctrl_handler *ctrl_hdlr;
1571+
const struct imx258_link_cfg *link_cfg;
15481572
s64 vblank_def;
15491573
s64 vblank_min;
15501574
s64 pixel_rate;
@@ -1567,8 +1591,11 @@ static int imx258_init_controls(struct imx258 *imx258)
15671591
if (imx258->link_freq)
15681592
imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
15691593

1594+
link_freq_cfgs = &imx258->link_freq_configs[0];
1595+
link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;
15701596
pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
1571-
imx258->nlanes);
1597+
link_cfg);
1598+
15721599
/* By default, PIXEL_RATE is read only */
15731600
imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
15741601
V4L2_CID_PIXEL_RATE,
@@ -1739,10 +1766,16 @@ static int imx258_probe(struct i2c_client *client)
17391766
}
17401767

17411768
/* Get number of data lanes */
1742-
imx258->nlanes = ep.bus.mipi_csi2.num_data_lanes;
1743-
if (imx258->nlanes != 2 && imx258->nlanes != 4) {
1769+
switch (ep.bus.mipi_csi2.num_data_lanes) {
1770+
case 2:
1771+
imx258->lane_mode_idx = IMX258_2_LANE_MODE;
1772+
break;
1773+
case 4:
1774+
imx258->lane_mode_idx = IMX258_4_LANE_MODE;
1775+
break;
1776+
default:
17441777
dev_err(&client->dev, "Invalid data lanes: %u\n",
1745-
imx258->nlanes);
1778+
ep.bus.mipi_csi2.num_data_lanes);
17461779
ret = -EINVAL;
17471780
goto error_endpoint_poweron;
17481781
}

0 commit comments

Comments
 (0)