Merge branch 'topic/hdsp' into for-linus
[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_STREAM_TYPE:
504                 return v4l2_ctrl_query_fill(qctrl,
505                                 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
506                                 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
507                                 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
508
509         case V4L2_CID_MPEG_STREAM_VBI_FMT:
510                 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
511                         return v4l2_ctrl_query_fill(qctrl,
512                                         V4L2_MPEG_STREAM_VBI_FMT_NONE,
513                                         V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
514                                         V4L2_MPEG_STREAM_VBI_FMT_NONE);
515                 return cx2341x_ctrl_query_fill(qctrl,
516                                 V4L2_MPEG_STREAM_VBI_FMT_NONE,
517                                 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
518                                 default_params.stream_vbi_fmt);
519
520         case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
521                 return v4l2_ctrl_query_fill(qctrl,
522                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
523                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
524                                 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
525
526         case V4L2_CID_MPEG_AUDIO_ENCODING:
527                 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
528                         /*
529                          * The state of L2 & AC3 bitrate controls can change
530                          * when this control changes, but v4l2_ctrl_query_fill()
531                          * already sets V4L2_CTRL_FLAG_UPDATE for
532                          * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
533                          */
534                         return v4l2_ctrl_query_fill(qctrl,
535                                         V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
536                                         V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
537                                         default_params.audio_encoding);
538                 }
539
540                 return v4l2_ctrl_query_fill(qctrl,
541                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
542                                 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
543                                 default_params.audio_encoding);
544
545         case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
546                 err = v4l2_ctrl_query_fill(qctrl,
547                                 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
548                                 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
549                                 default_params.audio_l2_bitrate);
550                 if (err)
551                         return err;
552                 if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
553                     params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
554                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
555                 return 0;
556
557         case V4L2_CID_MPEG_AUDIO_MODE:
558                 return v4l2_ctrl_query_fill(qctrl,
559                                 V4L2_MPEG_AUDIO_MODE_STEREO,
560                                 V4L2_MPEG_AUDIO_MODE_MONO, 1,
561                                 V4L2_MPEG_AUDIO_MODE_STEREO);
562
563         case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
564                 err = v4l2_ctrl_query_fill(qctrl,
565                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
566                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
567                                 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
568                 if (err == 0 &&
569                     params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
570                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
571                 return err;
572
573         case V4L2_CID_MPEG_AUDIO_EMPHASIS:
574                 return v4l2_ctrl_query_fill(qctrl,
575                                 V4L2_MPEG_AUDIO_EMPHASIS_NONE,
576                                 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
577                                 V4L2_MPEG_AUDIO_EMPHASIS_NONE);
578
579         case V4L2_CID_MPEG_AUDIO_CRC:
580                 return v4l2_ctrl_query_fill(qctrl,
581                                 V4L2_MPEG_AUDIO_CRC_NONE,
582                                 V4L2_MPEG_AUDIO_CRC_CRC16, 1,
583                                 V4L2_MPEG_AUDIO_CRC_NONE);
584
585         case V4L2_CID_MPEG_AUDIO_MUTE:
586                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
587
588         case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
589                 err = v4l2_ctrl_query_fill(qctrl,
590                                 V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
591                                 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
592                                 default_params.audio_ac3_bitrate);
593                 if (err)
594                         return err;
595                 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
596                         if (params->audio_encoding !=
597                                                    V4L2_MPEG_AUDIO_ENCODING_AC3)
598                                 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
599                 } else
600                         qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
601                 return 0;
602
603         case V4L2_CID_MPEG_VIDEO_ENCODING:
604                 /* this setting is read-only for the cx2341x since the
605                    V4L2_CID_MPEG_STREAM_TYPE really determines the
606                    MPEG-1/2 setting */
607                 err = v4l2_ctrl_query_fill(qctrl,
608                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
609                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
610                                            V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
611                 if (err == 0)
612                         qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
613                 return err;
614
615         case V4L2_CID_MPEG_VIDEO_ASPECT:
616                 return v4l2_ctrl_query_fill(qctrl,
617                                 V4L2_MPEG_VIDEO_ASPECT_1x1,
618                                 V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
619                                 V4L2_MPEG_VIDEO_ASPECT_4x3);
620
621         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
622                 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
623
624         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
625                 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
626                                 params->is_50hz ? 12 : 15);
627
628         case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
629                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
630
631         case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
632                 err = v4l2_ctrl_query_fill(qctrl,
633                                 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
634                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
635                                 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
636                 if (err == 0 &&
637                     params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
638                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
639                 return err;
640
641         case V4L2_CID_MPEG_VIDEO_BITRATE:
642                 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
643
644         case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
645                 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
646                 if (err == 0 &&
647                     params->video_bitrate_mode ==
648                                 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
649                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
650                 return err;
651
652         case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
653                 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
654
655         case V4L2_CID_MPEG_VIDEO_MUTE:
656                 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
657
658         case V4L2_CID_MPEG_VIDEO_MUTE_YUV:  /* Init YUV (really YCbCr) to black */
659                 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
660
661         /* CX23415/6 specific */
662         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
663                 return cx2341x_ctrl_query_fill(qctrl,
664                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
665                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
666                         default_params.video_spatial_filter_mode);
667
668         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
669                 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
670                                 default_params.video_spatial_filter);
671                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
672                 if (params->video_spatial_filter_mode ==
673                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
674                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
675                 return 0;
676
677         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
678                 cx2341x_ctrl_query_fill(qctrl,
679                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
680                         V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
681                         1,
682                         default_params.video_luma_spatial_filter_type);
683                 if (params->video_spatial_filter_mode ==
684                             V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
685                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
686                 return 0;
687
688         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
689                 cx2341x_ctrl_query_fill(qctrl,
690                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
691                     V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
692                     1,
693                     default_params.video_chroma_spatial_filter_type);
694                 if (params->video_spatial_filter_mode ==
695                         V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
696                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
697                 return 0;
698
699         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
700                 return cx2341x_ctrl_query_fill(qctrl,
701                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
702                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
703                         default_params.video_temporal_filter_mode);
704
705         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
706                 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
707                                 default_params.video_temporal_filter);
708                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
709                 if (params->video_temporal_filter_mode ==
710                         V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
711                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
712                 return 0;
713
714         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
715                 return cx2341x_ctrl_query_fill(qctrl,
716                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
717                         V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
718                         default_params.video_median_filter_type);
719
720         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
721                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
722                                 default_params.video_luma_median_filter_top);
723                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
724                 if (params->video_median_filter_type ==
725                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
726                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
727                 return 0;
728
729         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
730                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
731                                 default_params.video_luma_median_filter_bottom);
732                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
733                 if (params->video_median_filter_type ==
734                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
735                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
736                 return 0;
737
738         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
739                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
740                                 default_params.video_chroma_median_filter_top);
741                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
742                 if (params->video_median_filter_type ==
743                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
744                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
745                 return 0;
746
747         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
748                 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
749                         default_params.video_chroma_median_filter_bottom);
750                 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
751                 if (params->video_median_filter_type ==
752                                 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
753                         qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
754                 return 0;
755
756         case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
757                 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
758                                 default_params.stream_insert_nav_packets);
759
760         default:
761                 return -EINVAL;
762
763         }
764 }
765 EXPORT_SYMBOL(cx2341x_ctrl_query);
766
767 const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
768 {
769         static const char *mpeg_stream_type_without_ts[] = {
770                 "MPEG-2 Program Stream",
771                 "",
772                 "MPEG-1 System Stream",
773                 "MPEG-2 DVD-compatible Stream",
774                 "MPEG-1 VCD-compatible Stream",
775                 "MPEG-2 SVCD-compatible Stream",
776                 NULL
777         };
778
779         static const char *mpeg_stream_type_with_ts[] = {
780                 "MPEG-2 Program Stream",
781                 "MPEG-2 Transport Stream",
782                 "MPEG-1 System Stream",
783                 "MPEG-2 DVD-compatible Stream",
784                 "MPEG-1 VCD-compatible Stream",
785                 "MPEG-2 SVCD-compatible Stream",
786                 NULL
787         };
788
789         static const char *mpeg_audio_encoding_l2_ac3[] = {
790                 "",
791                 "MPEG-1/2 Layer II",
792                 "",
793                 "",
794                 "AC-3",
795                 NULL
796         };
797
798         static const char *cx2341x_video_spatial_filter_mode_menu[] = {
799                 "Manual",
800                 "Auto",
801                 NULL
802         };
803
804         static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
805                 "Off",
806                 "1D Horizontal",
807                 "1D Vertical",
808                 "2D H/V Separable",
809                 "2D Symmetric non-separable",
810                 NULL
811         };
812
813         static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
814                 "Off",
815                 "1D Horizontal",
816                 NULL
817         };
818
819         static const char *cx2341x_video_temporal_filter_mode_menu[] = {
820                 "Manual",
821                 "Auto",
822                 NULL
823         };
824
825         static const char *cx2341x_video_median_filter_type_menu[] = {
826                 "Off",
827                 "Horizontal",
828                 "Vertical",
829                 "Horizontal/Vertical",
830                 "Diagonal",
831                 NULL
832         };
833
834         switch (id) {
835         case V4L2_CID_MPEG_STREAM_TYPE:
836                 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
837                         mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
838         case V4L2_CID_MPEG_AUDIO_ENCODING:
839                 return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
840                         mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
841         case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
842         case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
843                 return NULL;
844         case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
845                 return cx2341x_video_spatial_filter_mode_menu;
846         case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
847                 return cx2341x_video_luma_spatial_filter_type_menu;
848         case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
849                 return cx2341x_video_chroma_spatial_filter_type_menu;
850         case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
851                 return cx2341x_video_temporal_filter_mode_menu;
852         case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
853                 return cx2341x_video_median_filter_type_menu;
854         default:
855                 return v4l2_ctrl_get_menu(id);
856         }
857 }
858 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
859
860 /* definitions for audio properties bits 29-28 */
861 #define CX2341X_AUDIO_ENCODING_METHOD_MPEG      0
862 #define CX2341X_AUDIO_ENCODING_METHOD_AC3       1
863 #define CX2341X_AUDIO_ENCODING_METHOD_LPCM      2
864
865 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
866 {
867         params->audio_properties =
868                 (params->audio_sampling_freq << 0) |
869                 (params->audio_mode << 8) |
870                 (params->audio_mode_extension << 10) |
871                 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
872                   ? 3 : params->audio_emphasis) << 12) |
873                 (params->audio_crc << 14);
874
875         if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
876             params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
877                 params->audio_properties |=
878                         /* Not sure if this MPEG Layer II setting is required */
879                         ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
880                         (params->audio_ac3_bitrate << 4) |
881                         (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
882         } else {
883                 /* Assuming MPEG Layer II */
884                 params->audio_properties |=
885                         ((3 - params->audio_encoding) << 2) |
886                         ((1 + params->audio_l2_bitrate) << 4);
887         }
888 }
889
890 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
891                   struct v4l2_ext_controls *ctrls, unsigned int cmd)
892 {
893         int err = 0;
894         int i;
895
896         if (cmd == VIDIOC_G_EXT_CTRLS) {
897                 for (i = 0; i < ctrls->count; i++) {
898                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
899
900                         err = cx2341x_get_ctrl(params, ctrl);
901                         if (err) {
902                                 ctrls->error_idx = i;
903                                 break;
904                         }
905                 }
906                 return err;
907         }
908         for (i = 0; i < ctrls->count; i++) {
909                 struct v4l2_ext_control *ctrl = ctrls->controls + i;
910                 struct v4l2_queryctrl qctrl;
911                 const char **menu_items = NULL;
912
913                 qctrl.id = ctrl->id;
914                 err = cx2341x_ctrl_query(params, &qctrl);
915                 if (err)
916                         break;
917                 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
918                         menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
919                 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
920                 if (err)
921                         break;
922                 err = cx2341x_set_ctrl(params, busy, ctrl);
923                 if (err)
924                         break;
925         }
926         if (err == 0 &&
927             params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
928             params->video_bitrate_peak < params->video_bitrate) {
929                 err = -ERANGE;
930                 ctrls->error_idx = ctrls->count;
931         }
932         if (err)
933                 ctrls->error_idx = i;
934         else
935                 cx2341x_calc_audio_properties(params);
936         return err;
937 }
938 EXPORT_SYMBOL(cx2341x_ext_ctrls);
939
940 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
941 {
942         *p = default_params;
943         cx2341x_calc_audio_properties(p);
944 }
945 EXPORT_SYMBOL(cx2341x_fill_defaults);
946
947 static int cx2341x_api(void *priv, cx2341x_mbox_func func,
948                        u32 cmd, int args, ...)
949 {
950         u32 data[CX2341X_MBOX_MAX_DATA];
951         va_list vargs;
952         int i;
953
954         va_start(vargs, args);
955
956         for (i = 0; i < args; i++)
957                 data[i] = va_arg(vargs, int);
958         va_end(vargs);
959         return func(priv, cmd, args, 0, data);
960 }
961
962 #define NEQ(field) (old->field != new->field)
963
964 int cx2341x_update(void *priv, cx2341x_mbox_func func,
965                    const struct cx2341x_mpeg_params *old,
966                    const struct cx2341x_mpeg_params *new)
967 {
968         static int mpeg_stream_type[] = {
969                 0,      /* MPEG-2 PS */
970                 1,      /* MPEG-2 TS */
971                 2,      /* MPEG-1 SS */
972                 14,     /* DVD */
973                 11,     /* VCD */
974                 12,     /* SVCD */
975         };
976
977         int err = 0;
978         int force = (old == NULL);
979         u16 temporal = new->video_temporal_filter;
980
981         cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
982
983         if (force || NEQ(is_50hz)) {
984                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
985                                   new->is_50hz);
986                 if (err) return err;
987         }
988
989         if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
990                 u16 w = new->width;
991                 u16 h = new->height;
992
993                 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
994                         w /= 2;
995                         h /= 2;
996                 }
997                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
998                                   h, w);
999                 if (err) return err;
1000         }
1001
1002         if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
1003                 /* Adjust temporal filter if necessary. The problem with the
1004                    temporal filter is that it works well with full resolution
1005                    capturing, but not when the capture window is scaled (the
1006                    filter introduces a ghosting effect). So if the capture
1007                    window is scaled, then force the filter to 0.
1008
1009                    For full resolution the filter really improves the video
1010                    quality, especially if the original video quality is
1011                    suboptimal. */
1012                 temporal = 0;
1013         }
1014
1015         if (force || NEQ(stream_type)) {
1016                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1017                                   mpeg_stream_type[new->stream_type]);
1018                 if (err) return err;
1019         }
1020         if (force || NEQ(video_aspect)) {
1021                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1022                                   1 + new->video_aspect);
1023                 if (err) return err;
1024         }
1025         if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1026                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1027                                 new->video_gop_size, new->video_b_frames + 1);
1028                 if (err) return err;
1029         }
1030         if (force || NEQ(video_gop_closure)) {
1031                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1032                                   new->video_gop_closure);
1033                 if (err) return err;
1034         }
1035         if (force || NEQ(audio_properties)) {
1036                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1037                                   1, new->audio_properties);
1038                 if (err) return err;
1039         }
1040         if (force || NEQ(audio_mute)) {
1041                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1042                                   new->audio_mute);
1043                 if (err) return err;
1044         }
1045         if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1046                                                 NEQ(video_bitrate_peak)) {
1047                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1048                                 new->video_bitrate_mode, new->video_bitrate,
1049                                 new->video_bitrate_peak / 400, 0, 0);
1050                 if (err) return err;
1051         }
1052         if (force || NEQ(video_spatial_filter_mode) ||
1053                      NEQ(video_temporal_filter_mode) ||
1054                      NEQ(video_median_filter_type)) {
1055                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1056                                   2, new->video_spatial_filter_mode |
1057                                         (new->video_temporal_filter_mode << 1),
1058                                 new->video_median_filter_type);
1059                 if (err) return err;
1060         }
1061         if (force || NEQ(video_luma_median_filter_bottom) ||
1062                      NEQ(video_luma_median_filter_top) ||
1063                      NEQ(video_chroma_median_filter_bottom) ||
1064                      NEQ(video_chroma_median_filter_top)) {
1065                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1066                                 new->video_luma_median_filter_bottom,
1067                                 new->video_luma_median_filter_top,
1068                                 new->video_chroma_median_filter_bottom,
1069                                 new->video_chroma_median_filter_top);
1070                 if (err) return err;
1071         }
1072         if (force || NEQ(video_luma_spatial_filter_type) ||
1073                      NEQ(video_chroma_spatial_filter_type)) {
1074                 err = cx2341x_api(priv, func,
1075                                   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1076                                   2, new->video_luma_spatial_filter_type,
1077                                   new->video_chroma_spatial_filter_type);
1078                 if (err) return err;
1079         }
1080         if (force || NEQ(video_spatial_filter) ||
1081                      old->video_temporal_filter != temporal) {
1082                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1083                                   2, new->video_spatial_filter, temporal);
1084                 if (err) return err;
1085         }
1086         if (force || NEQ(video_temporal_decimation)) {
1087                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1088                                   1, new->video_temporal_decimation);
1089                 if (err) return err;
1090         }
1091         if (force || NEQ(video_mute) ||
1092                 (new->video_mute && NEQ(video_mute_yuv))) {
1093                 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1094                                 new->video_mute | (new->video_mute_yuv << 8));
1095                 if (err) return err;
1096         }
1097         if (force || NEQ(stream_insert_nav_packets)) {
1098                 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1099                                 7, new->stream_insert_nav_packets);
1100                 if (err) return err;
1101         }
1102         return 0;
1103 }
1104 EXPORT_SYMBOL(cx2341x_update);
1105
1106 static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1107 {
1108         const char **menu = cx2341x_ctrl_get_menu(p, id);
1109         struct v4l2_ext_control ctrl;
1110
1111         if (menu == NULL)
1112                 goto invalid;
1113         ctrl.id = id;
1114         if (cx2341x_get_ctrl(p, &ctrl))
1115                 goto invalid;
1116         while (ctrl.value-- && *menu) menu++;
1117         if (*menu == NULL)
1118                 goto invalid;
1119         return *menu;
1120
1121 invalid:
1122         return "<invalid>";
1123 }
1124
1125 void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1126 {
1127         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1128         int temporal = p->video_temporal_filter;
1129
1130         /* Stream */
1131         printk(KERN_INFO "%s: Stream: %s",
1132                 prefix,
1133                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1134         if (p->stream_insert_nav_packets)
1135                 printk(" (with navigation packets)");
1136         printk("\n");
1137         printk(KERN_INFO "%s: VBI Format: %s\n",
1138                 prefix,
1139                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1140
1141         /* Video */
1142         printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1143                 prefix,
1144                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1145                 p->is_50hz ? 25 : 30,
1146                 (p->video_mute) ? " (muted)" : "");
1147         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1148                 prefix,
1149                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1150                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1151                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1152                 p->video_bitrate);
1153         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1154                 printk(", Peak %d", p->video_bitrate_peak);
1155         printk("\n");
1156         printk(KERN_INFO
1157                 "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1158                 prefix,
1159                 p->video_gop_size, p->video_b_frames,
1160                 p->video_gop_closure ? "" : "No ");
1161         if (p->video_temporal_decimation)
1162                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1163                         prefix, p->video_temporal_decimation);
1164
1165         /* Audio */
1166         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1167                 prefix,
1168                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1169                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1170                 cx2341x_menu_item(p,
1171                            p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1172                                               ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1173                                               : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1174                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1175                 p->audio_mute ? " (muted)" : "");
1176         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1177                 printk(", %s", cx2341x_menu_item(p,
1178                                 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1179         printk(", %s, %s\n",
1180                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1181                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1182
1183         /* Encoding filters */
1184         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1185                 prefix,
1186                 cx2341x_menu_item(p,
1187                     V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1188                 cx2341x_menu_item(p,
1189                     V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1190                 cx2341x_menu_item(p,
1191                     V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1192                 p->video_spatial_filter);
1193
1194         if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1195                 temporal = 0;
1196
1197         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1198                 prefix,
1199                 cx2341x_menu_item(p,
1200                         V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1201                 temporal);
1202         printk(KERN_INFO
1203                 "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1204                 prefix,
1205                 cx2341x_menu_item(p,
1206                         V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1207                 p->video_luma_median_filter_bottom,
1208                 p->video_luma_median_filter_top,
1209                 p->video_chroma_median_filter_bottom,
1210                 p->video_chroma_median_filter_top);
1211 }
1212 EXPORT_SYMBOL(cx2341x_log_status);
1213
1214 /*
1215  * Local variables:
1216  * c-basic-offset: 8
1217  * End:
1218  */
1219