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