Skip to content

Commit 41a7fe6

Browse files
committed
media: imx477: Support 10 or 12 bit readout for all modes
The sensor supports readout as 10 or 12 bit. As we are now computing the horizontal blanking limits dynamically, adding support for both readout modes falls out trivially, so add them both. Signed-off-by: Dave Stevenson <[email protected]>
1 parent e8e3630 commit 41a7fe6

File tree

1 file changed

+35
-65
lines changed

1 file changed

+35
-65
lines changed

drivers/media/i2c/imx477.c

Lines changed: 35 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
6060

6161
#define IMX477_REG_ORIENTATION CCI_REG8(0x101)
6262

63+
#define IMX477_REG_CSI_DT_FMT_H CCI_REG8(0x0112)
64+
#define IMX477_REG_CSI_DT_FMT_L CCI_REG8(0x0113)
65+
6366
#define IMX477_XCLK_FREQ 24000000
6467

6568
#define IMX477_DEFAULT_LINK_FREQ 450000000
@@ -103,6 +106,7 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
103106
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
104107
#define IMX477_DGTL_GAIN_STEP 1
105108

109+
#define IMX477_REG_IOP_PXCK_DIV CCI_REG8(0x0309)
106110
#define IMX477_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
107111
#define IMX477_IOP_SYSCK_DIV 0x02
108112
#define IMX477_REG_IOP_PREDIV CCI_REG8(0x030d)
@@ -142,6 +146,7 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
142146
#define IMX477_REG_XVS_IO_CTRL CCI_REG8(0x3040)
143147
#define IMX477_REG_EXTOUT_EN CCI_REG8(0x4b81)
144148

149+
#define IMX477_REG_ADBIT_MODE CCI_REG8(0x3f0d)
145150
/* Temperature sensor */
146151
#define IMX477_REG_TEMP_SEN_CTL CCI_REG8(0x0138)
147152

