@@ -67,6 +67,8 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable)
67
67
struct imgu_media_pipe * imgu_pipe = & imgu -> imgu_pipe [pipe ];
68
68
69
69
dev_dbg (dev , "%s %d for pipe %u" , __func__ , enable , pipe );
70
+ /* grab ctrl after streamon and return after off */
71
+ v4l2_ctrl_grab (imgu_sd -> ctrl , enable );
70
72
71
73
if (!enable ) {
72
74
imgu_sd -> active = false;
@@ -94,7 +96,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable)
94
96
if (imgu_pipe -> nodes [IMGU_NODE_VF ].enabled )
95
97
css_pipe -> vf_output_en = true;
96
98
97
- if (imgu_sd -> running_mode == IPU3_RUNNING_MODE_VIDEO )
99
+ if (atomic_read ( & imgu_sd -> running_mode ) == IPU3_RUNNING_MODE_VIDEO )
98
100
css_pipe -> pipe_id = IPU3_CSS_PIPE_ID_VIDEO ;
99
101
else
100
102
css_pipe -> pipe_id = IPU3_CSS_PIPE_ID_CAPTURE ;
@@ -666,7 +668,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node,
666
668
if (imgu_pipe -> nodes [IMGU_NODE_VF ].enabled )
667
669
css_pipe -> vf_output_en = true;
668
670
669
- if (imgu_sd -> running_mode == IPU3_RUNNING_MODE_VIDEO )
671
+ if (atomic_read ( & imgu_sd -> running_mode ) == IPU3_RUNNING_MODE_VIDEO )
670
672
css_pipe -> pipe_id = IPU3_CSS_PIPE_ID_VIDEO ;
671
673
else
672
674
css_pipe -> pipe_id = IPU3_CSS_PIPE_ID_CAPTURE ;
@@ -897,6 +899,11 @@ static struct v4l2_subdev_internal_ops imgu_subdev_internal_ops = {
897
899
.open = imgu_subdev_open ,
898
900
};
899
901
902
+ static const struct v4l2_subdev_core_ops imgu_subdev_core_ops = {
903
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event ,
904
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe ,
905
+ };
906
+
900
907
static const struct v4l2_subdev_video_ops imgu_subdev_video_ops = {
901
908
.s_stream = imgu_subdev_s_stream ,
902
909
};
@@ -910,6 +917,7 @@ static const struct v4l2_subdev_pad_ops imgu_subdev_pad_ops = {
910
917
};
911
918
912
919
static const struct v4l2_subdev_ops imgu_subdev_ops = {
920
+ .core = & imgu_subdev_core_ops ,
913
921
.video = & imgu_subdev_video_ops ,
914
922
.pad = & imgu_subdev_pad_ops ,
915
923
};
@@ -1003,6 +1011,44 @@ static const struct v4l2_ioctl_ops imgu_v4l2_meta_ioctl_ops = {
1003
1011
.vidioc_expbuf = vb2_ioctl_expbuf ,
1004
1012
};
1005
1013
1014
+ static int imgu_sd_s_ctrl (struct v4l2_ctrl * ctrl )
1015
+ {
1016
+ struct imgu_v4l2_subdev * imgu_sd =
1017
+ container_of (ctrl -> handler , struct imgu_v4l2_subdev , ctrl_handler );
1018
+ struct imgu_device * imgu = v4l2_get_subdevdata (& imgu_sd -> subdev );
1019
+ struct device * dev = & imgu -> pci_dev -> dev ;
1020
+
1021
+ dev_dbg (dev , "set val %d to ctrl 0x%8x for subdev %u" ,
1022
+ ctrl -> val , ctrl -> id , imgu_sd -> pipe );
1023
+
1024
+ switch (ctrl -> id ) {
1025
+ case V4L2_CID_INTEL_IPU3_MODE :
1026
+ atomic_set (& imgu_sd -> running_mode , ctrl -> val );
1027
+ return 0 ;
1028
+ default :
1029
+ return - EINVAL ;
1030
+ }
1031
+ }
1032
+
1033
+ static const struct v4l2_ctrl_ops imgu_subdev_ctrl_ops = {
1034
+ .s_ctrl = imgu_sd_s_ctrl ,
1035
+ };
1036
+
1037
+ static const char * const imgu_ctrl_mode_strings [] = {
1038
+ "Video mode" ,
1039
+ "Still mode" ,
1040
+ };
1041
+
1042
+ static const struct v4l2_ctrl_config imgu_subdev_ctrl_mode = {
1043
+ .ops = & imgu_subdev_ctrl_ops ,
1044
+ .id = V4L2_CID_INTEL_IPU3_MODE ,
1045
+ .name = "IPU3 Pipe Mode" ,
1046
+ .type = V4L2_CTRL_TYPE_MENU ,
1047
+ .max = ARRAY_SIZE (imgu_ctrl_mode_strings ) - 1 ,
1048
+ .def = IPU3_RUNNING_MODE_VIDEO ,
1049
+ .qmenu = imgu_ctrl_mode_strings ,
1050
+ };
1051
+
1006
1052
/******************** Framework registration ********************/
1007
1053
1008
1054
/* helper function to config node's video properties */
@@ -1048,6 +1094,7 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu,
1048
1094
unsigned int pipe )
1049
1095
{
1050
1096
int i , r ;
1097
+ struct v4l2_ctrl_handler * hdl = & imgu_sd -> ctrl_handler ;
1051
1098
struct imgu_media_pipe * imgu_pipe = & imgu -> imgu_pipe [pipe ];
1052
1099
1053
1100
/* Initialize subdev media entity */
@@ -1068,12 +1115,21 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu,
1068
1115
v4l2_subdev_init (& imgu_sd -> subdev , & imgu_subdev_ops );
1069
1116
imgu_sd -> subdev .entity .function = MEDIA_ENT_F_PROC_VIDEO_STATISTICS ;
1070
1117
imgu_sd -> subdev .internal_ops = & imgu_subdev_internal_ops ;
1071
- imgu_sd -> subdev .flags = V4L2_SUBDEV_FL_HAS_DEVNODE ;
1118
+ imgu_sd -> subdev .flags = V4L2_SUBDEV_FL_HAS_DEVNODE |
1119
+ V4L2_SUBDEV_FL_HAS_EVENTS ;
1072
1120
snprintf (imgu_sd -> subdev .name , sizeof (imgu_sd -> subdev .name ),
1073
- "%s %s " , IMGU_NAME , pipe ? "still" : "video" );
1121
+ "%s %u " , IMGU_NAME , pipe );
1074
1122
v4l2_set_subdevdata (& imgu_sd -> subdev , imgu );
1075
- imgu_sd -> running_mode =
1076
- pipe ? IPU3_RUNNING_MODE_STILL : IPU3_RUNNING_MODE_VIDEO ;
1123
+ atomic_set (& imgu_sd -> running_mode , IPU3_RUNNING_MODE_VIDEO );
1124
+ v4l2_ctrl_handler_init (hdl , 1 );
1125
+ imgu_sd -> subdev .ctrl_handler = hdl ;
1126
+ imgu_sd -> ctrl = v4l2_ctrl_new_custom (hdl , & imgu_subdev_ctrl_mode , NULL );
1127
+ if (hdl -> error ) {
1128
+ r = hdl -> error ;
1129
+ dev_err (& imgu -> pci_dev -> dev ,
1130
+ "failed to create subdev v4l2 ctrl with err %d" , r );
1131
+ goto fail_subdev ;
1132
+ }
1077
1133
r = v4l2_device_register_subdev (& imgu -> v4l2_dev , & imgu_sd -> subdev );
1078
1134
if (r ) {
1079
1135
dev_err (& imgu -> pci_dev -> dev ,
@@ -1085,6 +1141,7 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu,
1085
1141
return 0 ;
1086
1142
1087
1143
fail_subdev :
1144
+ v4l2_ctrl_handler_free (imgu_sd -> subdev .ctrl_handler );
1088
1145
media_entity_cleanup (& imgu_sd -> subdev .entity );
1089
1146
1090
1147
return r ;
@@ -1179,8 +1236,8 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe,
1179
1236
}
1180
1237
1181
1238
/* Initialize vdev */
1182
- snprintf (vdev -> name , sizeof (vdev -> name ), "%s %s %s" ,
1183
- IMGU_NAME , pipe ? "still" : "video" , node -> name );
1239
+ snprintf (vdev -> name , sizeof (vdev -> name ), "%s %u %s" ,
1240
+ IMGU_NAME , pipe , node -> name );
1184
1241
vdev -> release = video_device_release_empty ;
1185
1242
vdev -> fops = & imgu_v4l2_fops ;
1186
1243
vdev -> lock = & node -> lock ;
@@ -1255,6 +1312,7 @@ static void imgu_v4l2_subdev_cleanup(struct imgu_device *imgu, unsigned int i)
1255
1312
struct imgu_media_pipe * imgu_pipe = & imgu -> imgu_pipe [i ];
1256
1313
1257
1314
v4l2_device_unregister_subdev (& imgu_pipe -> imgu_sd .subdev );
1315
+ v4l2_ctrl_handler_free (imgu_pipe -> imgu_sd .subdev .ctrl_handler );
1258
1316
media_entity_cleanup (& imgu_pipe -> imgu_sd .subdev .entity );
1259
1317
}
1260
1318
0 commit comments