126
126
#define IMX219_PIXEL_ARRAY_WIDTH 3280U
127
127
#define IMX219_PIXEL_ARRAY_HEIGHT 2464U
128
128
129
+ /* Embedded metadata stream structure */
130
+ #define IMX219_EMBEDDED_LINE_WIDTH 16384
131
+ #define IMX219_NUM_EMBEDDED_LINES 1
132
+
133
+ enum pad_types {
134
+ IMAGE_PAD ,
135
+ METADATA_PAD ,
136
+ NUM_PADS
137
+ };
138
+
129
139
struct imx219_reg {
130
140
u16 address ;
131
141
u8 val ;
@@ -448,7 +458,7 @@ static const struct imx219_mode supported_modes[] = {
448
458
449
459
struct imx219 {
450
460
struct v4l2_subdev sd ;
451
- struct media_pad pad ;
461
+ struct media_pad pad [ NUM_PADS ] ;
452
462
453
463
struct v4l2_mbus_framefmt fmt ;
454
464
@@ -598,18 +608,26 @@ static void imx219_set_default_format(struct imx219 *imx219)
598
608
static int imx219_open (struct v4l2_subdev * sd , struct v4l2_subdev_fh * fh )
599
609
{
600
610
struct imx219 * imx219 = to_imx219 (sd );
601
- struct v4l2_mbus_framefmt * try_fmt =
602
- v4l2_subdev_get_try_format (sd , fh -> state , 0 );
611
+ struct v4l2_mbus_framefmt * try_fmt_img =
612
+ v4l2_subdev_get_try_format (sd , fh -> state , IMAGE_PAD );
613
+ struct v4l2_mbus_framefmt * try_fmt_meta =
614
+ v4l2_subdev_get_try_format (sd , fh -> state , METADATA_PAD );
603
615
struct v4l2_rect * try_crop ;
604
616
605
617
mutex_lock (& imx219 -> mutex );
606
618
607
619
/* Initialize try_fmt */
608
- try_fmt -> width = supported_modes [0 ].width ;
609
- try_fmt -> height = supported_modes [0 ].height ;
610
- try_fmt -> code = imx219_get_format_code (imx219 ,
611
- MEDIA_BUS_FMT_SRGGB10_1X10 );
612
- try_fmt -> field = V4L2_FIELD_NONE ;
620
+ try_fmt_img -> width = supported_modes [0 ].width ;
621
+ try_fmt_img -> height = supported_modes [0 ].height ;
622
+ try_fmt_img -> code = imx219_get_format_code (imx219 ,
623
+ MEDIA_BUS_FMT_SRGGB10_1X10 );
624
+ try_fmt_img -> field = V4L2_FIELD_NONE ;
625
+
626
+ /* Initialize try_fmt for the embedded metadata pad */
627
+ try_fmt_meta -> width = IMX219_EMBEDDED_LINE_WIDTH ;
628
+ try_fmt_meta -> height = IMX219_NUM_EMBEDDED_LINES ;
629
+ try_fmt_meta -> code = MEDIA_BUS_FMT_SENSOR_DATA ;
630
+ try_fmt_meta -> field = V4L2_FIELD_NONE ;
613
631
614
632
/* Initialize try_crop rectangle. */
615
633
try_crop = v4l2_subdev_get_try_crop (sd , fh -> state , 0 );
@@ -723,12 +741,22 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
723
741
{
724
742
struct imx219 * imx219 = to_imx219 (sd );
725
743
726
- if (code -> index >= ( ARRAY_SIZE ( codes ) / 4 ) )
744
+ if (code -> pad >= NUM_PADS )
727
745
return - EINVAL ;
728
746
729
- mutex_lock (& imx219 -> mutex );
730
- code -> code = imx219_get_format_code (imx219 , codes [code -> index * 4 ]);
731
- mutex_unlock (& imx219 -> mutex );
747
+ if (code -> pad == IMAGE_PAD ) {
748
+ if (code -> index >= (ARRAY_SIZE (codes ) / 4 ))
749
+ return - EINVAL ;
750
+
751
+ mutex_lock (& imx219 -> mutex );
752
+ code -> code = imx219_get_format_code (imx219 , codes [code -> index * 4 ]);
753
+ mutex_unlock (& imx219 -> mutex );
754
+ } else {
755
+ if (code -> index > 0 )
756
+ return - EINVAL ;
757
+
758
+ code -> code = MEDIA_BUS_FMT_SENSOR_DATA ;
759
+ }
732
760
733
761
return 0 ;
734
762
}
@@ -740,19 +768,32 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
740
768
struct imx219 * imx219 = to_imx219 (sd );
741
769
u32 code ;
742
770
743
- if (fse -> index >= ARRAY_SIZE ( supported_modes ) )
771
+ if (fse -> pad >= NUM_PADS )
744
772
return - EINVAL ;
745
773
746
- mutex_lock (& imx219 -> mutex );
747
- code = imx219_get_format_code (imx219 , fse -> code );
748
- mutex_unlock (& imx219 -> mutex );
749
- if (fse -> code != code )
750
- return - EINVAL ;
774
+ if (fse -> pad == IMAGE_PAD ) {
775
+ if (fse -> index >= ARRAY_SIZE (supported_modes ))
776
+ return - EINVAL ;
777
+
778
+ mutex_lock (& imx219 -> mutex );
779
+ code = imx219_get_format_code (imx219 , fse -> code );
780
+ mutex_unlock (& imx219 -> mutex );
781
+ if (fse -> code != code )
782
+ return - EINVAL ;
783
+
784
+ fse -> min_width = supported_modes [fse -> index ].width ;
785
+ fse -> max_width = fse -> min_width ;
786
+ fse -> min_height = supported_modes [fse -> index ].height ;
787
+ fse -> max_height = fse -> min_height ;
788
+ } else {
789
+ if (fse -> code != MEDIA_BUS_FMT_SENSOR_DATA || fse -> index > 0 )
790
+ return - EINVAL ;
751
791
752
- fse -> min_width = supported_modes [fse -> index ].width ;
753
- fse -> max_width = fse -> min_width ;
754
- fse -> min_height = supported_modes [fse -> index ].height ;
755
- fse -> max_height = fse -> min_height ;
792
+ fse -> min_width = IMX219_EMBEDDED_LINE_WIDTH ;
793
+ fse -> max_width = fse -> min_width ;
794
+ fse -> min_height = IMX219_NUM_EMBEDDED_LINES ;
795
+ fse -> max_height = fse -> min_height ;
796
+ }
756
797
757
798
return 0 ;
758
799
}
@@ -767,31 +808,49 @@ static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
767
808
fmt -> xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT (fmt -> colorspace );
768
809
}
769
810
770
- static void imx219_update_pad_format (struct imx219 * imx219 ,
771
- const struct imx219_mode * mode ,
772
- struct v4l2_subdev_format * fmt )
811
+ static void imx219_update_image_pad_format (struct imx219 * imx219 ,
812
+ const struct imx219_mode * mode ,
813
+ struct v4l2_subdev_format * fmt )
773
814
{
774
815
fmt -> format .width = mode -> width ;
775
816
fmt -> format .height = mode -> height ;
776
817
fmt -> format .field = V4L2_FIELD_NONE ;
777
818
imx219_reset_colorspace (& fmt -> format );
778
819
}
779
820
821
+ static void imx219_update_metadata_pad_format (struct v4l2_subdev_format * fmt )
822
+ {
823
+ fmt -> format .width = IMX219_EMBEDDED_LINE_WIDTH ;
824
+ fmt -> format .height = IMX219_NUM_EMBEDDED_LINES ;
825
+ fmt -> format .code = MEDIA_BUS_FMT_SENSOR_DATA ;
826
+ fmt -> format .field = V4L2_FIELD_NONE ;
827
+ }
828
+
780
829
static int __imx219_get_pad_format (struct imx219 * imx219 ,
781
830
struct v4l2_subdev_state * sd_state ,
782
831
struct v4l2_subdev_format * fmt )
783
832
{
833
+ if (fmt -> pad >= NUM_PADS )
834
+ return - EINVAL ;
835
+
784
836
if (fmt -> which == V4L2_SUBDEV_FORMAT_TRY ) {
785
837
struct v4l2_mbus_framefmt * try_fmt =
786
838
v4l2_subdev_get_try_format (& imx219 -> sd , sd_state ,
787
839
fmt -> pad );
788
840
/* update the code which could change due to vflip or hflip: */
789
- try_fmt -> code = imx219_get_format_code (imx219 , try_fmt -> code );
841
+ try_fmt -> code = fmt -> pad == IMAGE_PAD ?
842
+ imx219_get_format_code (imx219 , try_fmt -> code ) :
843
+ MEDIA_BUS_FMT_SENSOR_DATA ;
790
844
fmt -> format = * try_fmt ;
791
845
} else {
792
- imx219_update_pad_format (imx219 , imx219 -> mode , fmt );
793
- fmt -> format .code = imx219_get_format_code (imx219 ,
794
- imx219 -> fmt .code );
846
+ if (fmt -> pad == IMAGE_PAD ) {
847
+ imx219_update_image_pad_format (imx219 , imx219 -> mode ,
848
+ fmt );
849
+ fmt -> format .code = imx219_get_format_code (imx219 ,
850
+ imx219 -> fmt .code );
851
+ } else {
852
+ imx219_update_metadata_pad_format (fmt );
853
+ }
795
854
}
796
855
797
856
return 0 ;
@@ -821,59 +880,78 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
821
880
int exposure_max , exposure_def , hblank ;
822
881
unsigned int i ;
823
882
824
- mutex_lock (& imx219 -> mutex );
825
-
826
- for (i = 0 ; i < ARRAY_SIZE (codes ); i ++ )
827
- if (codes [i ] == fmt -> format .code )
828
- break ;
829
- if (i >= ARRAY_SIZE (codes ))
830
- i = 0 ;
883
+ if (fmt -> pad >= NUM_PADS )
884
+ return - EINVAL ;
831
885
832
- /* Bayer order varies with flips */
833
- fmt -> format .code = imx219_get_format_code (imx219 , codes [i ]);
886
+ mutex_lock (& imx219 -> mutex );
834
887
835
- mode = v4l2_find_nearest_size (supported_modes ,
836
- ARRAY_SIZE (supported_modes ),
837
- width , height ,
838
- fmt -> format .width , fmt -> format .height );
839
- imx219_update_pad_format (imx219 , mode , fmt );
840
- if (fmt -> which == V4L2_SUBDEV_FORMAT_TRY ) {
841
- framefmt = v4l2_subdev_get_try_format (sd , sd_state , fmt -> pad );
842
- * framefmt = fmt -> format ;
843
- } else if (imx219 -> mode != mode ||
844
- imx219 -> fmt .code != fmt -> format .code ) {
845
- u32 prev_hts = imx219 -> mode -> width + imx219 -> hblank -> val ;
846
-
847
- imx219 -> fmt = fmt -> format ;
848
- imx219 -> mode = mode ;
849
- /* Update limits and set FPS to default */
850
- __v4l2_ctrl_modify_range (imx219 -> vblank , IMX219_VBLANK_MIN ,
851
- IMX219_VTS_MAX - mode -> height , 1 ,
852
- mode -> vts_def - mode -> height );
853
- __v4l2_ctrl_s_ctrl (imx219 -> vblank ,
854
- mode -> vts_def - mode -> height );
855
- /* Update max exposure while meeting expected vblanking */
856
- exposure_max = mode -> vts_def - 4 ;
857
- exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT ) ?
858
- exposure_max : IMX219_EXPOSURE_DEFAULT ;
859
- __v4l2_ctrl_modify_range (imx219 -> exposure ,
860
- imx219 -> exposure -> minimum ,
861
- exposure_max , imx219 -> exposure -> step ,
862
- exposure_def );
863
- /*
864
- * Retain PPL setting from previous mode so that the
865
- * line time does not change on a mode change.
866
- * Limits have to be recomputed as the controls define
867
- * the blanking only, so PPL values need to have the
868
- * mode width subtracted.
869
- */
870
- hblank = prev_hts - mode -> width ;
871
- __v4l2_ctrl_modify_range (imx219 -> hblank ,
872
- IMX219_PPL_MIN - mode -> width ,
873
- IMX219_PPL_MAX - mode -> width ,
874
- 1 ,
875
- IMX219_PPL_MIN - mode -> width );
876
- __v4l2_ctrl_s_ctrl (imx219 -> hblank , hblank );
888
+ if (fmt -> pad == IMAGE_PAD ) {
889
+ for (i = 0 ; i < ARRAY_SIZE (codes ); i ++ )
890
+ if (codes [i ] == fmt -> format .code )
891
+ break ;
892
+ if (i >= ARRAY_SIZE (codes ))
893
+ i = 0 ;
894
+
895
+ /* Bayer order varies with flips */
896
+ fmt -> format .code = imx219_get_format_code (imx219 , codes [i ]);
897
+
898
+ mode = v4l2_find_nearest_size (supported_modes ,
899
+ ARRAY_SIZE (supported_modes ),
900
+ width , height ,
901
+ fmt -> format .width ,
902
+ fmt -> format .height );
903
+ imx219_update_image_pad_format (imx219 , mode , fmt );
904
+ if (fmt -> which == V4L2_SUBDEV_FORMAT_TRY ) {
905
+ framefmt = v4l2_subdev_get_try_format (sd , sd_state ,
906
+ fmt -> pad );
907
+ * framefmt = fmt -> format ;
908
+ } else if (imx219 -> mode != mode ||
909
+ imx219 -> fmt .code != fmt -> format .code ) {
910
+ u32 prev_hts = imx219 -> mode -> width + imx219 -> hblank -> val ;
911
+
912
+ imx219 -> fmt = fmt -> format ;
913
+ imx219 -> mode = mode ;
914
+ /* Update limits and set FPS to default */
915
+ __v4l2_ctrl_modify_range (imx219 -> vblank ,
916
+ IMX219_VBLANK_MIN ,
917
+ IMX219_VTS_MAX - mode -> height ,
918
+ 1 ,
919
+ mode -> vts_def - mode -> height );
920
+ __v4l2_ctrl_s_ctrl (imx219 -> vblank ,
921
+ mode -> vts_def - mode -> height );
922
+ /* Update max exposure while meeting expected vblanking */
923
+ exposure_max = mode -> vts_def - 4 ;
924
+ exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT ) ?
925
+ exposure_max : IMX219_EXPOSURE_DEFAULT ;
926
+ __v4l2_ctrl_modify_range (imx219 -> exposure ,
927
+ imx219 -> exposure -> minimum ,
928
+ exposure_max ,
929
+ imx219 -> exposure -> step ,
930
+ exposure_def );
931
+ /*
932
+ * Retain PPL setting from previous mode so that the
933
+ * line time does not change on a mode change.
934
+ * Limits have to be recomputed as the controls define
935
+ * the blanking only, so PPL values need to have the
936
+ * mode width subtracted.
937
+ */
938
+ hblank = prev_hts - mode -> width ;
939
+ __v4l2_ctrl_modify_range (imx219 -> hblank ,
940
+ IMX219_PPL_MIN - mode -> width ,
941
+ IMX219_PPL_MAX - mode -> width ,
942
+ 1 ,
943
+ IMX219_PPL_MIN - mode -> width );
944
+ __v4l2_ctrl_s_ctrl (imx219 -> hblank , hblank );
945
+ }
946
+ } else {
947
+ if (fmt -> which == V4L2_SUBDEV_FORMAT_TRY ) {
948
+ framefmt = v4l2_subdev_get_try_format (sd , sd_state ,
949
+ fmt -> pad );
950
+ * framefmt = fmt -> format ;
951
+ } else {
952
+ /* Only one embedded data mode is supported */
953
+ imx219_update_metadata_pad_format (fmt );
954
+ }
877
955
}
878
956
879
957
mutex_unlock (& imx219 -> mutex );
@@ -1490,12 +1568,13 @@ static int imx219_probe(struct i2c_client *client)
1490
1568
imx219 -> sd .entity .function = MEDIA_ENT_F_CAM_SENSOR ;
1491
1569
1492
1570
/* Initialize source pad */
1493
- imx219 -> pad .flags = MEDIA_PAD_FL_SOURCE ;
1571
+ imx219 -> pad [IMAGE_PAD ].flags = MEDIA_PAD_FL_SOURCE ;
1572
+ imx219 -> pad [METADATA_PAD ].flags = MEDIA_PAD_FL_SOURCE ;
1494
1573
1495
1574
/* Initialize default format */
1496
1575
imx219_set_default_format (imx219 );
1497
1576
1498
- ret = media_entity_pads_init (& imx219 -> sd .entity , 1 , & imx219 -> pad );
1577
+ ret = media_entity_pads_init (& imx219 -> sd .entity , NUM_PADS , imx219 -> pad );
1499
1578
if (ret ) {
1500
1579
dev_err (dev , "failed to init entity pads: %d\n" , ret );
1501
1580
goto error_handler_free ;
0 commit comments