Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[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 = 0,
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
735         cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
736
737         if (old == NULL || old->is_50hz != new->is_50hz) {
738                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
739                 if (err) return err;
740         }
741
742         if (old == NULL || old->width != new->width || old->height != new->height ||
743                         old->video_encoding != new->video_encoding) {
744                 u16 w = new->width;
745                 u16 h = new->height;
746
747                 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
748                         w /= 2;
749                         h /= 2;
750                 }
751                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
752                 if (err) return err;
753         }
754
755         if (old == NULL || old->stream_type != new->stream_type) {
756                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
757                 if (err) return err;
758         }
759         if (old == NULL || old->video_aspect != new->video_aspect) {
760                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
761                 if (err) return err;
762         }
763         if (old == NULL || old->video_b_frames != new->video_b_frames ||
764                 old->video_gop_size != new->video_gop_size) {
765                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
766                                 new->video_gop_size, new->video_b_frames + 1);
767                 if (err) return err;
768         }
769         if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
770                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
771                 if (err) return err;
772         }
773         if (old == NULL || old->video_pulldown != new->video_pulldown) {
774                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
775                 if (err) return err;
776         }
777         if (old == NULL || old->audio_properties != new->audio_properties) {
778                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
779                 if (err) return err;
780         }
781         if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
782                 old->video_bitrate != new->video_bitrate ||
783                 old->video_bitrate_peak != new->video_bitrate_peak) {
784                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
785                                 new->video_bitrate_mode, new->video_bitrate,
786                                 new->video_bitrate_peak / 400, 0, 0);
787                 if (err) return err;
788         }
789         if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
790                 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
791                 old->video_median_filter_type != new->video_median_filter_type) {
792                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
793                                 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
794                                 new->video_median_filter_type);
795                 if (err) return err;
796         }
797         if (old == NULL ||
798                 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
799                 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
800                 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
801                 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
802                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
803                                 new->video_luma_median_filter_bottom,
804                                 new->video_luma_median_filter_top,
805                                 new->video_chroma_median_filter_bottom,
806                                 new->video_chroma_median_filter_top);
807                 if (err) return err;
808         }
809         if (old == NULL ||
810                 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
811                 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
812                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
813                         new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
814                 if (err) return err;
815         }
816         if (old == NULL ||
817                 old->video_spatial_filter != new->video_spatial_filter ||
818                 old->video_temporal_filter != new->video_temporal_filter) {
819                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
820                         new->video_spatial_filter, new->video_temporal_filter);
821                 if (err) return err;
822         }
823         if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
824                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
825                         new->video_temporal_decimation);
826                 if (err) return err;
827         }
828         return 0;
829 }
830
831 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
832 {
833         const char **menu = cx2341x_ctrl_get_menu(id);
834         struct v4l2_ext_control ctrl;
835
836         if (menu == NULL)
837                 goto invalid;
838         ctrl.id = id;
839         if (cx2341x_get_ctrl(p, &ctrl))
840                 goto invalid;
841         while (ctrl.value-- && *menu) menu++;
842         if (*menu == NULL)
843                 goto invalid;
844         return *menu;
845
846 invalid:
847         return "<invalid>";
848 }
849
850 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
851 {
852         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
853
854         /* Stream */
855         printk(KERN_INFO "%s: Stream: %s\n",
856                 prefix,
857                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
858
859         /* Video */
860         printk(KERN_INFO "%s: Video:  %dx%d, %d fps\n",
861                 prefix,
862                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
863                 p->is_50hz ? 25 : 30);
864         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
865                 prefix,
866                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
867                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
868                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
869                 p->video_bitrate);
870         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
871                 printk(", Peak %d", p->video_bitrate_peak);
872         }
873         printk("\n");
874         printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
875                 prefix,
876                 p->video_gop_size, p->video_b_frames,
877                 p->video_gop_closure ? "" : "No ",
878                 p->video_pulldown ? "" : "No ");
879         if (p->video_temporal_decimation) {
880                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
881                         prefix, p->video_temporal_decimation);
882         }
883
884         /* Audio */
885         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s",
886                 prefix,
887                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
888                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
889                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
890                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
891         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
892                 printk(", %s",
893                         cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
894         }
895         printk(", %s, %s\n",
896                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
897                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
898
899         /* Encoding filters */
900         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
901                 prefix,
902                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
903                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
904                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
905                 p->video_spatial_filter);
906         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
907                 prefix,
908                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
909                 p->video_temporal_filter);
910         printk(KERN_INFO "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
911                 prefix,
912                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
913                 p->video_luma_median_filter_bottom,
914                 p->video_luma_median_filter_top,
915                 p->video_chroma_median_filter_bottom,
916                 p->video_chroma_median_filter_top);
917 }
918
919 EXPORT_SYMBOL(cx2341x_fill_defaults);
920 EXPORT_SYMBOL(cx2341x_ctrl_query);
921 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
922 EXPORT_SYMBOL(cx2341x_ext_ctrls);
923 EXPORT_SYMBOL(cx2341x_update);
924 EXPORT_SYMBOL(cx2341x_log_status);
925 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
926
927 /*
928  * Local variables:
929  * c-basic-offset: 8
930  * End:
931  */
932