Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[pandora-kernel.git] / drivers / media / video / cx2341x.c
1 /*
2  * cx2341x - generic code for cx23415/6/8 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/8 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 /* Must be sorted from low to high control ID! */
42 const u32 cx2341x_mpeg_ctrls[] = {
43         V4L2_CID_MPEG_CLASS,
44         V4L2_CID_MPEG_STREAM_TYPE,
45         V4L2_CID_MPEG_STREAM_VBI_FMT,
46         V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
47         V4L2_CID_MPEG_AUDIO_ENCODING,
48         V4L2_CID_MPEG_AUDIO_L2_BITRATE,
49         V4L2_CID_MPEG_AUDIO_MODE,
50         V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
51         V4L2_CID_MPEG_AUDIO_EMPHASIS,
52         V4L2_CID_MPEG_AUDIO_CRC,
53         V4L2_CID_MPEG_AUDIO_MUTE,
54         V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
55         V4L2_CID_MPEG_VIDEO_ENCODING,
56         V4L2_CID_MPEG_VIDEO_ASPECT,
57         V4L2_CID_MPEG_VIDEO_B_FRAMES,
58         V4L2_CID_MPEG_VIDEO_GOP_SIZE,
59         V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
60         V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
61         V4L2_CID_MPEG_VIDEO_BITRATE,
62         V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
63         V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
64         V4L2_CID_MPEG_VIDEO_MUTE,
65         V4L2_CID_MPEG_VIDEO_MUTE_YUV,
66         V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
67         V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
68         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
69         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
70         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
71         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
72         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
73         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
74         V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
75         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
76         V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
77         V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
78         0
79 };
80 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
81
82 static const struct cx2341x_mpeg_params default_params = {
83         /* misc */
84         .capabilities = 0,
85         .port = CX2341X_PORT_MEMORY,
86         .width = 720,
87         .height = 480,
88         .is_50hz = 0,
89
90         /* stream */
91         .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
92         .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
93         .stream_insert_nav_packets = 0,
94
95         /* audio */
96         .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
97         .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
98         .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
99         .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
100         .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
101         .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
102         .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
103         .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
104         .audio_mute = 0,
105
106         /* video */
107         .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
108         .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
109         .video_b_frames = 2,
110         .video_gop_size = 12,
111         .video_gop_closure = 1,
112         .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
113         .video_bitrate = 6000000,
114         .video_bitrate_peak = 8000000,
115         .video_temporal_decimation = 0,
116         .video_mute = 0,
117         .video_mute_yuv = 0x008080,  /* YCbCr value for black */
118
119         /* encoding filters */
120         .video_spatial_filter_mode =
121                 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
122         .video_spatial_filter = 0,
123         .video_luma_spatial_filter_type =
124                 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
125         .video_chroma_spatial_filter_type =
126                 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
127         .video_temporal_filter_mode =
128                 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
129         .video_temporal_filter = 8,
130         .video_median_filter_type =
131                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
132         .video_luma_median_filter_top = 255,
133         .video_luma_median_filter_bottom = 0,
134         .video_chroma_median_filter_top = 255,
135         .video_chroma_median_filter_bottom = 0,
136 };
137
138
139 /* Map the control ID to the correct field in the cx2341x_mpeg_params
140    struct. Return -EINVAL if the ID is unknown, else return 0. */
141 static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
142                 struct v4l2_ext_control *ctrl)
143 {
144         switch (ctrl->id) {
145         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
146                 ctrl->value = params->audio_sampling_freq;
147                 break;
148         case V4L2_CID_MPEG_AUDIO_ENCODING:
149                 ctrl->value = params->audio_encoding;
150                 break;
151         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
152                 ctrl->value = params->audio_l2_bitrate;
153                 break;
154         case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
155                 ctrl->value = params->audio_ac3_bitrate;
156                 break;
157         case V4L2_CID_MPEG_AUDIO_MODE:
158                 ctrl->value = params->audio_mode;
159                 break;
160         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
161                 ctrl->value = params->audio_mode_extension;
162                 break;
163         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
164                 ctrl->value = params->audio_emphasis;
165                 break;
166         case V4L2_CID_MPEG_AUDIO_CRC:
167                 ctrl->value = params->audio_crc;
168                 break;
169         case V4L2_CID_MPEG_AUDIO_MUTE:
170                 ctrl->value = params->audio_mute;
171                 break;
172         case V4L2_CID_MPEG_VIDEO_ENCODING:
173                 ctrl->value = params->video_encoding;
174                 break;
175         case V4L2_CID_MPEG_VIDEO_ASPECT:
176                 ctrl->value = params->video_aspect;
177                 break;
178         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
179                 ctrl->value = params->video_b_frames;
180                 break;
181         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
182                 ctrl->value = params->video_gop_size;
183                 break;
184         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
185                 ctrl->value = params->video_gop_closure;
186                 break;
187         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
188                 ctrl->value = params->video_bitrate_mode;
189                 break;
190         case V4L2_CID_MPEG_VIDEO_BITRATE:
191                 ctrl->value = params->video_bitrate;
192                 break;
193         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
194                 ctrl->value = params->video_bitrate_peak;
195                 break;
196         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
197                 ctrl->value = params->video_temporal_decimation;
198                 break;
199         case V4L2_CID_MPEG_VIDEO_MUTE:
200                 ctrl->value = params->video_mute;
201                 break;
202         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
203                 ctrl->value = params->video_mute_yuv;
204                 break;
205         case V4L2_CID_MPEG_STREAM_TYPE:
206                 ctrl->value = params->stream_type;
207                 break;
208         case V4L2_CID_MPEG_STREAM_VBI_FMT:
209                 ctrl->value = params->stream_vbi_fmt;
210                 break;
211         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
212                 ctrl->value = params->video_spatial_filter_mode;
213                 break;
214         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
215                 ctrl->value = params->video_spatial_filter;
216                 break;
217         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
218                 ctrl->value = params->video_luma_spatial_filter_type;
219                 break;
220         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
221                 ctrl->value = params->video_chroma_spatial_filter_type;
222                 break;
223         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
224                 ctrl->value = params->video_temporal_filter_mode;
225                 break;
226         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
227                 ctrl->value = params->video_temporal_filter;
228                 break;
229         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
230                 ctrl->value = params->video_median_filter_type;
231                 break;
232         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
233                 ctrl->value = params->video_luma_median_filter_top;
234                 break;
235         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
236                 ctrl->value = params->video_luma_median_filter_bottom;
237                 break;
238         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
239                 ctrl->value = params->video_chroma_median_filter_top;
240                 break;
241         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
242                 ctrl->value = params->video_chroma_median_filter_bottom;
243                 break;
244         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
245                 ctrl->value = params->stream_insert_nav_packets;
246                 break;
247         default:
248                 return -EINVAL;
249         }
250         return 0;
251 }
252
253 /* Map the control ID to the correct field in the cx2341x_mpeg_params
254    struct. Return -EINVAL if the ID is unknown, else return 0. */
255 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
256                 struct v4l2_ext_control *ctrl)
257 {
258         switch (ctrl->id) {
259         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
260                 if (busy)
261                         return -EBUSY;
262                 params->audio_sampling_freq = ctrl->value;
263                 break;
264         case V4L2_CID_MPEG_AUDIO_ENCODING:
265                 if (busy)
266                         return -EBUSY;
267                 if (params->capabilities & CX2341X_CAP_HAS_AC3)
268                         if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
269                             ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
270                                 return -ERANGE;
271                 params->audio_encoding = ctrl->value;
272                 break;
273         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
274                 if (busy)
275                         return -EBUSY;
276                 params->audio_l2_bitrate = ctrl->value;
277                 break;
278         case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
279                 if (busy)
280                         return -EBUSY;
281                 if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
282                         return -EINVAL;
283                 params->audio_ac3_bitrate = ctrl->value;
284                 break;
285         case V4L2_CID_MPEG_AUDIO_MODE:
286                 params->audio_mode = ctrl->value;
287                 break;
288         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
289                 params->audio_mode_extension = ctrl->value;
290                 break;
291         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
292                 params->audio_emphasis = ctrl->value;
293                 break;
294         case V4L2_CID_MPEG_AUDIO_CRC:
295                 params->audio_crc = ctrl->value;
296                 break;
297         case V4L2_CID_MPEG_AUDIO_MUTE:
298                 params->audio_mute = ctrl->value;
299                 break;
300         case V4L2_CID_MPEG_VIDEO_ASPECT:
301                 params->video_aspect = ctrl->value;
302                 break;
303         case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
304                 int b = ctrl->value + 1;
305                 int gop = params->video_gop_size;
306                 params->video_b_frames = ctrl->value;
307                 params->video_gop_size = b * ((gop + b - 1) / b);
308                 /* Max GOP size = 34 */
309                 while (params->video_gop_size > 34)
310                         params->video_gop_size -= b;
311                 break;
312         }
313         case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
314                 int b = params->video_b_frames + 1;
315                 int gop = ctrl->value;
316                 params->video_gop_size = b * ((gop + b - 1) / b);
317                 /* Max GOP size = 34 */
318                 while (params->video_gop_size > 34)
319                         params->video_gop_size -= b;
320                 ctrl->value = params->video_gop_size;
321                 break;
322         }
323         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
324                 params->video_gop_closure = ctrl->value;
325                 break;
326         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
327                 if (busy)
328                         return -EBUSY;
329                 /* MPEG-1 only allows CBR */
330                 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
331                     ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
332                         return -EINVAL;
333                 params->video_bitrate_mode = ctrl->value;
334                 break;
335         case V4L2_CID_MPEG_VIDEO_BITRATE:
336                 if (busy)
337                         return -EBUSY;
338                 params->video_bitrate = ctrl->value;
339                 break;
340         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
341                 if (busy)
342                         return -EBUSY;
343                 params->video_bitrate_peak = ctrl->value;
344                 break;
345         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
346                 params->video_temporal_decimation = ctrl->value;
347                 break;
348         case V4L2_CID_MPEG_VIDEO_MUTE:
349                 params->video_mute = (ctrl->value != 0);
350                 break;
351         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
352                 params->video_mute_yuv = ctrl->value;
353                 break;
354         case V4L2_CID_MPEG_STREAM_TYPE:
355                 if (busy)
356                         return -EBUSY;
357                 params->stream_type = ctrl->value;
358                 params->video_encoding =
359                     (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
360                      params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
361                         V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
362                         V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
363                 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
364                         /* MPEG-1 implies CBR */
365                         params->video_bitrate_mode =
366                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
367                 break;
368         case V4L2_CID_MPEG_STREAM_VBI_FMT:
369                 params->stream_vbi_fmt = ctrl->value;
370                 break;
371         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
372                 params->video_spatial_filter_mode = ctrl->value;
373                 break;
374         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
375                 params->video_spatial_filter = ctrl->value;
376                 break;
377         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
378                 params->video_luma_spatial_filter_type = ctrl->value;
379                 break;
380         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
381                 params->video_chroma_spatial_filter_type = ctrl->value;
382                 break;
383         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
384                 params->video_temporal_filter_mode = ctrl->value;
385                 break;
386         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
387                 params->video_temporal_filter = ctrl->value;
388                 break;
389         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
390                 params->video_median_filter_type = ctrl->value;
391                 break;
392         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
393                 params->video_luma_median_filter_top = ctrl->value;
394                 break;
395         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
396                 params->video_luma_median_filter_bottom = ctrl->value;
397                 break;
398         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
399                 params->video_chroma_median_filter_top = ctrl->value;
400                 break;
401         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
402                 params->video_chroma_median_filter_bottom = ctrl->value;
403                 break;
404         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
405                 params->stream_insert_nav_packets = ctrl->value;
406                 break;
407         default:
408                 return -EINVAL;
409         }
410         return 0;
411 }
412
413 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
414                                    s32 min, s32 max, s32 step, s32 def)
415 {
416         const char *name;
417
418         qctrl->flags = 0;
419         switch (qctrl->id) {
420         /* MPEG controls */
421         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
422                 name = "Spatial Filter Mode";
423                 break;
424         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
425                 name = "Spatial Filter";
426                 break;
427         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
428                 name = "Spatial Luma Filter Type";
429                 break;
430         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
431                 name = "Spatial Chroma Filter Type";
432                 break;
433         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
434                 name = "Temporal Filter Mode";
435                 break;
436         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
437                 name = "Temporal Filter";
438                 break;
439         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
440                 name = "Median Filter Type";
441                 break;
442         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
443                 name = "Median Luma Filter Maximum";
444                 break;
445         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
446                 name = "Median Luma Filter Minimum";
447                 break;
448         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
449                 name = "Median Chroma Filter Maximum";
450                 break;
451         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
452                 name = "Median Chroma Filter Minimum";
453                 break;
454         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
455                 name = "Insert Navigation Packets";
456                 break;
457
458         default:
459                 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
460         }
461         switch (qctrl->id) {
462         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
463         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
464         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
465         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
466         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
467                 qctrl->type = V4L2_CTRL_TYPE_MENU;
468                 min = 0;
469                 step = 1;
470                 break;
471         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
472                 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
473                 min = 0;
474                 max = 1;
475                 step = 1;
476                 break;
477         default:
478                 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
479                 break;
480         }
481         switch (qctrl->id) {
482         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
483         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
484         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
485                 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
486                 break;
487         }
488         qctrl->minimum = min;
489         qctrl->maximum = max;
490         qctrl->step = step;
491         qctrl->default_value = def;
492         qctrl->reserved[0] = qctrl->reserved[1] = 0;
493         snprintf(qctrl->name, sizeof(qctrl->name), name);
494         return 0;
495 }
496
497 int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
498                        struct v4l2_queryctrl *qctrl)
499 {
500         int err;
501
502         switch (qctrl->id) {
503         case V4L2_CID_MPEG_CLASS:
504                 return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
505         case V4L2_CID_MPEG_STREAM_TYPE:
506                 return v4l2_ctrl_query_fill(qctrl,
507                                 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
508                                 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
509                                 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
510
511         case V4L2_CID_MPEG_STREAM_VBI_FMT:
512                 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
513                         return v4l2_ctrl_query_fill(qctrl,
514                                         V4L2_MPEG_STREAM_VBI_FMT_NONE,
515                                         V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
516                                         V4L2_MPEG_STREAM_VBI_FMT_NONE);
517                 return cx2341x_ctrl_query_fill(qctrl,
518                                 V4L2_MPEG_STREAM_VBI_FMT_NONE,
519                                 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
520                                 default_params.stream_vbi_fmt);
521
522         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
523                 return v4l2_ctrl_query_fill(qctrl,
524                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
525                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
526                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
527
528         case V4L2_CID_MPEG_AUDIO_ENCODING:
529                 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
530                         /*
531                          * The state of L2 & AC3 bitrate controls can change
532                          * when this control changes, but v4l2_ctrl_query_fill()
533                          * already sets V4L2_CTRL_FLAG_UPDATE for
534                          * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
535                          */
536                         return v4l2_ctrl_query_fill(qctrl,
537                                         V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
538                                         V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
539                                         default_params.audio_encoding);
540                 }
541
542                 return v4l2_ctrl_query_fill(qctrl,
543                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
544                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
545                                 default_params.audio_encoding);
546
547         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
548                 err = v4l2_ctrl_query_fill(qctrl,
549                                 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
550                                 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
551                                 default_params.audio_l2_bitrate);
552                 if (err)
553                         return err;
554                 if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
555                     params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
556                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
557                 return 0;
558
559         case V4L2_CID_MPEG_AUDIO_MODE:
560                 return v4l2_ctrl_query_fill(qctrl,
561                                 V4L2_MPEG_AUDIO_MODE_STEREO,
562                                 V4L2_MPEG_AUDIO_MODE_MONO, 1,
563                                 V4L2_MPEG_AUDIO_MODE_STEREO);
564
565         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
566                 err = v4l2_ctrl_query_fill(qctrl,
567                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
568                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
569                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
570                 if (err == 0 &&
571                     params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
572                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
573                 return err;
574
575         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
576                 return v4l2_ctrl_query_fill(qctrl,
577                                 V4L2_MPEG_AUDIO_EMPHASIS_NONE,
578                                 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
579                                 V4L2_MPEG_AUDIO_EMPHASIS_NONE);
580
581         case V4L2_CID_MPEG_AUDIO_CRC:
582                 return v4l2_ctrl_query_fill(qctrl,
583                                 V4L2_MPEG_AUDIO_CRC_NONE,
584                                 V4L2_MPEG_AUDIO_CRC_CRC16, 1,
585                                 V4L2_MPEG_AUDIO_CRC_NONE);
586
587         case V4L2_CID_MPEG_AUDIO_MUTE:
588                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
589
590         case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
591                 err = v4l2_ctrl_query_fill(qctrl,
592                                 V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
593                                 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
594                                 default_params.audio_ac3_bitrate);
595                 if (err)
596                         return err;
597                 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
598                         if (params->audio_encoding !=
599                                                    V4L2_MPEG_AUDIO_ENCODING_AC3)
600                                 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
601                 } else
602                         qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
603                 return 0;
604
605         case V4L2_CID_MPEG_VIDEO_ENCODING:
606                 /* this setting is read-only for the cx2341x since the
607                    V4L2_CID_MPEG_STREAM_TYPE really determines the
608                    MPEG-1/2 setting */
609                 err = v4l2_ctrl_query_fill(qctrl,
610                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
611                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
612                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
613                 if (err == 0)
614                         qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
615                 return err;
616
617         case V4L2_CID_MPEG_VIDEO_ASPECT:
618                 return v4l2_ctrl_query_fill(qctrl,
619                                 V4L2_MPEG_VIDEO_ASPECT_1x1,
620                                 V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
621                                 V4L2_MPEG_VIDEO_ASPECT_4x3);
622
623         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
624                 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
625
626         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
627                 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
628                                 params->is_50hz ? 12 : 15);
629
630         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
631                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
632
633         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
634                 err = v4l2_ctrl_query_fill(qctrl,
635                                 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
636                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
637                                 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
638                 if (err == 0 &&
639                     params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
640                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
641                 return err;
642
643         case V4L2_CID_MPEG_VIDEO_BITRATE:
644                 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
645
646         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
647                 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
648                 if (err == 0 &&
649                     params->video_bitrate_mode ==
650                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
651                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
652                 return err;
653
654         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
655                 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
656
657         case V4L2_CID_MPEG_VIDEO_MUTE:
658                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
659
660         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:  /* Init YUV (really YCbCr) to black */
661                 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
662
663         /* CX23415/6 specific */
664         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
665                 return cx2341x_ctrl_query_fill(qctrl,
666                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
667                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
668                         default_params.video_spatial_filter_mode);
669
670         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
671                 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
672                                 default_params.video_spatial_filter);
673                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
674                 if (params->video_spatial_filter_mode ==
675                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
676                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
677                 return 0;
678
679         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
680                 cx2341x_ctrl_query_fill(qctrl,
681                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
682                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
683                         1,
684                         default_params.video_luma_spatial_filter_type);
685                 if (params->video_spatial_filter_mode ==
686                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
687                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
688                 return 0;
689
690         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
691                 cx2341x_ctrl_query_fill(qctrl,
692                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
693                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
694                     1,
695                     default_params.video_chroma_spatial_filter_type);
696                 if (params->video_spatial_filter_mode ==
697                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
698                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
699                 return 0;
700
701         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
702                 return cx2341x_ctrl_query_fill(qctrl,
703                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
704                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
705                         default_params.video_temporal_filter_mode);
706
707         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
708                 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
709                                 default_params.video_temporal_filter);
710                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
711                 if (params->video_temporal_filter_mode ==
712                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
713                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
714                 return 0;
715
716         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
717                 return cx2341x_ctrl_query_fill(qctrl,
718                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
719                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
720                         default_params.video_median_filter_type);
721
722         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
723                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
724                                 default_params.video_luma_median_filter_top);
725                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
726                 if (params->video_median_filter_type ==
727                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
728                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
729                 return 0;
730
731         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
732                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
733                                 default_params.video_luma_median_filter_bottom);
734                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
735                 if (params->video_median_filter_type ==
736                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
737                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
738                 return 0;
739
740         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
741                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
742                                 default_params.video_chroma_median_filter_top);
743                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
744                 if (params->video_median_filter_type ==
745                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
746                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
747                 return 0;
748
749         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
750                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
751                         default_params.video_chroma_median_filter_bottom);
752                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
753                 if (params->video_median_filter_type ==
754                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
755                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
756                 return 0;
757
758         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
759                 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
760                                 default_params.stream_insert_nav_packets);
761
762         default:
763                 return -EINVAL;
764
765         }
766 }
767 EXPORT_SYMBOL(cx2341x_ctrl_query);
768
769 const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
770 {
771         static const char *mpeg_stream_type_without_ts[] = {
772                 "MPEG-2 Program Stream",
773                 "",
774                 "MPEG-1 System Stream",
775                 "MPEG-2 DVD-compatible Stream",
776                 "MPEG-1 VCD-compatible Stream",
777                 "MPEG-2 SVCD-compatible Stream",
778                 NULL
779         };
780
781         static const char *mpeg_stream_type_with_ts[] = {
782                 "MPEG-2 Program Stream",
783                 "MPEG-2 Transport Stream",
784                 "MPEG-1 System Stream",
785                 "MPEG-2 DVD-compatible Stream",
786                 "MPEG-1 VCD-compatible Stream",
787                 "MPEG-2 SVCD-compatible Stream",
788                 NULL
789         };
790
791         static const char *mpeg_audio_encoding_l2_ac3[] = {
792                 "",
793                 "MPEG-1/2 Layer II",
794                 "",
795                 "",
796                 "AC-3",
797                 NULL
798         };
799
800         static const char *cx2341x_video_spatial_filter_mode_menu[] = {
801                 "Manual",
802                 "Auto",
803                 NULL
804         };
805
806         static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
807                 "Off",
808                 "1D Horizontal",
809                 "1D Vertical",
810                 "2D H/V Separable",
811                 "2D Symmetric non-separable",
812                 NULL
813         };
814
815         static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
816                 "Off",
817                 "1D Horizontal",
818                 NULL
819         };
820
821         static const char *cx2341x_video_temporal_filter_mode_menu[] = {
822                 "Manual",
823                 "Auto",
824                 NULL
825         };
826
827         static const char *cx2341x_video_median_filter_type_menu[] = {
828                 "Off",
829                 "Horizontal",
830                 "Vertical",
831                 "Horizontal/Vertical",
832                 "Diagonal",
833                 NULL
834         };
835
836         switch (id) {
837         case V4L2_CID_MPEG_STREAM_TYPE:
838                 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
839                         mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
840         case V4L2_CID_MPEG_AUDIO_ENCODING:
841                 return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
842                         mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
843         case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
844         case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
845                 return NULL;
846         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
847                 return cx2341x_video_spatial_filter_mode_menu;
848         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
849                 return cx2341x_video_luma_spatial_filter_type_menu;
850         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
851                 return cx2341x_video_chroma_spatial_filter_type_menu;
852         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
853                 return cx2341x_video_temporal_filter_mode_menu;
854         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
855                 return cx2341x_video_median_filter_type_menu;
856         default:
857                 return v4l2_ctrl_get_menu(id);
858         }
859 }
860 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
861
862 /* definitions for audio properties bits 29-28 */
863 #define CX2341X_AUDIO_ENCODING_METHOD_MPEG      0
864 #define CX2341X_AUDIO_ENCODING_METHOD_AC3       1
865 #define CX2341X_AUDIO_ENCODING_METHOD_LPCM      2
866
867 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
868 {
869         params->audio_properties =
870                 (params->audio_sampling_freq << 0) |
871                 (params->audio_mode << 8) |
872                 (params->audio_mode_extension << 10) |
873                 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
874                   ? 3 : params->audio_emphasis) << 12) |
875                 (params->audio_crc << 14);
876
877         if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
878             params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
879                 params->audio_properties |=
880                         /* Not sure if this MPEG Layer II setting is required */
881                         ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
882                         (params->audio_ac3_bitrate << 4) |
883                         (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
884         } else {
885                 /* Assuming MPEG Layer II */
886                 params->audio_properties |=
887                         ((3 - params->audio_encoding) << 2) |
888                         ((1 + params->audio_l2_bitrate) << 4);
889         }
890 }
891
892 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
893                   struct v4l2_ext_controls *ctrls, unsigned int cmd)
894 {
895         int err = 0;
896         int i;
897
898         if (cmd == VIDIOC_G_EXT_CTRLS) {
899                 for (i = 0; i < ctrls->count; i++) {
900                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
901
902                         err = cx2341x_get_ctrl(params, ctrl);
903                         if (err) {
904                                 ctrls->error_idx = i;
905                                 break;
906                         }
907                 }
908                 return err;
909         }
910         for (i = 0; i < ctrls->count; i++) {
911                 struct v4l2_ext_control *ctrl = ctrls->controls + i;
912                 struct v4l2_queryctrl qctrl;
913                 const char **menu_items = NULL;
914
915                 qctrl.id = ctrl->id;
916                 err = cx2341x_ctrl_query(params, &qctrl);
917                 if (err)
918                         break;
919                 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
920                         menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
921                 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
922                 if (err)
923                         break;
924                 err = cx2341x_set_ctrl(params, busy, ctrl);
925                 if (err)
926                         break;
927         }
928         if (err == 0 &&
929             params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
930             params->video_bitrate_peak < params->video_bitrate) {
931                 err = -ERANGE;
932                 ctrls->error_idx = ctrls->count;
933         }
934         if (err)
935                 ctrls->error_idx = i;
936         else
937                 cx2341x_calc_audio_properties(params);
938         return err;
939 }
940 EXPORT_SYMBOL(cx2341x_ext_ctrls);
941
942 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
943 {
944         *p = default_params;
945         cx2341x_calc_audio_properties(p);
946 }
947 EXPORT_SYMBOL(cx2341x_fill_defaults);
948
949 static int cx2341x_api(void *priv, cx2341x_mbox_func func,
950                        u32 cmd, int args, ...)
951 {
952         u32 data[CX2341X_MBOX_MAX_DATA];
953         va_list vargs;
954         int i;
955
956         va_start(vargs, args);
957
958         for (i = 0; i < args; i++)
959                 data[i] = va_arg(vargs, int);
960         va_end(vargs);
961         return func(priv, cmd, args, 0, data);
962 }
963
964 #define NEQ(field) (old->field != new->field)
965
966 int cx2341x_update(void *priv, cx2341x_mbox_func func,
967                    const struct cx2341x_mpeg_params *old,
968                    const struct cx2341x_mpeg_params *new)
969 {
970         static int mpeg_stream_type[] = {
971                 0,      /* MPEG-2 PS */
972                 1,      /* MPEG-2 TS */
973                 2,      /* MPEG-1 SS */
974                 14,     /* DVD */
975                 11,     /* VCD */
976                 12,     /* SVCD */
977         };
978
979         int err = 0;
980         int force = (old == NULL);
981         u16 temporal = new->video_temporal_filter;
982
983         cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
984
985         if (force || NEQ(is_50hz)) {
986                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
987                                   new->is_50hz);
988                 if (err) return err;
989         }
990
991         if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
992                 u16 w = new->width;
993                 u16 h = new->height;
994
995                 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
996                         w /= 2;
997                         h /= 2;
998                 }
999                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
1000                                   h, w);
1001                 if (err) return err;
1002         }
1003         if (force || NEQ(stream_type)) {
1004                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1005                                   mpeg_stream_type[new->stream_type]);
1006                 if (err) return err;
1007         }
1008         if (force || NEQ(video_aspect)) {
1009                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1010                                   1 + new->video_aspect);
1011                 if (err) return err;
1012         }
1013         if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1014                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1015                                 new->video_gop_size, new->video_b_frames + 1);
1016                 if (err) return err;
1017         }
1018         if (force || NEQ(video_gop_closure)) {
1019                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1020                                   new->video_gop_closure);
1021                 if (err) return err;
1022         }
1023         if (force || NEQ(audio_properties)) {
1024                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1025                                   1, new->audio_properties);
1026                 if (err) return err;
1027         }
1028         if (force || NEQ(audio_mute)) {
1029                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1030                                   new->audio_mute);
1031                 if (err) return err;
1032         }
1033         if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1034                                                 NEQ(video_bitrate_peak)) {
1035                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1036                                 new->video_bitrate_mode, new->video_bitrate,
1037                                 new->video_bitrate_peak / 400, 0, 0);
1038                 if (err) return err;
1039         }
1040         if (force || NEQ(video_spatial_filter_mode) ||
1041                      NEQ(video_temporal_filter_mode) ||
1042                      NEQ(video_median_filter_type)) {
1043                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1044                                   2, new->video_spatial_filter_mode |
1045                                         (new->video_temporal_filter_mode << 1),
1046                                 new->video_median_filter_type);
1047                 if (err) return err;
1048         }
1049         if (force || NEQ(video_luma_median_filter_bottom) ||
1050                      NEQ(video_luma_median_filter_top) ||
1051                      NEQ(video_chroma_median_filter_bottom) ||
1052                      NEQ(video_chroma_median_filter_top)) {
1053                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1054                                 new->video_luma_median_filter_bottom,
1055                                 new->video_luma_median_filter_top,
1056                                 new->video_chroma_median_filter_bottom,
1057                                 new->video_chroma_median_filter_top);
1058                 if (err) return err;
1059         }
1060         if (force || NEQ(video_luma_spatial_filter_type) ||
1061                      NEQ(video_chroma_spatial_filter_type)) {
1062                 err = cx2341x_api(priv, func,
1063                                   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1064                                   2, new->video_luma_spatial_filter_type,
1065                                   new->video_chroma_spatial_filter_type);
1066                 if (err) return err;
1067         }
1068         if (force || NEQ(video_spatial_filter) ||
1069                      old->video_temporal_filter != temporal) {
1070                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1071                                   2, new->video_spatial_filter, temporal);
1072                 if (err) return err;
1073         }
1074         if (force || NEQ(video_temporal_decimation)) {
1075                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1076                                   1, new->video_temporal_decimation);
1077                 if (err) return err;
1078         }
1079         if (force || NEQ(video_mute) ||
1080                 (new->video_mute && NEQ(video_mute_yuv))) {
1081                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1082                                 new->video_mute | (new->video_mute_yuv << 8));
1083                 if (err) return err;
1084         }
1085         if (force || NEQ(stream_insert_nav_packets)) {
1086                 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1087                                 7, new->stream_insert_nav_packets);
1088                 if (err) return err;
1089         }
1090         return 0;
1091 }
1092 EXPORT_SYMBOL(cx2341x_update);
1093
1094 static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1095 {
1096         const char **menu = cx2341x_ctrl_get_menu(p, id);
1097         struct v4l2_ext_control ctrl;
1098
1099         if (menu == NULL)
1100                 goto invalid;
1101         ctrl.id = id;
1102         if (cx2341x_get_ctrl(p, &ctrl))
1103                 goto invalid;
1104         while (ctrl.value-- && *menu) menu++;
1105         if (*menu == NULL)
1106                 goto invalid;
1107         return *menu;
1108
1109 invalid:
1110         return "<invalid>";
1111 }
1112
1113 void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1114 {
1115         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1116
1117         /* Stream */
1118         printk(KERN_INFO "%s: Stream: %s",
1119                 prefix,
1120                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1121         if (p->stream_insert_nav_packets)
1122                 printk(" (with navigation packets)");
1123         printk("\n");
1124         printk(KERN_INFO "%s: VBI Format: %s\n",
1125                 prefix,
1126                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1127
1128         /* Video */
1129         printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1130                 prefix,
1131                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1132                 p->is_50hz ? 25 : 30,
1133                 (p->video_mute) ? " (muted)" : "");
1134         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1135                 prefix,
1136                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1137                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1138                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1139                 p->video_bitrate);
1140         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1141                 printk(", Peak %d", p->video_bitrate_peak);
1142         printk("\n");
1143         printk(KERN_INFO
1144                 "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1145                 prefix,
1146                 p->video_gop_size, p->video_b_frames,
1147                 p->video_gop_closure ? "" : "No ");
1148         if (p->video_temporal_decimation)
1149                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1150                         prefix, p->video_temporal_decimation);
1151
1152         /* Audio */
1153         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1154                 prefix,
1155                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1156                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1157                 cx2341x_menu_item(p,
1158                            p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1159                                               ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1160                                               : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1161                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1162                 p->audio_mute ? " (muted)" : "");
1163         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1164                 printk(", %s", cx2341x_menu_item(p,
1165                                 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1166         printk(", %s, %s\n",
1167                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1168                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1169
1170         /* Encoding filters */
1171         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1172                 prefix,
1173                 cx2341x_menu_item(p,
1174                     V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1175                 cx2341x_menu_item(p,
1176                     V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1177                 cx2341x_menu_item(p,
1178                     V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1179                 p->video_spatial_filter);
1180
1181         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1182                 prefix,
1183                 cx2341x_menu_item(p,
1184                         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1185                 p->video_temporal_filter);
1186         printk(KERN_INFO
1187                 "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1188                 prefix,
1189                 cx2341x_menu_item(p,
1190                         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1191                 p->video_luma_median_filter_bottom,
1192                 p->video_luma_median_filter_top,
1193                 p->video_chroma_median_filter_bottom,
1194                 p->video_chroma_median_filter_top);
1195 }
1196 EXPORT_SYMBOL(cx2341x_log_status);
1197
1198 /*
1199  * Local variables:
1200  * c-basic-offset: 8
1201  * End:
1202  */
1203