@@ -40,6 +40,14 @@ struct vimc_cap_device {
4040 struct media_pipeline pipe ;
4141};
4242
43+ static const struct v4l2_pix_format fmt_default = {
44+ .width = 640 ,
45+ .height = 480 ,
46+ .pixelformat = V4L2_PIX_FMT_RGB24 ,
47+ .field = V4L2_FIELD_NONE ,
48+ .colorspace = V4L2_COLORSPACE_DEFAULT ,
49+ };
50+
4351struct vimc_cap_buffer {
4452 /*
4553 * struct vb2_v4l2_buffer must be the first element
@@ -73,7 +81,7 @@ static void vimc_cap_get_format(struct vimc_ent_device *ved,
7381 * fmt = vcap -> format ;
7482}
7583
76- static int vimc_cap_fmt_vid_cap (struct file * file , void * priv ,
84+ static int vimc_cap_g_fmt_vid_cap (struct file * file , void * priv ,
7785 struct v4l2_format * f )
7886{
7987 struct vimc_cap_device * vcap = video_drvdata (file );
@@ -83,16 +91,98 @@ static int vimc_cap_fmt_vid_cap(struct file *file, void *priv,
8391 return 0 ;
8492}
8593
94+ static int vimc_cap_try_fmt_vid_cap (struct file * file , void * priv ,
95+ struct v4l2_format * f )
96+ {
97+ struct v4l2_pix_format * format = & f -> fmt .pix ;
98+ const struct vimc_pix_map * vpix ;
99+
100+ format -> width = clamp_t (u32 , format -> width , VIMC_FRAME_MIN_WIDTH ,
101+ VIMC_FRAME_MAX_WIDTH ) & ~1 ;
102+ format -> height = clamp_t (u32 , format -> height , VIMC_FRAME_MIN_HEIGHT ,
103+ VIMC_FRAME_MAX_HEIGHT ) & ~1 ;
104+
105+ /* Don't accept a pixelformat that is not on the table */
106+ vpix = vimc_pix_map_by_pixelformat (format -> pixelformat );
107+ if (!vpix ) {
108+ format -> pixelformat = fmt_default .pixelformat ;
109+ vpix = vimc_pix_map_by_pixelformat (format -> pixelformat );
110+ }
111+ /* TODO: Add support for custom bytesperline values */
112+ format -> bytesperline = format -> width * vpix -> bpp ;
113+ format -> sizeimage = format -> bytesperline * format -> height ;
114+
115+ if (format -> field == V4L2_FIELD_ANY )
116+ format -> field = fmt_default .field ;
117+
118+ vimc_colorimetry_clamp (format );
119+
120+ return 0 ;
121+ }
122+
123+ static int vimc_cap_s_fmt_vid_cap (struct file * file , void * priv ,
124+ struct v4l2_format * f )
125+ {
126+ struct vimc_cap_device * vcap = video_drvdata (file );
127+
128+ /* Do not change the format while stream is on */
129+ if (vb2_is_busy (& vcap -> queue ))
130+ return - EBUSY ;
131+
132+ vimc_cap_try_fmt_vid_cap (file , priv , f );
133+
134+ dev_dbg (vcap -> vdev .v4l2_dev -> dev , "%s: format update: "
135+ "old:%dx%d (0x%x, %d, %d, %d, %d) "
136+ "new:%dx%d (0x%x, %d, %d, %d, %d)\n" , vcap -> vdev .name ,
137+ /* old */
138+ vcap -> format .width , vcap -> format .height ,
139+ vcap -> format .pixelformat , vcap -> format .colorspace ,
140+ vcap -> format .quantization , vcap -> format .xfer_func ,
141+ vcap -> format .ycbcr_enc ,
142+ /* new */
143+ f -> fmt .pix .width , f -> fmt .pix .height ,
144+ f -> fmt .pix .pixelformat , f -> fmt .pix .colorspace ,
145+ f -> fmt .pix .quantization , f -> fmt .pix .xfer_func ,
146+ f -> fmt .pix .ycbcr_enc );
147+
148+ vcap -> format = f -> fmt .pix ;
149+
150+ return 0 ;
151+ }
152+
86153static int vimc_cap_enum_fmt_vid_cap (struct file * file , void * priv ,
87154 struct v4l2_fmtdesc * f )
88155{
89- struct vimc_cap_device * vcap = video_drvdata ( file );
156+ const struct vimc_pix_map * vpix = vimc_pix_map_by_index ( f -> index );
90157
91- if (f -> index > 0 )
158+ if (! vpix )
92159 return - EINVAL ;
93160
94- /* We only support one format for now */
95- f -> pixelformat = vcap -> format .pixelformat ;
161+ f -> pixelformat = vpix -> pixelformat ;
162+
163+ return 0 ;
164+ }
165+
166+ static int vimc_cap_enum_framesizes (struct file * file , void * fh ,
167+ struct v4l2_frmsizeenum * fsize )
168+ {
169+ const struct vimc_pix_map * vpix ;
170+
171+ if (fsize -> index )
172+ return - EINVAL ;
173+
174+ /* Only accept code in the pix map table */
175+ vpix = vimc_pix_map_by_code (fsize -> pixel_format );
176+ if (!vpix )
177+ return - EINVAL ;
178+
179+ fsize -> type = V4L2_FRMSIZE_TYPE_CONTINUOUS ;
180+ fsize -> stepwise .min_width = VIMC_FRAME_MIN_WIDTH ;
181+ fsize -> stepwise .max_width = VIMC_FRAME_MAX_WIDTH ;
182+ fsize -> stepwise .min_height = VIMC_FRAME_MIN_HEIGHT ;
183+ fsize -> stepwise .max_height = VIMC_FRAME_MAX_HEIGHT ;
184+ fsize -> stepwise .step_width = 2 ;
185+ fsize -> stepwise .step_height = 2 ;
96186
97187 return 0 ;
98188}
@@ -110,10 +200,11 @@ static const struct v4l2_file_operations vimc_cap_fops = {
110200static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = {
111201 .vidioc_querycap = vimc_cap_querycap ,
112202
113- .vidioc_g_fmt_vid_cap = vimc_cap_fmt_vid_cap ,
114- .vidioc_s_fmt_vid_cap = vimc_cap_fmt_vid_cap ,
115- .vidioc_try_fmt_vid_cap = vimc_cap_fmt_vid_cap ,
203+ .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap ,
204+ .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap ,
205+ .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap ,
116206 .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap ,
207+ .vidioc_enum_framesizes = vimc_cap_enum_framesizes ,
117208
118209 .vidioc_reqbufs = vb2_ioctl_reqbufs ,
119210 .vidioc_create_bufs = vb2_ioctl_create_bufs ,
@@ -360,15 +451,9 @@ struct vimc_ent_device *vimc_cap_create(struct v4l2_device *v4l2_dev,
360451 INIT_LIST_HEAD (& vcap -> buf_list );
361452 spin_lock_init (& vcap -> qlock );
362453
363- /* Set the frame format (this is hardcoded for now) */
364- vcap -> format .width = 640 ;
365- vcap -> format .height = 480 ;
366- vcap -> format .pixelformat = V4L2_PIX_FMT_RGB24 ;
367- vcap -> format .field = V4L2_FIELD_NONE ;
368- vcap -> format .colorspace = V4L2_COLORSPACE_SRGB ;
369-
454+ /* Set default frame format */
455+ vcap -> format = fmt_default ;
370456 vpix = vimc_pix_map_by_pixelformat (vcap -> format .pixelformat );
371-
372457 vcap -> format .bytesperline = vcap -> format .width * vpix -> bpp ;
373458 vcap -> format .sizeimage = vcap -> format .bytesperline *
374459 vcap -> format .height ;
0 commit comments