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