@@ -490,8 +495,6 @@ static const struct cci_reg_sequence mode_common_regs[] = {
490495
{CCI_REG8(0xb21f), 0x04},
491496
{CCI_REG8(0xb35c), 0x00},
492497
{CCI_REG8(0xb35e), 0x08},
493-
{CCI_REG8(0x0112), 0x0c},
494-
{CCI_REG8(0x0113), 0x0c},
495498
{CCI_REG8(0x0114), 0x01},
496499
{CCI_REG8(0x0350), 0x00},
497500
{CCI_REG8(0xbcf1), 0x02},
@@ -557,7 +560,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
557560
{CCI_REG8(0x0901), 0x11},
558561
{CCI_REG8(0x3c01), 0x03},
559562
{CCI_REG8(0x3c02), 0xa2},
560-
{CCI_REG8(0x3f0d), 0x01},
561563
{CCI_REG8(0x5748), 0x07},
562564
{CCI_REG8(0x5749), 0xff},
563565
{CCI_REG8(0x574a), 0x00},
@@ -593,7 +595,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
593595
{CCI_REG8(0x0305), 0x04},
594596
{CCI_REG8(0x0306), 0x01},
595597
{CCI_REG8(0x0307), 0x5e},
596-
{CCI_REG8(0x0309), 0x0c},
597598
{CCI_REG8(0xe04c), 0x00},
598599
{CCI_REG8(0xe04d), 0x7f},
599600
{CCI_REG8(0xe04e), 0x00},
@@ -622,7 +623,6 @@ static const struct cci_reg_sequence mode_4056x2160_regs[] = {
622623
{CCI_REG8(0x0901), 0x11},
623624
{CCI_REG8(0x3c01), 0x03},
624625
{CCI_REG8(0x3c02), 0xa2},
625-
{CCI_REG8(0x3f0d), 0x01},
626626
{CCI_REG8(0x5748), 0x07},
627627
{CCI_REG8(0x5749), 0xff},
628628
{CCI_REG8(0x574a), 0x00},
@@ -680,7 +680,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
680680
{CCI_REG8(0x0901), 0x22},
681681
{CCI_REG8(0x3c01), 0x03},
682682
{CCI_REG8(0x3c02), 0xa2},
683-
{CCI_REG8(0x3f0d), 0x01},
684683
{CCI_REG8(0x5748), 0x07},
685684
{CCI_REG8(0x5749), 0xff},
686685
{CCI_REG8(0x574a), 0x00},
@@ -711,7 +710,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
711710
{CCI_REG8(0x0305), 0x04},
712711
{CCI_REG8(0x0306), 0x01},
713712
{CCI_REG8(0x0307), 0x5e},
714-
{CCI_REG8(0x0309), 0x0c},
715713
{CCI_REG8(0xe04c), 0x00},
716714
{CCI_REG8(0xe04d), 0x7f},
717715
{CCI_REG8(0xe04e), 0x00},
@@ -734,7 +732,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
734732
{CCI_REG8(0x0901), 0x22},
735733
{CCI_REG8(0x3c01), 0x03},
736734
{CCI_REG8(0x3c02), 0xa2},
737-
{CCI_REG8(0x3f0d), 0x01},
738735
{CCI_REG8(0x5748), 0x07},
739736
{CCI_REG8(0x5749), 0xff},
740737
{CCI_REG8(0x574a), 0x00},
@@ -765,7 +762,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
765762
{CCI_REG8(0x0305), 0x04},
766763
{CCI_REG8(0x0306), 0x01},
767764
{CCI_REG8(0x0307), 0x5e},
768-
{CCI_REG8(0x0309), 0x0c},
769765
{CCI_REG8(0xe04c), 0x00},
770766
{CCI_REG8(0xe04d), 0x7f},
771767
{CCI_REG8(0xe04e), 0x00},
@@ -788,8 +784,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
788784
{CCI_REG8(0x9a4b), 0x06},
789785
{CCI_REG8(0x9a4c), 0x06},
790786
{CCI_REG8(0x9a4d), 0x06},
791-
{CCI_REG8(0x0112), 0x0a},
792-
{CCI_REG8(0x0113), 0x0a},
793787
{CCI_REG8(0x0114), 0x01},
794788
{CCI_REG8(0x0340), 0x04},
795789
{CCI_REG8(0x0341), 0x1a},
@@ -821,7 +815,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
821815
{CCI_REG8(0x3c00), 0x00},
822816
{CCI_REG8(0x3c01), 0x01},
823817
{CCI_REG8(0x3c02), 0x9c},
824-
{CCI_REG8(0x3f0d), 0x00},
825818
{CCI_REG8(0x5748), 0x00},
826819
{CCI_REG8(0x5749), 0x00},
827820
{CCI_REG8(0x574a), 0x00},
@@ -857,7 +850,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
857850
{CCI_REG8(0x0305), 0x02},
858851
{CCI_REG8(0x0306), 0x00},
859852
{CCI_REG8(0x0307), 0xaf},
860-
{CCI_REG8(0x0309), 0x0a},
861853
{CCI_REG8(0xe04c), 0x00},
862854
{CCI_REG8(0xe04d), 0x5f},
863855
{CCI_REG8(0xe04e), 0x00},
@@ -867,7 +859,7 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
867859
};
868860

869861
/* Mode configs */
870-
static const struct imx477_mode supported_modes_12bit[] = {
862+
static const struct imx477_mode supported_modes[] = {
871863
{
872864
/* 12MPix 10fps mode */
873865
.width = 4056,
@@ -931,10 +923,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
931923
.num_of_regs = ARRAY_SIZE(mode_2028x1080_regs),
932924
.regs = mode_2028x1080_regs,
933925
},
934-
}
935-
};
936-
937-
static const struct imx477_mode supported_modes_10bit[] = {
926+
},
938927
{
939928
/* 120fps. 2x2 binned and cropped */
940929
.width = 1332,
@@ -1081,33 +1070,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
10811070
return container_of(_sd, struct imx477, sd);
10821071
}
10831072

1084-
static inline void get_mode_table(unsigned int code,
1085-
const struct imx477_mode **mode_list,
1086-
unsigned int *num_modes)
1087-
{
1088-
switch (code) {
1089-
/* 12-bit */
1090-
case MEDIA_BUS_FMT_SRGGB12_1X12:
1091-
case MEDIA_BUS_FMT_SGRBG12_1X12:
1092-
case MEDIA_BUS_FMT_SGBRG12_1X12:
1093-
case MEDIA_BUS_FMT_SBGGR12_1X12:
1094-
*mode_list = supported_modes_12bit;
1095-
*num_modes = ARRAY_SIZE(supported_modes_12bit);
1096-
break;
1097-
/* 10-bit */
1098-
case MEDIA_BUS_FMT_SRGGB10_1X10:
1099-
case MEDIA_BUS_FMT_SGRBG10_1X10:
1100-
case MEDIA_BUS_FMT_SGBRG10_1X10:
1101-
case MEDIA_BUS_FMT_SBGGR10_1X10:
1102-
*mode_list = supported_modes_10bit;
1103-
*num_modes = ARRAY_SIZE(supported_modes_10bit);
1104-
break;
1105-
default:
1106-
*mode_list = NULL;
1107-
*num_modes = 0;
1108-
}
1109-
}
1110-
11111073
/* Get bayer order based on flip setting. */
11121074
static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
11131075
{
@@ -1131,7 +1093,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
11311093
static void imx477_set_default_format(struct imx477 *imx477)
11321094
{
11331095
/* Set default mode to max resolution */
1134-
imx477->mode = &supported_modes_12bit[0];
1096+
imx477->mode = &supported_modes[0];
11351097
imx477->fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12;
11361098
}
11371099

@@ -1165,8 +1127,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
11651127
mutex_lock(&imx477->mutex);
11661128

11671129
/* Initialize try_fmt for the image pad */
1168-
try_fmt_img->width = supported_modes_12bit[0].width;
1169-
try_fmt_img->height = supported_modes_12bit[0].height;
1130+
try_fmt_img->width = supported_modes[0].width;
1131+
try_fmt_img->height = supported_modes[0].height;
11701132
try_fmt_img->code = imx477_get_format_code(imx477,
11711133
MEDIA_BUS_FMT_SRGGB12_1X12);
11721134
try_fmt_img->field = V4L2_FIELD_NONE;
@@ -1342,12 +1304,7 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
13421304
return -EINVAL;
13431305

13441306
if (fse->pad == IMAGE_PAD) {
1345-
const struct imx477_mode *mode_list;
1346-
unsigned int num_modes;
1347-
1348-
get_mode_table(fse->code, &mode_list, &num_modes);
1349-
1350-
if (fse->index >= num_modes)
1307+
if (fse->index >= ARRAY_SIZE(supported_modes))
13511308
return -EINVAL;
13521309

13531310
mutex_lock(&imx477->mutex);
@@ -1357,9 +1314,9 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
13571314
if (fse->code != code)
13581315
return -EINVAL;
13591316

1360-
fse->min_width = mode_list[fse->index].width;
1317+
fse->min_width = supported_modes[fse->index].width;
13611318
fse->max_width = fse->min_width;
1362-
fse->min_height = mode_list[fse->index].height;
1319+
fse->min_height = supported_modes[fse->index].height;
13631320
fse->max_height = fse->min_height;
13641321
} else {
13651322
if (fse->code != MEDIA_BUS_FMT_SENSOR_DATA || fse->index > 0)
@@ -1465,6 +1422,16 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14651422
/* Allow 500pixel clocks for HS<>LP transitions (approx 0.6usecs) */
14661423
line_length_min += 500;
14671424

1425+
/*
1426+
* 1332x990 12bit mode appears to need additional horizontal blanking
1427+
* compared to all other modes. Empirically determined setting with
1428+
* link freq of 750MHz where it still gives valid images. The limit
1429+
* leaves all other modes unchanged as their line times are inherently
1430+
* greater.
1431+
*/
1432+
if (bpp == 12)
1433+
line_length_min = max(line_length_min, 1332 + 4600);
1434+
14681435
hblank_min = line_length_min - mode->width;
14691436
__v4l2_ctrl_modify_range(imx477->hblank, hblank_min,
14701437
IMX477_LINE_LENGTH_MAX, 1, hblank_min);
@@ -1485,17 +1452,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
14851452
mutex_lock(&imx477->mutex);
14861453

14871454
if (fmt->pad == IMAGE_PAD) {
1488-
const struct imx477_mode *mode_list;
1489-
unsigned int num_modes;
1490-
14911455
/* Bayer order varies with flips */
14921456
fmt->format.code = imx477_get_format_code(imx477,
14931457
fmt->format.code);
14941458

1495-
get_mode_table(fmt->format.code, &mode_list, &num_modes);
1496-
1497-
mode = v4l2_find_nearest_size(mode_list,
1498-
num_modes,
1459+
mode = v4l2_find_nearest_size(supported_modes,
1460+
ARRAY_SIZE(supported_modes),
14991461
width, height,
15001462
fmt->format.width,
15011463
fmt->format.height);
@@ -1504,7 +1466,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
15041466
framefmt = v4l2_subdev_state_get_format(sd_state,
15051467
fmt->pad);
15061468
*framefmt = fmt->format;
1507-
} else if (imx477->mode != mode) {
1469+
} else if (imx477->mode != mode ||
1470+
imx477->fmt_code != fmt->format.code) {
15081471
imx477->mode = mode;
15091472
imx477->fmt_code = fmt->format.code;
15101473
imx477_set_framing_limits(imx477);
@@ -1585,7 +1548,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
15851548
const struct imx477_reg_list *extra_regs;
15861549
unsigned int fst_width;
15871550
unsigned int fst_mult;
1588-
int ret, tm;
1551+
int ret, tm, bpp;
15891552

15901553
if (!imx477->common_regs_written) {
15911554
ret = cci_multi_reg_write(imx477->regmap, mode_common_regs,
@@ -1653,6 +1616,13 @@ static int imx477_start_streaming(struct imx477 *imx477)
16531616
// FLASH_TRIG_RS
16541617
cci_write(imx477->regmap, CCI_REG8(0x0c1B), !!fstrobe_enable, &ret);
16551618

1619+
bpp = imx477_get_bpp(imx477->fmt_code);
1620+
cci_write(imx477->regmap, IMX477_REG_CSI_DT_FMT_H, bpp, &ret);
1621+
cci_write(imx477->regmap, IMX477_REG_CSI_DT_FMT_L, bpp, &ret);
1622+
cci_write(imx477->regmap, IMX477_REG_IOP_PXCK_DIV, bpp, &ret);
1623+
cci_write(imx477->regmap, IMX477_REG_ADBIT_MODE, bpp == 12 ? 1 : 0,
1624+
&ret);
1625+
16561626
/* Set on-sensor DPC. */
16571627
cci_write(imx477->regmap, CCI_REG8(0x0b05), !!dpc_enable, &ret);
16581628
cci_write(imx477->regmap, CCI_REG8(0x0b06), !!dpc_enable, &ret);

0 commit comments

Comments
 (0)