2929
3030/* Register Map */
3131#define VD55G1_REG_MODEL_ID CCI_REG32_LE(0x0000)
32- #define VD55G1_MODEL_ID 0x53354731
32+ #define VD55G1_MODEL_ID_VD55G1 0x53354731 /* Mono */
33+ #define VD55G1_MODEL_ID_VD65G4 0x53354733 /* RGB */
3334#define VD55G1_REG_REVISION CCI_REG16_LE(0x0004)
3435#define VD55G1_REVISION_CCB 0x2020
36+ #define VD55G1_REVISION_BAYER 0x3030
3537#define VD55G1_REG_FWPATCH_REVISION CCI_REG16_LE(0x0012)
3638#define VD55G1_REG_FWPATCH_START_ADDR CCI_REG8(0x2000)
3739#define VD55G1_REG_SYSTEM_FSM CCI_REG8(0x001c)
3840#define VD55G1_SYSTEM_FSM_READY_TO_BOOT 0x01
3941#define VD55G1_SYSTEM_FSM_SW_STBY 0x02
4042#define VD55G1_SYSTEM_FSM_STREAMING 0x03
4143#define VD55G1_REG_BOOT CCI_REG8(0x0200)
42- #define VD55G1_BOOT_PATCH_SETUP 2
44+ #define VD55G1_BOOT_BOOT 1
45+ #define VD55G1_BOOT_PATCH_AND_BOOT 2
4346#define VD55G1_REG_STBY CCI_REG8(0x0201)
4447#define VD55G1_STBY_START_STREAM 1
4548#define VD55G1_REG_STREAMING CCI_REG8(0x0202)
132135#define VD55G1_MIPI_RATE_MIN (250 * MEGA)
133136#define VD55G1_MIPI_RATE_MAX (1200 * MEGA)
134137
135- static const u8 patch_array [] = {
138+ #define VD55G1_MODEL_ID_NAME (id ) \
139+ ((id) == VD55G1_MODEL_ID_VD55G1 ? "vd55g1" : "vd65g4")
140+
141+ static const u8 vd55g1_patch_array [] = {
136142 0x44 , 0x03 , 0x09 , 0x02 , 0xe6 , 0x01 , 0x42 , 0x00 , 0xea , 0x01 , 0x42 , 0x00 ,
137143 0xf0 , 0x01 , 0x42 , 0x00 , 0xe6 , 0x01 , 0x42 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
138144 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
@@ -466,22 +472,24 @@ struct vd55g1_mode {
466472 u32 height ;
467473};
468474
469- struct vd55g1_fmt_desc {
470- u32 code ;
471- u8 bpp ;
472- u8 data_type ;
475+ static const u32 vd55g1_mbus_formats_mono [] = {
476+ MEDIA_BUS_FMT_Y8_1X8 ,
477+ MEDIA_BUS_FMT_Y10_1X10 ,
473478};
474479
475- static const struct vd55g1_fmt_desc vd55g1_mbus_codes [] = {
480+ /* Format order is : no flip, hflip, vflip, both */
481+ static const u32 vd55g1_mbus_formats_bayer [][4 ] = {
476482 {
477- .code = MEDIA_BUS_FMT_Y8_1X8 ,
478- .bpp = 8 ,
479- .data_type = MIPI_CSI2_DT_RAW8 ,
483+ MEDIA_BUS_FMT_SRGGB8_1X8 ,
484+ MEDIA_BUS_FMT_SGRBG8_1X8 ,
485+ MEDIA_BUS_FMT_SGBRG8_1X8 ,
486+ MEDIA_BUS_FMT_SBGGR8_1X8 ,
480487 },
481488 {
482- .code = MEDIA_BUS_FMT_Y10_1X10 ,
483- .bpp = 10 ,
484- .data_type = MIPI_CSI2_DT_RAW10 ,
489+ MEDIA_BUS_FMT_SRGGB10_1X10 ,
490+ MEDIA_BUS_FMT_SGRBG10_1X10 ,
491+ MEDIA_BUS_FMT_SGBRG10_1X10 ,
492+ MEDIA_BUS_FMT_SBGGR10_1X10 ,
485493 },
486494};
487495
@@ -524,6 +532,7 @@ struct vd55g1_vblank_limits {
524532
525533struct vd55g1 {
526534 struct device * dev ;
535+ unsigned int id ;
527536 struct v4l2_subdev sd ;
528537 struct media_pad pad ;
529538 struct regulator_bulk_data supplies [ARRAY_SIZE (vd55g1_supply_name )];
@@ -572,27 +581,78 @@ static inline struct vd55g1 *ctrl_to_vd55g1(struct v4l2_ctrl *ctrl)
572581 return to_vd55g1 (sd );
573582}
574583
575- static const struct vd55g1_fmt_desc * vd55g1_get_fmt_desc (struct vd55g1 * sensor ,
576- u32 code )
584+ static unsigned int vd55g1_get_fmt_bpp (u32 code )
577585{
578- unsigned int i ;
586+ switch (code ) {
587+ case MEDIA_BUS_FMT_Y8_1X8 :
588+ case MEDIA_BUS_FMT_SRGGB8_1X8 :
589+ case MEDIA_BUS_FMT_SGRBG8_1X8 :
590+ case MEDIA_BUS_FMT_SGBRG8_1X8 :
591+ case MEDIA_BUS_FMT_SBGGR8_1X8 :
592+ default :
593+ return 8 ;
594+
595+ case MEDIA_BUS_FMT_Y10_1X10 :
596+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
597+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
598+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
599+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
600+ return 10 ;
601+ }
602+ }
603+
604+ static unsigned int vd55g1_get_fmt_data_type (u32 code )
605+ {
606+ switch (code ) {
607+ case MEDIA_BUS_FMT_Y8_1X8 :
608+ case MEDIA_BUS_FMT_SRGGB8_1X8 :
609+ case MEDIA_BUS_FMT_SGRBG8_1X8 :
610+ case MEDIA_BUS_FMT_SGBRG8_1X8 :
611+ case MEDIA_BUS_FMT_SBGGR8_1X8 :
612+ default :
613+ return MIPI_CSI2_DT_RAW8 ;
614+
615+ case MEDIA_BUS_FMT_Y10_1X10 :
616+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
617+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
618+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
619+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
620+ return MIPI_CSI2_DT_RAW10 ;
621+ }
622+ }
623+
624+ static u32 vd55g1_get_fmt_code (struct vd55g1 * sensor , u32 code )
625+ {
626+ unsigned int i , j ;
579627
580- for (i = 0 ; i < ARRAY_SIZE (vd55g1_mbus_codes ); i ++ ) {
581- if (vd55g1_mbus_codes [i ].code == code )
582- return & vd55g1_mbus_codes [i ];
628+ if (sensor -> id == VD55G1_MODEL_ID_VD55G1 )
629+ return code ;
630+
631+ for (i = 0 ; i < ARRAY_SIZE (vd55g1_mbus_formats_bayer ); i ++ ) {
632+ for (j = 0 ; j < ARRAY_SIZE (vd55g1_mbus_formats_bayer [i ]); j ++ ) {
633+ if (vd55g1_mbus_formats_bayer [i ][j ] == code )
634+ goto adapt_bayer_pattern ;
635+ }
583636 }
637+ dev_warn (sensor -> dev , "Unsupported mbus format\n" );
584638
585- /* Should never happen */
586- dev_warn (sensor -> dev , "Unsupported code %d. default to 8 bpp\n" , code );
639+ return code ;
640+
641+ adapt_bayer_pattern :
642+ j = 0 ;
643+ /* In first init_state() call, controls might not be initialized yet */
644+ if (sensor -> hflip_ctrl && sensor -> vflip_ctrl ) {
645+ j = (sensor -> hflip_ctrl -> val ? 1 : 0 ) +
646+ (sensor -> vflip_ctrl -> val ? 2 : 0 );
647+ }
587648
588- return & vd55g1_mbus_codes [ 0 ];
649+ return vd55g1_mbus_formats_bayer [ i ][ j ];
589650}
590651
591652static s32 vd55g1_get_pixel_rate (struct vd55g1 * sensor ,
592653 struct v4l2_mbus_framefmt * format )
593654{
594- return sensor -> mipi_rate /
595- vd55g1_get_fmt_desc (sensor , format -> code )-> bpp ;
655+ return sensor -> mipi_rate / vd55g1_get_fmt_bpp (format -> code );
596656}
597657
598658static unsigned int vd55g1_get_hblank_min (struct vd55g1 * sensor ,
@@ -605,7 +665,7 @@ static unsigned int vd55g1_get_hblank_min(struct vd55g1 *sensor,
605665
606666 /* MIPI required time */
607667 mipi_req_line_time = (crop -> width *
608- vd55g1_get_fmt_desc ( sensor , format -> code )-> bpp +
668+ vd55g1_get_fmt_bpp ( format -> code ) +
609669 VD55G1_MIPI_MARGIN ) /
610670 (sensor -> mipi_rate / MEGA );
611671 mipi_req_line_length = mipi_req_line_time * sensor -> pixel_clock /
@@ -887,7 +947,7 @@ static void vd55g1_update_pad_fmt(struct vd55g1 *sensor,
887947 const struct vd55g1_mode * mode , u32 code ,
888948 struct v4l2_mbus_framefmt * fmt )
889949{
890- fmt -> code = code ;
950+ fmt -> code = vd55g1_get_fmt_code ( sensor , code ) ;
891951 fmt -> width = mode -> width ;
892952 fmt -> height = mode -> height ;
893953 fmt -> colorspace = V4L2_COLORSPACE_RAW ;
@@ -951,10 +1011,9 @@ static int vd55g1_set_framefmt(struct vd55g1 *sensor,
9511011 int ret = 0 ;
9521012
9531013 vd55g1_write (sensor , VD55G1_REG_FORMAT_CTRL ,
954- vd55g1_get_fmt_desc ( sensor , format -> code )-> bpp , & ret );
1014+ vd55g1_get_fmt_bpp ( format -> code ), & ret );
9551015 vd55g1_write (sensor , VD55G1_REG_OIF_IMG_CTRL ,
956- vd55g1_get_fmt_desc (sensor , format -> code )-> data_type ,
957- & ret );
1016+ vd55g1_get_fmt_data_type (format -> code ), & ret );
9581017
9591018 switch (crop -> width / format -> width ) {
9601019 case 1 :
@@ -1114,26 +1173,45 @@ static int vd55g1_patch(struct vd55g1 *sensor)
11141173 u64 patch ;
11151174 int ret = 0 ;
11161175
1117- vd55g1_write_array (sensor , VD55G1_REG_FWPATCH_START_ADDR ,
1118- sizeof (patch_array ), patch_array , & ret );
1119- vd55g1_write (sensor , VD55G1_REG_BOOT , VD55G1_BOOT_PATCH_SETUP , & ret );
1120- vd55g1_poll_reg (sensor , VD55G1_REG_BOOT , 0 , & ret );
1121- if (ret ) {
1122- dev_err (sensor -> dev , "Failed to apply patch\n" );
1123- return ret ;
1124- }
1176+ /* vd55g1 needs a patch while vd65g4 does not */
1177+ if (sensor -> id == VD55G1_MODEL_ID_VD55G1 ) {
1178+ vd55g1_write_array (sensor , VD55G1_REG_FWPATCH_START_ADDR ,
1179+ sizeof (vd55g1_patch_array ),
1180+ vd55g1_patch_array , & ret );
1181+ vd55g1_write (sensor , VD55G1_REG_BOOT ,
1182+ VD55G1_BOOT_PATCH_AND_BOOT , & ret );
1183+ vd55g1_poll_reg (sensor , VD55G1_REG_BOOT , 0 , & ret );
1184+ if (ret ) {
1185+ dev_err (sensor -> dev , "Failed to apply patch\n" );
1186+ return ret ;
1187+ }
11251188
1126- vd55g1_read (sensor , VD55G1_REG_FWPATCH_REVISION , & patch , & ret );
1127- if (patch != (VD55G1_FWPATCH_REVISION_MAJOR << 8 ) +
1128- VD55G1_FWPATCH_REVISION_MINOR ) {
1129- dev_err (sensor -> dev , "Bad patch version expected %d.%d got %d.%d\n" ,
1130- VD55G1_FWPATCH_REVISION_MAJOR ,
1131- VD55G1_FWPATCH_REVISION_MINOR ,
1189+ vd55g1_read (sensor , VD55G1_REG_FWPATCH_REVISION , & patch , & ret );
1190+ if (patch != (VD55G1_FWPATCH_REVISION_MAJOR << 8 ) +
1191+ VD55G1_FWPATCH_REVISION_MINOR ) {
1192+ dev_err (sensor -> dev , "Bad patch version expected %d.%d got %d.%d\n" ,
1193+ VD55G1_FWPATCH_REVISION_MAJOR ,
1194+ VD55G1_FWPATCH_REVISION_MINOR ,
1195+ (u8 )(patch >> 8 ), (u8 )(patch & 0xff ));
1196+ return - ENODEV ;
1197+ }
1198+ dev_dbg (sensor -> dev , "patch %d.%d applied\n" ,
11321199 (u8 )(patch >> 8 ), (u8 )(patch & 0xff ));
1133- return - ENODEV ;
1200+
1201+ } else {
1202+ vd55g1_write (sensor , VD55G1_REG_BOOT , VD55G1_BOOT_BOOT , & ret );
1203+ vd55g1_poll_reg (sensor , VD55G1_REG_BOOT , 0 , & ret );
1204+ if (ret ) {
1205+ dev_err (sensor -> dev , "Failed to boot\n" );
1206+ return ret ;
1207+ }
1208+ }
1209+
1210+ ret = vd55g1_wait_state (sensor , VD55G1_SYSTEM_FSM_SW_STBY , NULL );
1211+ if (ret ) {
1212+ dev_err (sensor -> dev , "Sensor waiting after boot failed\n" );
1213+ return ret ;
11341214 }
1135- dev_dbg (sensor -> dev , "patch %d.%d applied\n" ,
1136- (u8 )(patch >> 8 ), (u8 )(patch & 0xff ));
11371215
11381216 return 0 ;
11391217}
@@ -1165,10 +1243,19 @@ static int vd55g1_enum_mbus_code(struct v4l2_subdev *sd,
11651243 struct v4l2_subdev_state * sd_state ,
11661244 struct v4l2_subdev_mbus_code_enum * code )
11671245{
1168- if ( code -> index >= ARRAY_SIZE ( vd55g1_mbus_codes ))
1169- return - EINVAL ;
1246+ struct vd55g1 * sensor = to_vd55g1 ( sd );
1247+ u32 base_code ;
11701248
1171- code -> code = vd55g1_mbus_codes [code -> index ].code ;
1249+ if (sensor -> id == VD55G1_MODEL_ID_VD55G1 ) {
1250+ if (code -> index >= ARRAY_SIZE (vd55g1_mbus_formats_mono ))
1251+ return - EINVAL ;
1252+ base_code = vd55g1_mbus_formats_mono [code -> index ];
1253+ } else {
1254+ if (code -> index >= ARRAY_SIZE (vd55g1_mbus_formats_bayer ))
1255+ return - EINVAL ;
1256+ base_code = vd55g1_mbus_formats_bayer [code -> index ][0 ];
1257+ }
1258+ code -> code = vd55g1_get_fmt_code (sensor , base_code );
11721259
11731260 return 0 ;
11741261}
@@ -1275,7 +1362,7 @@ static int vd55g1_init_state(struct v4l2_subdev *sd,
12751362 return ret ;
12761363
12771364 vd55g1_update_pad_fmt (sensor , & vd55g1_supported_modes [VD55G1_MODE_DEF ],
1278- vd55g1_mbus_codes [ VD55G1_MBUS_CODE_DEF ]. code ,
1365+ vd55g1_get_fmt_code ( sensor , VD55G1_MBUS_CODE_DEF ) ,
12791366 & fmt .format );
12801367
12811368 return vd55g1_set_pad_fmt (sd , sd_state , & fmt );
@@ -1285,9 +1372,16 @@ static int vd55g1_enum_frame_size(struct v4l2_subdev *sd,
12851372 struct v4l2_subdev_state * sd_state ,
12861373 struct v4l2_subdev_frame_size_enum * fse )
12871374{
1375+ struct vd55g1 * sensor = to_vd55g1 (sd );
1376+ u32 code ;
1377+
12881378 if (fse -> index >= ARRAY_SIZE (vd55g1_supported_modes ))
12891379 return - EINVAL ;
12901380
1381+ code = vd55g1_get_fmt_code (sensor , fse -> code );
1382+ if (fse -> code != code )
1383+ return - EINVAL ;
1384+
12911385 fse -> min_width = vd55g1_supported_modes [fse -> index ].width ;
12921386 fse -> max_width = fse -> min_width ;
12931387 fse -> min_height = vd55g1_supported_modes [fse -> index ].height ;
@@ -1463,8 +1557,12 @@ static int vd55g1_init_ctrls(struct vd55g1 *sensor)
14631557 /* Flip cluster */
14641558 sensor -> hflip_ctrl = v4l2_ctrl_new_std (hdl , ops , V4L2_CID_HFLIP ,
14651559 0 , 1 , 1 , 0 );
1560+ if (sensor -> hflip_ctrl )
1561+ sensor -> hflip_ctrl -> flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT ;
14661562 sensor -> vflip_ctrl = v4l2_ctrl_new_std (hdl , ops , V4L2_CID_VFLIP ,
14671563 0 , 1 , 1 , 0 );
1564+ if (sensor -> vflip_ctrl )
1565+ sensor -> vflip_ctrl -> flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT ;
14681566 v4l2_ctrl_cluster (2 , & sensor -> hflip_ctrl );
14691567
14701568 /* Exposition cluster */
@@ -1548,26 +1646,34 @@ static int vd55g1_init_ctrls(struct vd55g1 *sensor)
15481646
15491647static int vd55g1_detect (struct vd55g1 * sensor )
15501648{
1551- u64 device_rev ;
1552- u64 id ;
1649+ unsigned int dt_id = ( uintptr_t ) device_get_match_data ( sensor -> dev ) ;
1650+ u64 rev , id ;
15531651 int ret ;
15541652
15551653 ret = vd55g1_read (sensor , VD55G1_REG_MODEL_ID , & id , NULL );
15561654 if (ret )
15571655 return ret ;
15581656
1559- if (id != VD55G1_MODEL_ID ) {
1560- dev_warn (sensor -> dev , "Unsupported sensor id %x\n" , (u32 )id );
1657+ if (id != VD55G1_MODEL_ID_VD55G1 && id != VD55G1_MODEL_ID_VD65G4 ) {
1658+ dev_warn (sensor -> dev , "Unsupported sensor id 0x%x\n" ,
1659+ (u32 )id );
1660+ return - ENODEV ;
1661+ }
1662+ if (id != dt_id ) {
1663+ dev_err (sensor -> dev , "Probed sensor %s and device tree definition (%s) mismatch" ,
1664+ VD55G1_MODEL_ID_NAME (id ), VD55G1_MODEL_ID_NAME (dt_id ));
15611665 return - ENODEV ;
15621666 }
1667+ sensor -> id = id ;
15631668
1564- ret = vd55g1_read (sensor , VD55G1_REG_REVISION , & device_rev , NULL );
1669+ ret = vd55g1_read (sensor , VD55G1_REG_REVISION , & rev , NULL );
15651670 if (ret )
15661671 return ret ;
15671672
1568- if (device_rev != VD55G1_REVISION_CCB ) {
1569- dev_err (sensor -> dev , "Unsupported sensor revision (0x%x)\n" ,
1570- (u16 )device_rev );
1673+ if ((id == VD55G1_MODEL_ID_VD55G1 && rev != VD55G1_REVISION_CCB ) &&
1674+ (id == VD55G1_MODEL_ID_VD65G4 && rev != VD55G1_REVISION_BAYER )) {
1675+ dev_err (sensor -> dev , "Unsupported sensor revision 0x%x for sensor %s\n" ,
1676+ (u16 )rev , VD55G1_MODEL_ID_NAME (id ));
15711677 return - ENODEV ;
15721678 }
15731679
@@ -1616,13 +1722,6 @@ static int vd55g1_power_on(struct device *dev)
16161722 goto disable_clock ;
16171723 }
16181724
1619- ret = vd55g1_wait_state (sensor , VD55G1_SYSTEM_FSM_SW_STBY , NULL );
1620- if (ret ) {
1621- dev_err (dev , "Sensor waiting after patch failed %d\n" ,
1622- ret );
1623- goto disable_clock ;
1624- }
1625-
16261725 return 0 ;
16271726
16281727disable_clock :
@@ -1934,7 +2033,8 @@ static void vd55g1_remove(struct i2c_client *client)
19342033}
19352034
19362035static const struct of_device_id vd55g1_dt_ids [] = {
1937- { .compatible = "st,vd55g1" },
2036+ { .compatible = "st,vd55g1" , .data = (void * )VD55G1_MODEL_ID_VD55G1 },
2037+ { .compatible = "st,vd65g4" , .data = (void * )VD55G1_MODEL_ID_VD65G4 },
19382038 { /* sentinel */ }
19392039};
19402040MODULE_DEVICE_TABLE (of , vd55g1_dt_ids );
0 commit comments