1 From abf839bec9fa64ce922d63b2625b02e8e5c5b7bb Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 1 Apr 2022 18:56:54 +0100
4 Subject: [PATCH] media: i2c: imx258: Support faster pixel rate on
7 With the binned modes, there is little point in faithfully
8 reproducing the horizontal line length of 5352 pixels on the CSI2
9 bus, and the FIFO between the pixel array and MIPI serialiser
10 allows us to remove that dependency.
12 Allow the pixel array to run with the normal settings, with the MIPI
13 serialiser at half the rate. This requires some additional
14 information for the link frequency to pixel rate function that
15 needs to be added to the configuration tables.
17 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
19 drivers/media/i2c/imx258.c | 107 ++++++++++++++++++++++++-------------
20 1 file changed, 70 insertions(+), 37 deletions(-)
22 --- a/drivers/media/i2c/imx258.c
23 +++ b/drivers/media/i2c/imx258.c
24 @@ -104,6 +104,11 @@ struct imx258_reg_list {
25 const struct imx258_reg *regs;
28 +struct imx258_link_cfg {
29 + unsigned int lf_to_pix_rate_factor;
30 + struct imx258_reg_list reg_list;
33 #define IMX258_LANE_CONFIGS 2
34 #define IMX258_2_LANE_MODE 0
35 #define IMX258_4_LANE_MODE 1
36 @@ -113,8 +118,8 @@ struct imx258_link_freq_config {
40 - /* PLL registers for this link frequency */
41 - struct imx258_reg_list reg_list[IMX258_LANE_CONFIGS];
42 + /* Configuration for this link frequency / num lanes selection */
43 + struct imx258_link_cfg link_cfg[IMX258_LANE_CONFIGS];
46 /* Mode : resolution and related config&values */
47 @@ -273,7 +278,7 @@ static const struct imx258_reg mipi_640m
48 static const struct imx258_reg mipi_642mbps_24mhz_2l[] = {
56 @@ -690,14 +695,22 @@ enum {
60 - * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
61 - * data rate => double data rate;
62 - * number of lanes => (configurable 2 or 4);
63 - * bits per pixel => 10
64 + * Pixel rate does not necessarily relate to link frequency on this sensor as
65 + * there is a FIFO between the pixel array pipeline and the MIPI serializer.
66 + * The recommendation from Sony is that the pixel array is always run with a
67 + * line length of 5352 pixels, which means that there is a large amount of
68 + * blanking time for the 1048x780 mode. There is no need to replicate this
69 + * blanking on the CSI2 bus, and the configuration of register 0x0301 allows the
70 + * divider to be altered.
72 + * The actual factor between link frequency and pixel rate is in the
73 + * imx258_link_cfg, so use this to convert between the two.
74 + * bits per pixel being 10, and D-PHY being DDR is assumed by this function, so
75 + * the value is only the combination of number of lanes and pixel clock divider.
77 -static u64 link_freq_to_pixel_rate(u64 f, unsigned int nlanes)
78 +static u64 link_freq_to_pixel_rate(u64 f, const struct imx258_link_cfg *link_cfg)
81 + f *= 2 * link_cfg->lf_to_pix_rate_factor;
85 @@ -722,31 +735,33 @@ static const s64 link_freq_menu_items_24
86 IMX258_LINK_FREQ_321MHZ,
89 +#define REGS(_list) { .num_of_regs = ARRAY_SIZE(_list), .regs = _list, }
91 /* Link frequency configs */
92 static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
93 [IMX258_LINK_FREQ_1267MBPS] = {
94 .pixels_per_line = IMX258_PPL_DEFAULT,
97 [IMX258_2_LANE_MODE] = {
98 - .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_2l),
99 - .regs = mipi_1267mbps_19_2mhz_2l,
100 + .lf_to_pix_rate_factor = 2 * 2,
101 + .reg_list = REGS(mipi_1267mbps_19_2mhz_2l),
103 [IMX258_4_LANE_MODE] = {
104 - .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_4l),
105 - .regs = mipi_1267mbps_19_2mhz_4l,
106 + .lf_to_pix_rate_factor = 4,
107 + .reg_list = REGS(mipi_1267mbps_19_2mhz_4l),
111 [IMX258_LINK_FREQ_640MBPS] = {
112 .pixels_per_line = IMX258_PPL_DEFAULT,
115 [IMX258_2_LANE_MODE] = {
116 - .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_2l),
117 - .regs = mipi_640mbps_19_2mhz_2l,
118 + .lf_to_pix_rate_factor = 2,
119 + .reg_list = REGS(mipi_640mbps_19_2mhz_2l),
121 [IMX258_4_LANE_MODE] = {
122 - .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_4l),
123 - .regs = mipi_640mbps_19_2mhz_4l,
124 + .lf_to_pix_rate_factor = 4,
125 + .reg_list = REGS(mipi_640mbps_19_2mhz_4l),
129 @@ -755,27 +770,27 @@ static const struct imx258_link_freq_con
130 static const struct imx258_link_freq_config link_freq_configs_24[] = {
131 [IMX258_LINK_FREQ_1267MBPS] = {
132 .pixels_per_line = IMX258_PPL_DEFAULT,
135 [IMX258_2_LANE_MODE] = {
136 - .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_2l),
137 - .regs = mipi_1272mbps_24mhz_2l,
138 + .lf_to_pix_rate_factor = 2,
139 + .reg_list = REGS(mipi_1272mbps_24mhz_2l),
141 [IMX258_4_LANE_MODE] = {
142 - .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_4l),
143 - .regs = mipi_1272mbps_24mhz_4l,
144 + .lf_to_pix_rate_factor = 4,
145 + .reg_list = REGS(mipi_1272mbps_24mhz_4l),
149 [IMX258_LINK_FREQ_640MBPS] = {
150 .pixels_per_line = IMX258_PPL_DEFAULT,
153 [IMX258_2_LANE_MODE] = {
154 - .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_2l),
155 - .regs = mipi_642mbps_24mhz_2l,
156 + .lf_to_pix_rate_factor = 2 * 2,
157 + .reg_list = REGS(mipi_642mbps_24mhz_2l),
159 [IMX258_4_LANE_MODE] = {
160 - .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_4l),
161 - .regs = mipi_642mbps_24mhz_4l,
162 + .lf_to_pix_rate_factor = 4,
163 + .reg_list = REGS(mipi_642mbps_24mhz_4l),
167 @@ -857,7 +872,7 @@ struct imx258 {
169 const struct imx258_link_freq_config *link_freq_configs;
170 const s64 *link_freq_menu_items;
171 - unsigned int nlanes;
172 + unsigned int lane_mode_idx;
173 unsigned int csi2_flags;
176 @@ -1212,8 +1227,10 @@ static int imx258_set_pad_format(struct
177 struct v4l2_subdev_format *fmt)
179 struct imx258 *imx258 = to_imx258(sd);
180 - const struct imx258_mode *mode;
181 + const struct imx258_link_freq_config *link_freq_cfgs;
182 + const struct imx258_link_cfg *link_cfg;
183 struct v4l2_mbus_framefmt *framefmt;
184 + const struct imx258_mode *mode;
188 @@ -1236,7 +1253,11 @@ static int imx258_set_pad_format(struct
189 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
191 link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
192 - pixel_rate = link_freq_to_pixel_rate(link_freq, imx258->nlanes);
194 + &imx258->link_freq_configs[mode->link_freq_index];
196 + link_cfg = &link_freq_cfgs->link_cfg[imx258->lane_mode_idx];
197 + pixel_rate = link_freq_to_pixel_rate(link_freq, link_cfg);
198 __v4l2_ctrl_modify_range(imx258->pixel_rate, pixel_rate,
199 pixel_rate, 1, pixel_rate);
200 /* Update limits and set FPS to default */
201 @@ -1333,7 +1354,8 @@ static int imx258_start_streaming(struct
203 link_freq_index = imx258->cur_mode->link_freq_index;
204 link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
205 - reg_list = &link_freq_cfg->reg_list[imx258->nlanes == 2 ? 0 : 1];
207 + reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list;
208 ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
210 dev_err(&client->dev, "%s failed to set plls\n", __func__);
211 @@ -1543,8 +1565,10 @@ static const struct v4l2_subdev_internal
212 static int imx258_init_controls(struct imx258 *imx258)
214 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
215 + const struct imx258_link_freq_config *link_freq_cfgs;
216 struct v4l2_fwnode_device_properties props;
217 struct v4l2_ctrl_handler *ctrl_hdlr;
218 + const struct imx258_link_cfg *link_cfg;
222 @@ -1567,8 +1591,11 @@ static int imx258_init_controls(struct i
223 if (imx258->link_freq)
224 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
226 + link_freq_cfgs = &imx258->link_freq_configs[0];
227 + link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;
228 pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
232 /* By default, PIXEL_RATE is read only */
233 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
235 @@ -1739,10 +1766,16 @@ static int imx258_probe(struct i2c_clien
238 /* Get number of data lanes */
239 - imx258->nlanes = ep.bus.mipi_csi2.num_data_lanes;
240 - if (imx258->nlanes != 2 && imx258->nlanes != 4) {
241 + switch (ep.bus.mipi_csi2.num_data_lanes) {
243 + imx258->lane_mode_idx = IMX258_2_LANE_MODE;
246 + imx258->lane_mode_idx = IMX258_4_LANE_MODE;
249 dev_err(&client->dev, "Invalid data lanes: %u\n",
251 + ep.bus.mipi_csi2.num_data_lanes);
253 goto error_endpoint_poweron;