V4L/DVB (12135): Add a driver for mt9v011 sensor
[linux-2.6.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
1004         if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
1005                 /* Adjust temporal filter if necessary. The problem with the
1006                    temporal filter is that it works well with full resolution
1007                    capturing, but not when the capture window is scaled (the
1008                    filter introduces a ghosting effect). So if the capture
1009                    window is scaled, then force the filter to 0.
1010
1011                    For full resolution the filter really improves the video
1012                    quality, especially if the original video quality is
1013                    suboptimal. */
1014                 temporal = 0;
1015         }
1016
1017         if (force || NEQ(stream_type)) {
1018                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1019                                   mpeg_stream_type[new->stream_type]);
1020                 if (err) return err;
1021         }
1022         if (force || NEQ(video_aspect)) {
1023                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1024                                   1 + new->video_aspect);
1025                 if (err) return err;
1026         }
1027         if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1028                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1029                                 new->video_gop_size, new->video_b_frames + 1);
1030                 if (err) return err;
1031         }
1032         if (force || NEQ(video_gop_closure)) {
1033                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1034                                   new->video_gop_closure);
1035                 if (err) return err;
1036         }
1037         if (force || NEQ(audio_properties)) {
1038                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1039                                   1, new->audio_properties);
1040                 if (err) return err;
1041         }
1042         if (force || NEQ(audio_mute)) {
1043                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1044                                   new->audio_mute);
1045                 if (err) return err;
1046         }
1047         if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1048                                                 NEQ(video_bitrate_peak)) {
1049                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1050                                 new->video_bitrate_mode, new->video_bitrate,
1051                                 new->video_bitrate_peak / 400, 0, 0);
1052                 if (err) return err;
1053         }
1054         if (force || NEQ(video_spatial_filter_mode) ||
1055                      NEQ(video_temporal_filter_mode) ||
1056                      NEQ(video_median_filter_type)) {
1057                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1058                                   2, new->video_spatial_filter_mode |
1059                                         (new->video_temporal_filter_mode << 1),
1060                                 new->video_median_filter_type);
1061                 if (err) return err;
1062         }
1063         if (force || NEQ(video_luma_median_filter_bottom) ||
1064                      NEQ(video_luma_median_filter_top) ||
1065                      NEQ(video_chroma_median_filter_bottom) ||
1066                      NEQ(video_chroma_median_filter_top)) {
1067                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1068                                 new->video_luma_median_filter_bottom,
1069                                 new->video_luma_median_filter_top,
1070                                 new->video_chroma_median_filter_bottom,
1071                                 new->video_chroma_median_filter_top);
1072                 if (err) return err;
1073         }
1074         if (force || NEQ(video_luma_spatial_filter_type) ||
1075                      NEQ(video_chroma_spatial_filter_type)) {
1076                 err = cx2341x_api(priv, func,
1077                                   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1078                                   2, new->video_luma_spatial_filter_type,
1079                                   new->video_chroma_spatial_filter_type);
1080                 if (err) return err;
1081         }
1082         if (force || NEQ(video_spatial_filter) ||
1083                      old->video_temporal_filter != temporal) {
1084                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1085                                   2, new->video_spatial_filter, temporal);
1086                 if (err) return err;
1087         }
1088         if (force || NEQ(video_temporal_decimation)) {
1089                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1090                                   1, new->video_temporal_decimation);
1091                 if (err) return err;
1092         }
1093         if (force || NEQ(video_mute) ||
1094                 (new->video_mute && NEQ(video_mute_yuv))) {
1095                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1096                                 new->video_mute | (new->video_mute_yuv << 8));
1097                 if (err) return err;
1098         }
1099         if (force || NEQ(stream_insert_nav_packets)) {
1100                 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1101                                 7, new->stream_insert_nav_packets);
1102                 if (err) return err;
1103         }
1104         return 0;
1105 }
1106 EXPORT_SYMBOL(cx2341x_update);
1107
1108 static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1109 {
1110         const char **menu = cx2341x_ctrl_get_menu(p, id);
1111         struct v4l2_ext_control ctrl;
1112
1113         if (menu == NULL)
1114                 goto invalid;
1115         ctrl.id = id;
1116         if (cx2341x_get_ctrl(p, &ctrl))
1117                 goto invalid;
1118         while (ctrl.value-- && *menu) menu++;
1119         if (*menu == NULL)
1120                 goto invalid;
1121         return *menu;
1122
1123 invalid:
1124         return "<invalid>";
1125 }
1126
1127 void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1128 {
1129         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1130         int temporal = p->video_temporal_filter;
1131
1132         /* Stream */
1133         printk(KERN_INFO "%s: Stream: %s",
1134                 prefix,
1135                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1136         if (p->stream_insert_nav_packets)
1137                 printk(" (with navigation packets)");
1138         printk("\n");
1139         printk(KERN_INFO "%s: VBI Format: %s\n",
1140                 prefix,
1141                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1142
1143         /* Video */
1144         printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1145                 prefix,
1146                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1147                 p->is_50hz ? 25 : 30,
1148                 (p->video_mute) ? " (muted)" : "");
1149         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1150                 prefix,
1151                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1152                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1153                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1154                 p->video_bitrate);
1155         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1156                 printk(", Peak %d", p->video_bitrate_peak);
1157         printk("\n");
1158         printk(KERN_INFO
1159                 "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1160                 prefix,
1161                 p->video_gop_size, p->video_b_frames,
1162                 p->video_gop_closure ? "" : "No ");
1163         if (p->video_temporal_decimation)
1164                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1165                         prefix, p->video_temporal_decimation);
1166
1167         /* Audio */
1168         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1169                 prefix,
1170                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1171                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1172                 cx2341x_menu_item(p,
1173                            p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1174                                               ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1175                                               : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1176                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1177                 p->audio_mute ? " (muted)" : "");
1178         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1179                 printk(", %s", cx2341x_menu_item(p,
1180                                 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1181         printk(", %s, %s\n",
1182                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1183                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1184
1185         /* Encoding filters */
1186         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1187                 prefix,
1188                 cx2341x_menu_item(p,
1189                     V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1190                 cx2341x_menu_item(p,
1191                     V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1192                 cx2341x_menu_item(p,
1193                     V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1194                 p->video_spatial_filter);
1195
1196         if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1197                 temporal = 0;
1198
1199         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1200                 prefix,
1201                 cx2341x_menu_item(p,
1202                         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1203                 temporal);
1204         printk(KERN_INFO
1205                 "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1206                 prefix,
1207                 cx2341x_menu_item(p,
1208                         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1209                 p->video_luma_median_filter_bottom,
1210                 p->video_luma_median_filter_top,
1211                 p->video_chroma_median_filter_bottom,
1212                 p->video_chroma_median_filter_top);
1213 }
1214 EXPORT_SYMBOL(cx2341x_log_status);
1215
1216 /*
1217  * Local variables:
1218  * c-basic-offset: 8
1219  * End:
1220  */
1221