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