Skip to content

Commit 2e4be19

Browse files
committed
Rework imx708 driver to modify pixel rate and line length based on the number of MIPI lanes
1 parent 0a886f7 commit 2e4be19

1 file changed

Lines changed: 153 additions & 40 deletions

File tree

drivers/media/i2c/imx708.c

Lines changed: 153 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ struct imx708_reg {
153153
u8 val;
154154
};
155155

156+
struct imx708_pair {
157+
u64 two_lane;
158+
u64 four_lane;
159+
};
160+
156161
struct imx708_reg_list {
157162
unsigned int num_of_regs;
158163
const struct imx708_reg *regs;
@@ -167,7 +172,7 @@ struct imx708_mode {
167172
unsigned int height;
168173

169174
/* H-timing in pixels */
170-
unsigned int line_length_pix;
175+
struct imx708_pair line_length_pix;
171176

172177
/* Analog crop rectangle. */
173178
struct v4l2_rect crop;
@@ -182,7 +187,7 @@ struct imx708_mode {
182187
struct imx708_reg_list reg_list;
183188

184189
/* Not all modes have the same pixel rate. */
185-
u64 pixel_rate;
190+
struct imx708_pair pixel_rates;
186191

187192
/* Not all modes have the same minimum exposure. */
188193
u32 exposure_lines_min;
@@ -273,8 +278,8 @@ static const struct imx708_reg mode_common_regs[] = {
273278
{0x0100, 0x00},
274279
{0x0136, 0x18}, //REG_EXCK_FREQ_MSB
275280
{0x0137, 0x00}, //REG_EXCK_FREQ_LSB
276-
{0x33F0, 0x02}, //0x01, 0x02
277-
{0x33F1, 0x05}, //0x01, 0x05
281+
{0x33F0, 0x02}, //REG_IOPSYCK_DIV 0x01, 0x02
282+
{0x33F1, 0x05}, //REG_IOPPXCK_DIV 0x01, 0x05
278283
{0x3062, 0x00},
279284
{0x3063, 0x12}, //0x30, 0x12
280285
{0x3068, 0x00},
@@ -319,10 +324,99 @@ static const struct imx708_reg mode_common_regs[] = {
319324
{0x0138, 0x01}, //REG_TEMP_SENS_CTL
320325
};
321326

327+
/* Pixel rate setup */
328+
enum {
329+
IMX708_PIX_RATE_566Mhz,
330+
IMX708_PIX_RATE_585Mhz,
331+
IMX708_PIX_RATE_595Mhz,
332+
IMX708_PIX_RATE_777Mhz,
333+
IMX708_PIX_RATE_854Mhz,
334+
};
335+
336+
static const s64 pixel_rates[] = {
337+
[IMX708_PIX_RATE_566Mhz] = 566400000,
338+
[IMX708_PIX_RATE_585Mhz] = 585600000,
339+
[IMX708_PIX_RATE_595Mhz] = 595200000,
340+
[IMX708_PIX_RATE_777Mhz] = 777600000,
341+
[IMX708_PIX_RATE_854Mhz] = 854400000,
342+
};
343+
344+
static const struct imx708_reg pixel_rate_566Mhz_regs[] = {
345+
{0x0305, 0x02},
346+
{0x0306, 0x00},
347+
{0x0307, 0x76},
348+
};
349+
350+
static const struct imx708_reg pixel_rate_585Mhz_regs[] = {
351+
{0x0305, 0x02},
352+
{0x0306, 0x00},
353+
{0x0307, 0x7A},
354+
};
355+
356+
static const struct imx708_reg pixel_rate_595Mhz_regs[] = {
357+
{0x0305, 0x02},
358+
{0x0306, 0x00},
359+
{0x0307, 0x7C},
360+
};
361+
362+
static const struct imx708_reg pixel_rate_777Mhz_regs[] = {
363+
{0x0305, 0x02},
364+
{0x0306, 0x00},
365+
{0x0307, 0xA2},
366+
};
367+
368+
static const struct imx708_reg pixel_rate_854Mhz_regs[] = {
369+
{0x0305, 0x03},
370+
{0x0306, 0x01},
371+
{0x0307, 0x0B},
372+
};
373+
374+
static const struct imx708_reg_list pixel_rate_regs[] = {
375+
[IMX708_PIX_RATE_566Mhz] = {
376+
.regs = pixel_rate_566Mhz_regs,
377+
.num_of_regs = ARRAY_SIZE(pixel_rate_566Mhz_regs)
378+
},
379+
[IMX708_PIX_RATE_585Mhz] = {
380+
.regs = pixel_rate_585Mhz_regs,
381+
.num_of_regs = ARRAY_SIZE(pixel_rate_585Mhz_regs)
382+
},
383+
[IMX708_PIX_RATE_595Mhz] = {
384+
.regs = pixel_rate_595Mhz_regs,
385+
.num_of_regs = ARRAY_SIZE(pixel_rate_595Mhz_regs)
386+
},
387+
[IMX708_PIX_RATE_777Mhz] = {
388+
.regs = pixel_rate_777Mhz_regs,
389+
.num_of_regs = ARRAY_SIZE(pixel_rate_777Mhz_regs)
390+
},
391+
[IMX708_PIX_RATE_854Mhz] = {
392+
.regs = pixel_rate_854Mhz_regs,
393+
.num_of_regs = ARRAY_SIZE(pixel_rate_854Mhz_regs)
394+
},
395+
};
396+
397+
/* Line Length setup */
398+
enum {
399+
IMX708_LINE_LENGTH_2608,
400+
IMX708_LINE_LENGTH_5216,
401+
IMX708_LINE_LENGTH_7824,
402+
IMX708_LINE_LENGTH_10432,
403+
IMX708_LINE_LENGTH_15648,
404+
IMX708_LINE_LENGTH_20864,
405+
};
406+
407+
static const s64 line_lengths[] = {
408+
[IMX708_LINE_LENGTH_2608] = 2608,
409+
[IMX708_LINE_LENGTH_5216] = 5216,
410+
[IMX708_LINE_LENGTH_7824] = 7824,
411+
[IMX708_LINE_LENGTH_10432] = 10432,
412+
[IMX708_LINE_LENGTH_15648] = 15648,
413+
[IMX708_LINE_LENGTH_20864] = 20864,
414+
};
415+
322416
/* 10-bit. */
323417
static const struct imx708_reg mode_4608x2592_regs[] = {
324418
{0x0340, 0x0A}, //REG_FRAME_LEN_MSB
325-
{0x0341, 0xC4}, //REG_FRAME_LEN_LSB (0xC4, 0x5A, 0x59)
419+
{0x0341, 0x59}, //REG_FRAME_LEN_LSB (0xC4, 0x5A, 0x59)
326420
{0x0344, 0x00}, //REG_X_ADD_STA_MSB
327421
{0x0345, 0x00}, //REG_X_ADD_STA_LSB
328422
{0x0346, 0x00}, //REG_Y_ADD_STA_MSB
@@ -358,10 +452,7 @@ static const struct imx708_reg mode_4608x2592_regs[] = {
358452
{0x034F, 0x20}, //REG_Y_OUT_SIZE_LSB
359453
{0x0301, 0x05}, //REG_IVTPXCK_DIV
360454
{0x0303, 0x02}, //REG_IVTSYCK_DIV
361-
{0x0305, 0x03}, //REG_IVT_PREPLLCK_DIV (0x03 , 0x02)
362-
{0x0306, 0x01}, //REG_PLL_IVT_MPY_MSB (0x01 , 0x00)
363-
{0x0307, 0x0B}, //REG_PLL_IVT_MPY_LSB (0x0B , 0x01, 0x7C)
364-
{0x030B, 0x02}, //REG_IOPSYCK_DIV
455+
{0x030B, 0x02},
365456
{0x030D, 0x04}, //REG_IOP_PREPLLCK_DIV
366457
{0x0310, 0x01}, //REG_PLL_MULTI_DRV
367458
{0x3CA0, 0x00},
@@ -381,7 +472,7 @@ static const struct imx708_reg mode_4608x2592_regs[] = {
381472
{0x3CBE, 0x00},
382473
{0x3CBF, 0x00},
383474
{0x0202, 0x0A}, //REG_COARSE_INTEGRATION_TIME_MSB
384-
{0x0203, 0x29}, //REG_COARSE_INTEGRATION_TIME_LSB (0x94, 0x29)
475+
{0x0203, 0x29}, //REG_COARSE_INTEGRATION_TIME_LSB
385476
{0x0224, 0x01},
386477
{0x0225, 0xF4},
387478
{0x3116, 0x01},
@@ -452,9 +543,6 @@ static const struct imx708_reg mode_2x2binned_regs[] = {
452543
{0x034F, 0x10},
453544
{0x0301, 0x05},
454545
{0x0303, 0x02},
455-
{0x0305, 0x02},
456-
{0x0306, 0x00},
457-
{0x0307, 0x7A},
458546
{0x030B, 0x02},
459547
{0x030D, 0x04},
460548
{0x0310, 0x01},
@@ -546,9 +634,6 @@ static const struct imx708_reg mode_2x2binned_720p_regs[] = {
546634
{0x034F, 0x60},
547635
{0x0301, 0x05},
548636
{0x0303, 0x02},
549-
{0x0305, 0x02},
550-
{0x0306, 0x00},
551-
{0x0307, 0x76},
552637
{0x030B, 0x02},
553638
{0x030D, 0x04},
554639
{0x0310, 0x01},
@@ -640,9 +725,6 @@ static const struct imx708_reg mode_hdr_regs[] = {
640725
{0x034F, 0x10},
641726
{0x0301, 0x05},
642727
{0x0303, 0x02},
643-
{0x0305, 0x02},
644-
{0x0306, 0x00},
645-
{0x0307, 0xA2},
646728
{0x030B, 0x02},
647729
{0x030D, 0x04},
648730
{0x0310, 0x01},
@@ -702,7 +784,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
702784
/* Full resolution. */
703785
.width = 4608,
704786
.height = 2592,
705-
.line_length_pix = 10432,
787+
.line_length_pix = {15648, 10432},
706788
.crop = {
707789
.left = IMX708_PIXEL_ARRAY_LEFT,
708790
.top = IMX708_PIXEL_ARRAY_TOP,
@@ -715,7 +797,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
715797
.num_of_regs = ARRAY_SIZE(mode_4608x2592_regs),
716798
.regs = mode_4608x2592_regs,
717799
},
718-
.pixel_rate = 854400000, //595200000,
800+
.pixel_rates = {595200000, 854400000},
719801
.exposure_lines_min = 8,
720802
.exposure_lines_step = 1,
721803
.hdr = false,
@@ -725,7 +807,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
725807
/* regular 2x2 binned. */
726808
.width = 2304,
727809
.height = 1296,
728-
.line_length_pix = 0x1e90,
810+
.line_length_pix = {7824, 5216},
729811
.crop = {
730812
.left = IMX708_PIXEL_ARRAY_LEFT,
731813
.top = IMX708_PIXEL_ARRAY_TOP,
@@ -738,7 +820,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
738820
.num_of_regs = ARRAY_SIZE(mode_2x2binned_regs),
739821
.regs = mode_2x2binned_regs,
740822
},
741-
.pixel_rate = 585600000,
823+
.pixel_rates = {585600000, 585600000},
742824
.exposure_lines_min = 4,
743825
.exposure_lines_step = 2,
744826
.hdr = false,
@@ -748,7 +830,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
748830
/* 2x2 binned and cropped for 720p. */
749831
.width = 1536,
750832
.height = 864,
751-
.line_length_pix = 0x1460,
833+
.line_length_pix = {5216, 5216},
752834
.crop = {
753835
.left = IMX708_PIXEL_ARRAY_LEFT + 768,
754836
.top = IMX708_PIXEL_ARRAY_TOP + 432,
@@ -761,7 +843,7 @@ static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
761843
.num_of_regs = ARRAY_SIZE(mode_2x2binned_720p_regs),
762844
.regs = mode_2x2binned_720p_regs,
763845
},
764-
.pixel_rate = 566400000,
846+
.pixel_rates = {566400000, 566400000},
765847
.exposure_lines_min = 4,
766848
.exposure_lines_step = 2,
767849
.hdr = false,
@@ -774,7 +856,7 @@ static const struct imx708_mode supported_modes_10bit_hdr[] = {
774856
/* There's only one HDR mode, which is 2x2 downscaled */
775857
.width = 2304,
776858
.height = 1296,
777-
.line_length_pix = 0x1460,
859+
.line_length_pix = {5216, 5216},
778860
.crop = {
779861
.left = IMX708_PIXEL_ARRAY_LEFT,
780862
.top = IMX708_PIXEL_ARRAY_TOP,
@@ -787,7 +869,7 @@ static const struct imx708_mode supported_modes_10bit_hdr[] = {
787869
.num_of_regs = ARRAY_SIZE(mode_hdr_regs),
788870
.regs = mode_hdr_regs,
789871
},
790-
.pixel_rate = 777600000,
872+
.pixel_rates = {777600000, 777600000},
791873
.exposure_lines_min = 8 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO,
792874
.exposure_lines_step = 2 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO,
793875
.hdr = true,
@@ -892,6 +974,8 @@ struct imx708 {
892974
unsigned int long_exp_shift;
893975

894976
unsigned int link_freq_idx;
977+
unsigned int pix_rate_idx;
978+
unsigned int line_length_idx;
895979

896980
/* Two or Four lanes */
897981
u8 lanes;
@@ -1137,20 +1221,32 @@ static int imx708_set_frame_length(struct imx708 *imx708, unsigned int val)
11371221
static void imx708_set_framing_limits(struct imx708 *imx708)
11381222
{
11391223
const struct imx708_mode *mode = imx708->mode;
1140-
unsigned int hblank;
1141-
1142-
__v4l2_ctrl_modify_range(imx708->pixel_rate,
1143-
mode->pixel_rate, mode->pixel_rate,
1144-
1, mode->pixel_rate);
1145-
1146-
/* Update limits and set FPS to default */
1147-
__v4l2_ctrl_modify_range(imx708->vblank, mode->vblank_min,
1148-
((1 << IMX708_LONG_EXP_SHIFT_MAX) *
1149-
IMX708_FRAME_LENGTH_MAX) - mode->height,
1150-
1, mode->vblank_default);
1224+
unsigned int hblank, pix_rate;
1225+
int i;
11511226

1152-
hblank = mode->line_length_pix - mode->width;
1227+
/* Get the line lenth */
1228+
for (i = 0; i < ARRAY_SIZE(line_lengths); i++) {
1229+
if (line_lengths[i] == (imx708->lanes == 2 ?
1230+
imx708->mode->line_length_pix.two_lane :
1231+
imx708->mode->line_length_pix.four_lane)) {
1232+
imx708->line_length_idx = i;
1233+
break;
1234+
}
1235+
}
1236+
hblank = line_lengths[imx708->line_length_idx] - mode->width;
11531237
__v4l2_ctrl_modify_range(imx708->hblank, hblank, hblank, 1, hblank);
1238+
1239+
/* Get the pixel rate */
1240+
for (i = 0; i < ARRAY_SIZE(pixel_rates); i++) {
1241+
if (pixel_rates[i] == (imx708->lanes == 2 ?
1242+
imx708->mode->pixel_rates.two_lane :
1243+
imx708->mode->pixel_rates.four_lane)) {
1244+
imx708->pix_rate_idx = i;
1245+
break;
1246+
}
1247+
}
1248+
pix_rate = pixel_rates[imx708->pix_rate_idx];
1249+
__v4l2_ctrl_modify_range(imx708->pixel_rate, pix_rate, pix_rate, 1, pix_rate);
11541250
}
11551251

11561252
static int imx708_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -1513,7 +1609,7 @@ static int imx708_configure_lanes(struct imx708 *imx708)
15131609
static int imx708_start_streaming(struct imx708 *imx708)
15141610
{
15151611
struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
1516-
const struct imx708_reg_list *reg_list, *freq_regs;
1612+
const struct imx708_reg_list *reg_list, *freq_regs, *pix_rate_regs;
15171613
int i, ret;
15181614
u32 val;
15191615

@@ -1569,6 +1665,23 @@ static int imx708_start_streaming(struct imx708 *imx708)
15691665
return ret;
15701666
}
15711667

1668+
// /* Set the pixel rate */
1669+
// for (i = 0; i < ARRAY_SIZE(pixel_rates); i++) {
1670+
// if (pixel_rates[i] == (imx708->lanes == 2 ?
1671+
// imx708->mode->pixel_rates.two_lane :
1672+
// imx708->mode->pixel_rates.four_lane)) {
1673+
// imx708->pix_rate_idx = i;
1674+
// break;
1675+
// }
1676+
// }
1677+
pix_rate_regs = &pixel_rate_regs[imx708->pix_rate_idx];
1678+
ret = imx708_write_regs(imx708, pix_rate_regs->regs,
1679+
pix_rate_regs->num_of_regs);
1680+
if (ret) {
1681+
dev_err(&client->dev, "%s failed to set pixel rate\n", __func__);
1682+
return ret;
1683+
}
1684+
15721685
/* Update the link frequency registers */
15731686
freq_regs = &link_freq_regs[imx708->link_freq_idx];
15741687
ret = imx708_write_regs(imx708, freq_regs->regs,

0 commit comments

Comments
 (0)