Merge ../linux-2.6-watchdog-mm
[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_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                 u16 w = new->width;
746                 u16 h = new->height;
747
748                 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
749                         w /= 2;
750                         h /= 2;
751                 }
752                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
753                 if (err) return err;
754         }
755
756         if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
757                 /* Adjust temporal filter if necessary. The problem with the temporal
758                    filter is that it works well with full resolution capturing, but
759                    not when the capture window is scaled (the filter introduces
760                    a ghosting effect). So if the capture window is scaled, then
761                    force the filter to 0.
762
763                    For full resolution the filter really improves the video
764                    quality, especially if the original video quality is suboptimal. */
765                 temporal = 0;
766         }
767
768         if (old == NULL || old->stream_type != new->stream_type) {
769                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
770                 if (err) return err;
771         }
772         if (old == NULL || old->video_aspect != new->video_aspect) {
773                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
774                 if (err) return err;
775         }
776         if (old == NULL || old->video_b_frames != new->video_b_frames ||
777                 old->video_gop_size != new->video_gop_size) {
778                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
779                                 new->video_gop_size, new->video_b_frames + 1);
780                 if (err) return err;
781         }
782         if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
783                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
784                 if (err) return err;
785         }
786         if (old == NULL || old->video_pulldown != new->video_pulldown) {
787                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
788                 if (err) return err;
789         }
790         if (old == NULL || old->audio_properties != new->audio_properties) {
791                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
792                 if (err) return err;
793         }
794         if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
795                 old->video_bitrate != new->video_bitrate ||
796                 old->video_bitrate_peak != new->video_bitrate_peak) {
797                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
798                                 new->video_bitrate_mode, new->video_bitrate,
799                                 new->video_bitrate_peak / 400, 0, 0);
800                 if (err) return err;
801         }
802         if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
803                 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
804                 old->video_median_filter_type != new->video_median_filter_type) {
805                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
806                                 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
807                                 new->video_median_filter_type);
808                 if (err) return err;
809         }
810         if (old == NULL ||
811                 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
812                 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
813                 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
814                 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
815                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
816                                 new->video_luma_median_filter_bottom,
817                                 new->video_luma_median_filter_top,
818                                 new->video_chroma_median_filter_bottom,
819                                 new->video_chroma_median_filter_top);
820                 if (err) return err;
821         }
822         if (old == NULL ||
823                 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
824                 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
825                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
826                         new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
827                 if (err) return err;
828         }
829         if (old == NULL ||
830                 old->video_spatial_filter != new->video_spatial_filter ||
831                 old->video_temporal_filter != temporal) {
832                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
833                         new->video_spatial_filter, temporal);
834                 if (err) return err;
835         }
836         if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
837                 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
838                         new->video_temporal_decimation);
839                 if (err) return err;
840         }
841         return 0;
842 }
843
844 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
845 {
846         const char **menu = cx2341x_ctrl_get_menu(id);
847         struct v4l2_ext_control ctrl;
848
849         if (menu == NULL)
850                 goto invalid;
851         ctrl.id = id;
852         if (cx2341x_get_ctrl(p, &ctrl))
853                 goto invalid;
854         while (ctrl.value-- && *menu) menu++;
855         if (*menu == NULL)
856                 goto invalid;
857         return *menu;
858
859 invalid:
860         return "<invalid>";
861 }
862
863 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
864 {
865         int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
866         int temporal = p->video_temporal_filter;
867
868         /* Stream */
869         printk(KERN_INFO "%s: Stream: %s\n",
870                 prefix,
871                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
872         printk(KERN_INFO "%s: VBI Format: %s\n",
873                 prefix,
874                 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
875
876         /* Video */
877         printk(KERN_INFO "%s: Video:  %dx%d, %d fps\n",
878                 prefix,
879                 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
880                 p->is_50hz ? 25 : 30);
881         printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
882                 prefix,
883                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
884                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
885                 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
886                 p->video_bitrate);
887         if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
888                 printk(", Peak %d", p->video_bitrate_peak);
889         }
890         printk("\n");
891         printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
892                 prefix,
893                 p->video_gop_size, p->video_b_frames,
894                 p->video_gop_closure ? "" : "No ",
895                 p->video_pulldown ? "" : "No ");
896         if (p->video_temporal_decimation) {
897                 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
898                         prefix, p->video_temporal_decimation);
899         }
900
901         /* Audio */
902         printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s",
903                 prefix,
904                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
905                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
906                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
907                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
908         if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
909                 printk(", %s",
910                         cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
911         }
912         printk(", %s, %s\n",
913                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
914                 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
915
916         /* Encoding filters */
917         printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
918                 prefix,
919                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
920                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
921                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
922                 p->video_spatial_filter);
923         if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
924                 temporal = 0;
925         }
926         printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
927                 prefix,
928                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
929                 temporal);
930         printk(KERN_INFO "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
931                 prefix,
932                 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
933                 p->video_luma_median_filter_bottom,
934                 p->video_luma_median_filter_top,
935                 p->video_chroma_median_filter_bottom,
936                 p->video_chroma_median_filter_top);
937 }
938
939 EXPORT_SYMBOL(cx2341x_fill_defaults);
940 EXPORT_SYMBOL(cx2341x_ctrl_query);
941 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
942 EXPORT_SYMBOL(cx2341x_ext_ctrls);
943 EXPORT_SYMBOL(cx2341x_update);
944 EXPORT_SYMBOL(cx2341x_log_status);
945 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
946
947 /*
948  * Local variables:
949  * c-basic-offset: 8
950  * End:
951  */
952