V4L/DVB (6811): media-video-usbvision-add-mutex_unlock-to-error-paths-fix
[linux-2.6] / drivers / media / video / cx2341x.c
1 /*
2  * cx2341x - generic code for cx23415/6 based devices
3  *
4  * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21
22 #include <linux/module.h>
23 #include <linux/errno.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/types.h>
27 #include <linux/videodev2.h>
28
29 #include <media/tuner.h>
30 #include <media/cx2341x.h>
31 #include <media/v4l2-common.h>
32
33 MODULE_DESCRIPTION("cx23415/6 driver");
34 MODULE_AUTHOR("Hans Verkuil");
35 MODULE_LICENSE("GPL");
36
37 static int debug;
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "Debug level (0-1)");
40
41 const u32 cx2341x_mpeg_ctrls[] = {
42         V4L2_CID_MPEG_CLASS,
43         V4L2_CID_MPEG_STREAM_TYPE,
44         V4L2_CID_MPEG_STREAM_VBI_FMT,
45         V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
46         V4L2_CID_MPEG_AUDIO_ENCODING,
47         V4L2_CID_MPEG_AUDIO_L2_BITRATE,
48         V4L2_CID_MPEG_AUDIO_MODE,
49         V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
50         V4L2_CID_MPEG_AUDIO_EMPHASIS,
51         V4L2_CID_MPEG_AUDIO_CRC,
52         V4L2_CID_MPEG_AUDIO_MUTE,
53         V4L2_CID_MPEG_VIDEO_ENCODING,
54         V4L2_CID_MPEG_VIDEO_ASPECT,
55         V4L2_CID_MPEG_VIDEO_B_FRAMES,
56         V4L2_CID_MPEG_VIDEO_GOP_SIZE,
57         V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
58         V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
59         V4L2_CID_MPEG_VIDEO_BITRATE,
60         V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
61         V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
62         V4L2_CID_MPEG_VIDEO_MUTE,
63         V4L2_CID_MPEG_VIDEO_MUTE_YUV,
64         V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
65         V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
66         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
67         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
68         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
69         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
70         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
71         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
72         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
73         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
74         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
75         V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
76         0
77 };
78 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
79
80
81 /* Map the control ID to the correct field in the cx2341x_mpeg_params
82    struct. Return -EINVAL if the ID is unknown, else return 0. */
83 static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
84                 struct v4l2_ext_control *ctrl)
85 {
86         switch (ctrl->id) {
87         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
88                 ctrl->value = params->audio_sampling_freq;
89                 break;
90         case V4L2_CID_MPEG_AUDIO_ENCODING:
91                 ctrl->value = params->audio_encoding;
92                 break;
93         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
94                 ctrl->value = params->audio_l2_bitrate;
95                 break;
96         case V4L2_CID_MPEG_AUDIO_MODE:
97                 ctrl->value = params->audio_mode;
98                 break;
99         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
100                 ctrl->value = params->audio_mode_extension;
101                 break;
102         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
103                 ctrl->value = params->audio_emphasis;
104                 break;
105         case V4L2_CID_MPEG_AUDIO_CRC:
106                 ctrl->value = params->audio_crc;
107                 break;
108         case V4L2_CID_MPEG_AUDIO_MUTE:
109                 ctrl->value = params->audio_mute;
110                 break;
111         case V4L2_CID_MPEG_VIDEO_ENCODING:
112                 ctrl->value = params->video_encoding;
113                 break;
114         case V4L2_CID_MPEG_VIDEO_ASPECT:
115                 ctrl->value = params->video_aspect;
116                 break;
117         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
118                 ctrl->value = params->video_b_frames;
119                 break;
120         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
121                 ctrl->value = params->video_gop_size;
122                 break;
123         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
124                 ctrl->value = params->video_gop_closure;
125                 break;
126         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
127                 ctrl->value = params->video_bitrate_mode;
128                 break;
129         case V4L2_CID_MPEG_VIDEO_BITRATE:
130                 ctrl->value = params->video_bitrate;
131                 break;
132         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
133                 ctrl->value = params->video_bitrate_peak;
134                 break;
135         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
136                 ctrl->value = params->video_temporal_decimation;
137                 break;
138         case V4L2_CID_MPEG_VIDEO_MUTE:
139                 ctrl->value = params->video_mute;
140                 break;
141         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
142                 ctrl->value = params->video_mute_yuv;
143                 break;
144         case V4L2_CID_MPEG_STREAM_TYPE:
145                 ctrl->value = params->stream_type;
146                 break;
147         case V4L2_CID_MPEG_STREAM_VBI_FMT:
148                 ctrl->value = params->stream_vbi_fmt;
149                 break;
150         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
151                 ctrl->value = params->video_spatial_filter_mode;
152                 break;
153         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
154                 ctrl->value = params->video_spatial_filter;
155                 break;
156         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
157                 ctrl->value = params->video_luma_spatial_filter_type;
158                 break;
159         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
160                 ctrl->value = params->video_chroma_spatial_filter_type;
161                 break;
162         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
163                 ctrl->value = params->video_temporal_filter_mode;
164                 break;
165         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
166                 ctrl->value = params->video_temporal_filter;
167                 break;
168         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
169                 ctrl->value = params->video_median_filter_type;
170                 break;
171         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
172                 ctrl->value = params->video_luma_median_filter_top;
173                 break;
174         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
175                 ctrl->value = params->video_luma_median_filter_bottom;
176                 break;
177         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
178                 ctrl->value = params->video_chroma_median_filter_top;
179                 break;
180         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
181                 ctrl->value = params->video_chroma_median_filter_bottom;
182                 break;
183         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
184                 ctrl->value = params->stream_insert_nav_packets;
185                 break;
186         default:
187                 return -EINVAL;
188         }
189         return 0;
190 }
191
192 /* Map the control ID to the correct field in the cx2341x_mpeg_params
193    struct. Return -EINVAL if the ID is unknown, else return 0. */
194 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
195                 struct v4l2_ext_control *ctrl)
196 {
197         switch (ctrl->id) {
198         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
199                 if (busy)
200                         return -EBUSY;
201                 params->audio_sampling_freq = ctrl->value;
202                 break;
203         case V4L2_CID_MPEG_AUDIO_ENCODING:
204                 params->audio_encoding = ctrl->value;
205                 break;
206         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
207                 if (busy)
208                         return -EBUSY;
209                 params->audio_l2_bitrate = ctrl->value;
210                 break;
211         case V4L2_CID_MPEG_AUDIO_MODE:
212                 params->audio_mode = ctrl->value;
213                 break;
214         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
215                 params->audio_mode_extension = ctrl->value;
216                 break;
217         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
218                 params->audio_emphasis = ctrl->value;
219                 break;
220         case V4L2_CID_MPEG_AUDIO_CRC:
221                 params->audio_crc = ctrl->value;
222                 break;
223         case V4L2_CID_MPEG_AUDIO_MUTE:
224                 params->audio_mute = ctrl->value;
225                 break;
226         case V4L2_CID_MPEG_VIDEO_ASPECT:
227                 params->video_aspect = ctrl->value;
228                 break;
229         case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
230                 int b = ctrl->value + 1;
231                 int gop = params->video_gop_size;
232                 params->video_b_frames = ctrl->value;
233                 params->video_gop_size = b * ((gop + b - 1) / b);
234                 /* Max GOP size = 34 */
235                 while (params->video_gop_size > 34)
236                         params->video_gop_size -= b;
237                 break;
238         }
239         case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
240                 int b = params->video_b_frames + 1;
241                 int gop = ctrl->value;
242                 params->video_gop_size = b * ((gop + b - 1) / b);
243                 /* Max GOP size = 34 */
244                 while (params->video_gop_size > 34)
245                         params->video_gop_size -= b;
246                 ctrl->value = params->video_gop_size;
247                 break;
248         }
249         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
250                 params->video_gop_closure = ctrl->value;
251                 break;
252         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
253                 if (busy)
254                         return -EBUSY;
255                 /* MPEG-1 only allows CBR */
256                 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
257                     ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
258                         return -EINVAL;
259                 params->video_bitrate_mode = ctrl->value;
260                 break;
261         case V4L2_CID_MPEG_VIDEO_BITRATE:
262                 if (busy)
263                         return -EBUSY;
264                 params->video_bitrate = ctrl->value;
265                 break;
266         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
267                 if (busy)
268                         return -EBUSY;
269                 params->video_bitrate_peak = ctrl->value;
270                 break;
271         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
272                 params->video_temporal_decimation = ctrl->value;
273                 break;
274         case V4L2_CID_MPEG_VIDEO_MUTE:
275                 params->video_mute = (ctrl->value != 0);
276                 break;
277         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
278                 params->video_mute_yuv = ctrl->value;
279                 break;
280         case V4L2_CID_MPEG_STREAM_TYPE:
281                 if (busy)
282                         return -EBUSY;
283                 params->stream_type = ctrl->value;
284                 params->video_encoding =
285                     (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
286                      params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
287                         V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
288                         V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
289                 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
290                         /* MPEG-1 implies CBR */
291                         params->video_bitrate_mode =
292                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
293                 break;
294         case V4L2_CID_MPEG_STREAM_VBI_FMT:
295                 params->stream_vbi_fmt = ctrl->value;
296                 break;
297         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
298                 params->video_spatial_filter_mode = ctrl->value;
299                 break;
300         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
301                 params->video_spatial_filter = ctrl->value;
302                 break;
303         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
304                 params->video_luma_spatial_filter_type = ctrl->value;
305                 break;
306         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
307                 params->video_chroma_spatial_filter_type = ctrl->value;
308                 break;
309         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
310                 params->video_temporal_filter_mode = ctrl->value;
311                 break;
312         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
313                 params->video_temporal_filter = ctrl->value;
314                 break;
315         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
316                 params->video_median_filter_type = ctrl->value;
317                 break;
318         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
319                 params->video_luma_median_filter_top = ctrl->value;
320                 break;
321         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
322                 params->video_luma_median_filter_bottom = ctrl->value;
323                 break;
324         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
325                 params->video_chroma_median_filter_top = ctrl->value;
326                 break;
327         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
328                 params->video_chroma_median_filter_bottom = ctrl->value;
329                 break;
330         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
331                 params->stream_insert_nav_packets = ctrl->value;
332                 break;
333         default:
334                 return -EINVAL;
335         }
336         return 0;
337 }
338
339 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
340                                    s32 min, s32 max, s32 step, s32 def)
341 {
342         const char *name;
343
344         qctrl->flags = 0;
345         switch (qctrl->id) {
346         /* MPEG controls */
347         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
348                 name = "Spatial Filter Mode";
349                 break;
350         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
351                 name = "Spatial Filter";
352                 break;
353         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
354                 name = "Spatial Luma Filter Type";
355                 break;
356         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
357                 name = "Spatial Chroma Filter Type";
358                 break;
359         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
360                 name = "Temporal Filter Mode";
361                 break;
362         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
363                 name = "Temporal Filter";
364                 break;
365         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
366                 name = "Median Filter Type";
367                 break;
368         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
369                 name = "Median Luma Filter Maximum";
370                 break;
371         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
372                 name = "Median Luma Filter Minimum";
373                 break;
374         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
375                 name = "Median Chroma Filter Maximum";
376                 break;
377         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
378                 name = "Median Chroma Filter Minimum";
379                 break;
380         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
381                 name = "Insert Navigation Packets";
382                 break;
383
384         default:
385                 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
386         }
387         switch (qctrl->id) {
388         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
389         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
390         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
391         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
392         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
393                 qctrl->type = V4L2_CTRL_TYPE_MENU;
394                 min = 0;
395                 step = 1;
396                 break;
397         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
398                 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
399                 min = 0;
400                 max = 1;
401                 step = 1;
402                 break;
403         default:
404                 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
405                 break;
406         }
407         switch (qctrl->id) {
408         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
409         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
410         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
411                 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
412                 break;
413         }
414         qctrl->minimum = min;
415         qctrl->maximum = max;
416         qctrl->step = step;
417         qctrl->default_value = def;
418         qctrl->reserved[0] = qctrl->reserved[1] = 0;
419         snprintf(qctrl->name, sizeof(qctrl->name), name);
420         return 0;
421 }
422
423 int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
424                        struct v4l2_queryctrl *qctrl)
425 {
426         int err;
427
428         switch (qctrl->id) {
429         case V4L2_CID_MPEG_AUDIO_ENCODING:
430                 return v4l2_ctrl_query_fill(qctrl,
431                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
432                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
433                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
434
435         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436                 return v4l2_ctrl_query_fill(qctrl,
437                                 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
438                                 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
439                                 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
440
441         case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
442         case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
443                 return -EINVAL;
444
445         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
446                 err = v4l2_ctrl_query_fill_std(qctrl);
447                 if (err == 0 &&
448                     params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
449                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
450                 return err;
451
452         case V4L2_CID_MPEG_VIDEO_ENCODING:
453                 /* this setting is read-only for the cx2341x since the
454                    V4L2_CID_MPEG_STREAM_TYPE really determines the
455                    MPEG-1/2 setting */
456                 err = v4l2_ctrl_query_fill_std(qctrl);
457                 if (err == 0)
458                         qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
459                 return err;
460
461         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
462                 err = v4l2_ctrl_query_fill_std(qctrl);
463                 if (err == 0 &&
464                     params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
465                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
466                 return err;
467
468         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
469                 err = v4l2_ctrl_query_fill_std(qctrl);
470                 if (err == 0 &&
471                     params->video_bitrate_mode ==
472                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
473                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
474                 return err;
475
476         case V4L2_CID_MPEG_STREAM_VBI_FMT:
477                 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
478                         return v4l2_ctrl_query_fill_std(qctrl);
479                 return cx2341x_ctrl_query_fill(qctrl,
480                                 V4L2_MPEG_STREAM_VBI_FMT_NONE,
481                                 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
482                                 V4L2_MPEG_STREAM_VBI_FMT_NONE);
483
484         /* CX23415/6 specific */
485         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
486                 return cx2341x_ctrl_query_fill(qctrl,
487                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
488                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
489                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
490
491         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
492                 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
493                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
494                 if (params->video_spatial_filter_mode ==
495                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
496                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
497                 return 0;
498
499         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
500                 cx2341x_ctrl_query_fill(qctrl,
501                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
502                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
503                         1,
504                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
505                 if (params->video_spatial_filter_mode ==
506                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
507                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
508                 return 0;
509
510         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
511                 cx2341x_ctrl_query_fill(qctrl,
512                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
513                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
514                     1,
515                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
516                 if (params->video_spatial_filter_mode ==
517                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
518                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
519                 return 0;
520
521         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
522                 return cx2341x_ctrl_query_fill(qctrl,
523                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
524                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
525                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
526
527         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
528                 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
529                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
530                 if (params->video_temporal_filter_mode ==
531                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
532                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
533                 return 0;
534
535         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
536                 return cx2341x_ctrl_query_fill(qctrl,
537                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
538                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
539                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
540
541         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
542                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
543                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
544                 if (params->video_median_filter_type ==
545                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
546                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
547                 return 0;
548
549         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
550                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
551                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
552                 if (params->video_median_filter_type ==
553                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
554                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
555                 return 0;
556
557         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
558                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
559                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
560                 if (params->video_median_filter_type ==
561                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
562                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
563                 return 0;
564
565         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
566                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
567                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
568                 if (params->video_median_filter_type ==
569                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
570                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
571                 return 0;
572
573         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
574                 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
575
576         default:
577                 return v4l2_ctrl_query_fill_std(qctrl);
578
579         }
580 }
581 EXPORT_SYMBOL(cx2341x_ctrl_query);
582
583 const char **cx2341x_ctrl_get_menu(u32 id)
584 {
585         static const char *mpeg_stream_type[] = {
586                 "MPEG-2 Program Stream",
587                 "",
588                 "MPEG-1 System Stream",
589                 "MPEG-2 DVD-compatible Stream",
590                 "MPEG-1 VCD-compatible Stream",
591                 "MPEG-2 SVCD-compatible Stream",
592                 NULL
593         };
594
595         static const char *cx2341x_video_spatial_filter_mode_menu[] = {
596                 "Manual",
597                 "Auto",
598                 NULL
599         };
600
601         static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
602                 "Off",
603                 "1D Horizontal",
604                 "1D Vertical",
605                 "2D H/V Separable",
606                 "2D Symmetric non-separable",
607                 NULL
608         };
609
610         static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
611                 "Off",
612                 "1D Horizontal",
613                 NULL
614         };
615
616         static const char *cx2341x_video_temporal_filter_mode_menu[] = {
617                 "Manual",
618                 "Auto",
619                 NULL
620         };
621
622         static const char *cx2341x_video_median_filter_type_menu[] = {
623                 "Off",
624                 "Horizontal",
625                 "Vertical",
626                 "Horizontal/Vertical",
627                 "Diagonal",
628                 NULL
629         };
630
631         switch (id) {
632         case V4L2_CID_MPEG_STREAM_TYPE:
633                 return mpeg_stream_type;
634         case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
635         case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
636                 return NULL;
637         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
638                 return cx2341x_video_spatial_filter_mode_menu;
639         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
640                 return cx2341x_video_luma_spatial_filter_type_menu;
641         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
642                 return cx2341x_video_chroma_spatial_filter_type_menu;
643         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
644                 return cx2341x_video_temporal_filter_mode_menu;
645         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
646                 return cx2341x_video_median_filter_type_menu;
647         default:
648                 return v4l2_ctrl_get_menu(id);
649         }
650 }
651 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
652
653 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
654 {
655         params->audio_properties = (params->audio_sampling_freq << 0) |
656                 ((3 - params->audio_encoding) << 2) |
657                 ((1 + params->audio_l2_bitrate) << 4) |
658                 (params->audio_mode << 8) |
659                 (params->audio_mode_extension << 10) |
660                 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
661                   ? 3 : params->audio_emphasis) << 12) |
662                 (params->audio_crc << 14);
663 }
664
665 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
666                   struct v4l2_ext_controls *ctrls, unsigned int cmd)
667 {
668         int err = 0;
669         int i;
670
671         if (cmd == VIDIOC_G_EXT_CTRLS) {
672                 for (i = 0; i < ctrls->count; i++) {
673                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
674
675                         err = cx2341x_get_ctrl(params, ctrl);
676                         if (err) {
677                                 ctrls->error_idx = i;
678                                 break;
679                         }
680                 }
681                 return err;
682         }
683         for (i = 0; i < ctrls->count; i++) {
684                 struct v4l2_ext_control *ctrl = ctrls->controls + i;
685                 struct v4l2_queryctrl qctrl;
686                 const char **menu_items = NULL;
687
688                 qctrl.id = ctrl->id;
689                 err = cx2341x_ctrl_query(params, &qctrl);
690                 if (err)
691                         break;
692                 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
693                         menu_items = cx2341x_ctrl_get_menu(qctrl.id);
694                 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
695                 if (err)
696                         break;
697                 err = cx2341x_set_ctrl(params, busy, ctrl);
698                 if (err)
699                         break;
700         }
701         if (err == 0 &&
702             params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
703             params->video_bitrate_peak < params->video_bitrate) {
704                 err = -ERANGE;
705                 ctrls->error_idx = ctrls->count;
706         }
707         if (err)
708                 ctrls->error_idx = i;
709         else
710                 cx2341x_calc_audio_properties(params);
711         return err;
712 }
713 EXPORT_SYMBOL(cx2341x_ext_ctrls);
714
715 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
716 {
717         static struct cx2341x_mpeg_params default_params = {
718         /* misc */
719         .capabilities = 0,
720         .port = CX2341X_PORT_MEMORY,
721         .width = 720,
722         .height = 480,
723         .is_50hz = 0,
724
725         /* stream */
726         .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
727         .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
728         .stream_insert_nav_packets = 0,
729
730         /* audio */
731         .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
732         .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
733         .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
734         .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
735         .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
736         .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
737         .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
738         .audio_mute = 0,
739
740         /* video */
741         .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
742         .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
743         .video_b_frames = 2,
744         .video_gop_size = 12,
745         .video_gop_closure = 1,
746         .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
747         .video_bitrate = 6000000,
748         .video_bitrate_peak = 8000000,
749         .video_temporal_decimation = 0,
750         .video_mute = 0,
751         .video_mute_yuv = 0x008080,  /* YCbCr value for black */
752
753         /* encoding filters */
754         .video_spatial_filter_mode =
755                 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
756         .video_spatial_filter = 0,
757         .video_luma_spatial_filter_type =
758                 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
759         .video_chroma_spatial_filter_type =
760                 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
761         .video_temporal_filter_mode =
762                 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
763         .video_temporal_filter = 8,
764         .video_median_filter_type =
765                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
766         .video_luma_median_filter_top = 255,
767         .video_luma_median_filter_bottom = 0,
768         .video_chroma_median_filter_top = 255,
769         .video_chroma_median_filter_bottom = 0,
770         };
771
772         *p = default_params;
773         cx2341x_calc_audio_properties(p);
774 }
775 EXPORT_SYMBOL(cx2341x_fill_defaults);
776
777 static int cx2341x_api(void *priv, cx2341x_mbox_func func,
778                        int cmd, int args, ...)
779 {
780         u32 data[CX2341X_MBOX_MAX_DATA];
781         va_list vargs;
782         int i;
783
784         va_start(vargs, args);
785
786         for (i = 0; i < args; i++)
787                 data[i] = va_arg(vargs, int);
788         va_end(vargs);
789         return func(priv, cmd, args, 0, data);
790 }
791
792 #define NEQ(field) (old->field != new->field)
793
794 int cx2341x_update(void *priv, cx2341x_mbox_func func,
795                    const struct cx2341x_mpeg_params *old,
796                    const struct cx2341x_mpeg_params *new)
797 {
798         static int mpeg_stream_type[] = {
799                 0,      /* MPEG-2 PS */
800                 1,      /* MPEG-2 TS */
801                 2,      /* MPEG-1 SS */
802                 14,     /* DVD */
803                 11,     /* VCD */
804                 12,     /* SVCD */
805         };
806
807         int err = 0;
808         int force = (old == NULL);
809         u16 temporal = new->video_temporal_filter;
810
811         cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
812
813         if (force || NEQ(is_50hz)) {
814                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
815                                   new->is_50hz);
816                 if (err) return err;
817         }
818
819         if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
820                 u16 w = new->width;
821                 u16 h = new->height;
822
823                 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
824                         w /= 2;
825                         h /= 2;
826                 }
827                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
828                                   h, w);
829                 if (err) return err;
830         }
831
832         if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
833                 /* Adjust temporal filter if necessary. The problem with the
834                    temporal filter is that it works well with full resolution
835                    capturing, but not when the capture window is scaled (the
836                    filter introduces a ghosting effect). So if the capture
837                    window is scaled, then force the filter to 0.
838
839                    For full resolution the filter really improves the video
840                    quality, especially if the original video quality is
841                    suboptimal. */
842                 temporal = 0;
843         }
844
845         if (force || NEQ(stream_type)) {
846                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
847                                   mpeg_stream_type[new->stream_type]);
848                 if (err) return err;
849         }
850         if (force || NEQ(video_aspect)) {
851                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
852                                   1 + new->video_aspect);
853                 if (err) return err;
854         }
855         if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
856                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
857                                 new->video_gop_size, new->video_b_frames + 1);
858                 if (err) return err;
859         }
860         if (force || NEQ(video_gop_closure)) {
861                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
862                                   new->video_gop_closure);
863                 if (err) return err;
864         }
865         if (force || NEQ(audio_properties)) {
866                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
867                                   1, new->audio_properties);
868                 if (err) return err;
869         }
870         if (force || NEQ(audio_mute)) {
871                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
872                                   new->audio_mute);
873                 if (err) return err;
874         }
875         if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
876                                                 NEQ(video_bitrate_peak)) {
877                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
878                                 new->video_bitrate_mode, new->video_bitrate,
879                                 new->video_bitrate_peak / 400, 0, 0);
880                 if (err) return err;
881         }
882         if (force || NEQ(video_spatial_filter_mode) ||
883                      NEQ(video_temporal_filter_mode) ||
884                      NEQ(video_median_filter_type)) {
885                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
886                                   2, new->video_spatial_filter_mode |
887                                         (new->video_temporal_filter_mode << 1),
888                                 new->video_median_filter_type);
889                 if (err) return err;
890         }
891         if (force || NEQ(video_luma_median_filter_bottom) ||
892                      NEQ(video_luma_median_filter_top) ||
893                      NEQ(video_chroma_median_filter_bottom) ||
894                      NEQ(video_chroma_median_filter_top)) {
895                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
896                                 new->video_luma_median_filter_bottom,
897                                 new->video_luma_median_filter_top,
898                                 new->video_chroma_median_filter_bottom,
899                                 new->video_chroma_median_filter_top);
900                 if (err) return err;
901         }
902         if (force || NEQ(video_luma_spatial_filter_type) ||
903                      NEQ(video_chroma_spatial_filter_type)) {
904                 err = cx2341x_api(priv, func,
905                                   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
906                                   2, new->video_luma_spatial_filter_type,
907                                   new->video_chroma_spatial_filter_type);
908                 if (err) return err;
909         }
910         if (force || NEQ(video_spatial_filter) ||
911                      old->video_temporal_filter != temporal) {
912                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
913                                   2, new->video_spatial_filter, temporal);
914                 if (err) return err;
915         }
916         if (force || NEQ(video_temporal_decimation)) {
917                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
918                                   1, new->video_temporal_decimation);
919                 if (err) return err;
920         }
921         if (force || NEQ(video_mute) ||
922                 (new->video_mute && NEQ(video_mute_yuv))) {
923                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
924                                 new->video_mute | (new->video_mute_yuv << 8));
925                 if (err) return err;
926         }
927         if (force || NEQ(stream_insert_nav_packets)) {
928                 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
929                                 7, new->stream_insert_nav_packets);
930                 if (err) return err;
931         }
932         return 0;
933 }
934 EXPORT_SYMBOL(cx2341x_update);
935
936 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
937 {
938         const char **menu = cx2341x_ctrl_get_menu(id);
939         struct v4l2_ext_control ctrl;
940
941         if (menu == NULL)
942                 goto invalid;
943         ctrl.id = id;
944         if (cx2341x_get_ctrl(p, &ctrl))
945                 goto invalid;
946         while (ctrl.value-- && *menu) menu++;
947         if (*menu == NULL)
948                 goto invalid;
949         return *menu;
950
951 invalid:
952         return "<invalid>";
953 }
954
955 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
956 {
957         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
958         int temporal = p->video_temporal_filter;
959
960         /* Stream */
961         printk(KERN_INFO "%s: Stream: %s",
962                 prefix,
963                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
964         if (p->stream_insert_nav_packets)
965                 printk(" (with navigation packets)");
966         printk("\n");
967         printk(KERN_INFO "%s: VBI Format: %s\n",
968                 prefix,
969                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
970
971         /* Video */
972         printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
973                 prefix,
974                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
975                 p->is_50hz ? 25 : 30,
976                 (p->video_mute) ? " (muted)" : "");
977         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
978                 prefix,
979                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
980                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
981                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
982                 p->video_bitrate);
983         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
984                 printk(", Peak %d", p->video_bitrate_peak);
985         printk("\n");
986         printk(KERN_INFO
987                 "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
988                 prefix,
989                 p->video_gop_size, p->video_b_frames,
990                 p->video_gop_closure ? "" : "No ");
991         if (p->video_temporal_decimation)
992                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
993                         prefix, p->video_temporal_decimation);
994
995         /* Audio */
996         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
997                 prefix,
998                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
999                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1000                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1001                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1002                 p->audio_mute ? " (muted)" : "");
1003         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1004                 printk(", %s", cx2341x_menu_item(p,
1005                                 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1006         printk(", %s, %s\n",
1007                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1008                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1009
1010         /* Encoding filters */
1011         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1012                 prefix,
1013                 cx2341x_menu_item(p,
1014                     V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1015                 cx2341x_menu_item(p,
1016                     V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1017                 cx2341x_menu_item(p,
1018                     V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1019                 p->video_spatial_filter);
1020
1021         if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1022                 temporal = 0;
1023
1024         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1025                 prefix,
1026                 cx2341x_menu_item(p,
1027                         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1028                 temporal);
1029         printk(KERN_INFO
1030                 "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1031                 prefix,
1032                 cx2341x_menu_item(p,
1033                         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1034                 p->video_luma_median_filter_bottom,
1035                 p->video_luma_median_filter_top,
1036                 p->video_chroma_median_filter_bottom,
1037                 p->video_chroma_median_filter_top);
1038 }
1039 EXPORT_SYMBOL(cx2341x_log_status);
1040
1041 /*
1042  * Local variables:
1043  * c-basic-offset: 8
1044  * End:
1045  */
1046