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