2 * cx2341x - generic code for cx23415/6 based devices
4 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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.
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>
29 #include <media/tuner.h>
30 #include <media/cx2341x.h>
31 #include <media/v4l2-common.h>
33 MODULE_DESCRIPTION("cx23415/6 driver");
34 MODULE_AUTHOR("Hans Verkuil");
35 MODULE_LICENSE("GPL");
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "Debug level (0-1)");
41 const u32 cx2341x_mpeg_ctrls[] = {
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,
78 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
81 /* Map the control ID to the correct field in the cx2341x_mpeg_params
82 struct. Return -EINVAL if the ID is unknown, else return 0. */
83 static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
84 struct v4l2_ext_control *ctrl)
87 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
88 ctrl->value = params->audio_sampling_freq;
90 case V4L2_CID_MPEG_AUDIO_ENCODING:
91 ctrl->value = params->audio_encoding;
93 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
94 ctrl->value = params->audio_l2_bitrate;
96 case V4L2_CID_MPEG_AUDIO_MODE:
97 ctrl->value = params->audio_mode;
99 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
100 ctrl->value = params->audio_mode_extension;
102 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
103 ctrl->value = params->audio_emphasis;
105 case V4L2_CID_MPEG_AUDIO_CRC:
106 ctrl->value = params->audio_crc;
108 case V4L2_CID_MPEG_AUDIO_MUTE:
109 ctrl->value = params->audio_mute;
111 case V4L2_CID_MPEG_VIDEO_ENCODING:
112 ctrl->value = params->video_encoding;
114 case V4L2_CID_MPEG_VIDEO_ASPECT:
115 ctrl->value = params->video_aspect;
117 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
118 ctrl->value = params->video_b_frames;
120 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
121 ctrl->value = params->video_gop_size;
123 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
124 ctrl->value = params->video_gop_closure;
126 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
127 ctrl->value = params->video_bitrate_mode;
129 case V4L2_CID_MPEG_VIDEO_BITRATE:
130 ctrl->value = params->video_bitrate;
132 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
133 ctrl->value = params->video_bitrate_peak;
135 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
136 ctrl->value = params->video_temporal_decimation;
138 case V4L2_CID_MPEG_VIDEO_MUTE:
139 ctrl->value = params->video_mute;
141 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
142 ctrl->value = params->video_mute_yuv;
144 case V4L2_CID_MPEG_STREAM_TYPE:
145 ctrl->value = params->stream_type;
147 case V4L2_CID_MPEG_STREAM_VBI_FMT:
148 ctrl->value = params->stream_vbi_fmt;
150 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
151 ctrl->value = params->video_spatial_filter_mode;
153 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
154 ctrl->value = params->video_spatial_filter;
156 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
157 ctrl->value = params->video_luma_spatial_filter_type;
159 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
160 ctrl->value = params->video_chroma_spatial_filter_type;
162 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
163 ctrl->value = params->video_temporal_filter_mode;
165 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
166 ctrl->value = params->video_temporal_filter;
168 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
169 ctrl->value = params->video_median_filter_type;
171 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
172 ctrl->value = params->video_luma_median_filter_top;
174 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
175 ctrl->value = params->video_luma_median_filter_bottom;
177 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
178 ctrl->value = params->video_chroma_median_filter_top;
180 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
181 ctrl->value = params->video_chroma_median_filter_bottom;
183 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
184 ctrl->value = params->stream_insert_nav_packets;
192 /* Map the control ID to the correct field in the cx2341x_mpeg_params
193 struct. Return -EINVAL if the ID is unknown, else return 0. */
194 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
195 struct v4l2_ext_control *ctrl)
198 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
201 params->audio_sampling_freq = ctrl->value;
203 case V4L2_CID_MPEG_AUDIO_ENCODING:
204 params->audio_encoding = ctrl->value;
206 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
209 params->audio_l2_bitrate = ctrl->value;
211 case V4L2_CID_MPEG_AUDIO_MODE:
212 params->audio_mode = ctrl->value;
214 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
215 params->audio_mode_extension = ctrl->value;
217 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
218 params->audio_emphasis = ctrl->value;
220 case V4L2_CID_MPEG_AUDIO_CRC:
221 params->audio_crc = ctrl->value;
223 case V4L2_CID_MPEG_AUDIO_MUTE:
224 params->audio_mute = ctrl->value;
226 case V4L2_CID_MPEG_VIDEO_ASPECT:
227 params->video_aspect = ctrl->value;
229 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
230 int b = ctrl->value + 1;
231 int gop = params->video_gop_size;
232 params->video_b_frames = ctrl->value;
233 params->video_gop_size = b * ((gop + b - 1) / b);
234 /* Max GOP size = 34 */
235 while (params->video_gop_size > 34)
236 params->video_gop_size -= b;
239 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
240 int b = params->video_b_frames + 1;
241 int gop = ctrl->value;
242 params->video_gop_size = b * ((gop + b - 1) / b);
243 /* Max GOP size = 34 */
244 while (params->video_gop_size > 34)
245 params->video_gop_size -= b;
246 ctrl->value = params->video_gop_size;
249 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
250 params->video_gop_closure = ctrl->value;
252 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
255 /* MPEG-1 only allows CBR */
256 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
257 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
259 params->video_bitrate_mode = ctrl->value;
261 case V4L2_CID_MPEG_VIDEO_BITRATE:
264 params->video_bitrate = ctrl->value;
266 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
269 params->video_bitrate_peak = ctrl->value;
271 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
272 params->video_temporal_decimation = ctrl->value;
274 case V4L2_CID_MPEG_VIDEO_MUTE:
275 params->video_mute = (ctrl->value != 0);
277 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
278 params->video_mute_yuv = ctrl->value;
280 case V4L2_CID_MPEG_STREAM_TYPE:
283 params->stream_type = ctrl->value;
284 params->video_encoding =
285 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
286 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
287 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
288 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
289 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
290 /* MPEG-1 implies CBR */
291 params->video_bitrate_mode =
292 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
294 case V4L2_CID_MPEG_STREAM_VBI_FMT:
295 params->stream_vbi_fmt = ctrl->value;
297 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
298 params->video_spatial_filter_mode = ctrl->value;
300 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
301 params->video_spatial_filter = ctrl->value;
303 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
304 params->video_luma_spatial_filter_type = ctrl->value;
306 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
307 params->video_chroma_spatial_filter_type = ctrl->value;
309 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
310 params->video_temporal_filter_mode = ctrl->value;
312 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
313 params->video_temporal_filter = ctrl->value;
315 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
316 params->video_median_filter_type = ctrl->value;
318 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
319 params->video_luma_median_filter_top = ctrl->value;
321 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
322 params->video_luma_median_filter_bottom = ctrl->value;
324 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
325 params->video_chroma_median_filter_top = ctrl->value;
327 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
328 params->video_chroma_median_filter_bottom = ctrl->value;
330 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
331 params->stream_insert_nav_packets = ctrl->value;
339 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
340 s32 min, s32 max, s32 step, s32 def)
347 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
348 name = "Spatial Filter Mode";
350 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
351 name = "Spatial Filter";
353 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
354 name = "Spatial Luma Filter Type";
356 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
357 name = "Spatial Chroma Filter Type";
359 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
360 name = "Temporal Filter Mode";
362 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
363 name = "Temporal Filter";
365 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
366 name = "Median Filter Type";
368 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
369 name = "Median Luma Filter Maximum";
371 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
372 name = "Median Luma Filter Minimum";
374 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
375 name = "Median Chroma Filter Maximum";
377 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
378 name = "Median Chroma Filter Minimum";
380 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
381 name = "Insert Navigation Packets";
385 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
388 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
389 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
390 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
391 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
392 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
393 qctrl->type = V4L2_CTRL_TYPE_MENU;
397 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
398 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
404 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
408 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
409 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
410 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
411 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
414 qctrl->minimum = min;
415 qctrl->maximum = max;
417 qctrl->default_value = def;
418 qctrl->reserved[0] = qctrl->reserved[1] = 0;
419 snprintf(qctrl->name, sizeof(qctrl->name), name);
423 int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
424 struct v4l2_queryctrl *qctrl)
429 case V4L2_CID_MPEG_AUDIO_ENCODING:
430 return v4l2_ctrl_query_fill(qctrl,
431 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
432 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
433 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
435 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436 return v4l2_ctrl_query_fill(qctrl,
437 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
438 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
439 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
441 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
442 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
445 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
446 err = v4l2_ctrl_query_fill_std(qctrl);
448 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
449 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
452 case V4L2_CID_MPEG_VIDEO_ENCODING:
453 /* this setting is read-only for the cx2341x since the
454 V4L2_CID_MPEG_STREAM_TYPE really determines the
456 err = v4l2_ctrl_query_fill_std(qctrl);
458 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
461 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
462 err = v4l2_ctrl_query_fill_std(qctrl);
464 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
468 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
469 err = v4l2_ctrl_query_fill_std(qctrl);
471 params->video_bitrate_mode ==
472 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
473 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
476 case V4L2_CID_MPEG_STREAM_VBI_FMT:
477 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
478 return v4l2_ctrl_query_fill_std(qctrl);
479 return cx2341x_ctrl_query_fill(qctrl,
480 V4L2_MPEG_STREAM_VBI_FMT_NONE,
481 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
482 V4L2_MPEG_STREAM_VBI_FMT_NONE);
484 /* CX23415/6 specific */
485 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
486 return cx2341x_ctrl_query_fill(qctrl,
487 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
488 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
489 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
491 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
492 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
493 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
494 if (params->video_spatial_filter_mode ==
495 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
496 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
499 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
500 cx2341x_ctrl_query_fill(qctrl,
501 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
502 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
504 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
505 if (params->video_spatial_filter_mode ==
506 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
507 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
510 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
511 cx2341x_ctrl_query_fill(qctrl,
512 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
513 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
515 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
516 if (params->video_spatial_filter_mode ==
517 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
518 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
521 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
522 return cx2341x_ctrl_query_fill(qctrl,
523 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
524 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
525 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
527 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
528 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
529 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
530 if (params->video_temporal_filter_mode ==
531 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
532 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
535 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
536 return cx2341x_ctrl_query_fill(qctrl,
537 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
538 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
539 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
541 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_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 ==
545 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
546 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
549 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
550 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
551 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
552 if (params->video_median_filter_type ==
553 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
554 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
557 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
558 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
559 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
560 if (params->video_median_filter_type ==
561 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
562 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
565 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
566 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
567 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
568 if (params->video_median_filter_type ==
569 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
570 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
573 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
574 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
577 return v4l2_ctrl_query_fill_std(qctrl);
581 EXPORT_SYMBOL(cx2341x_ctrl_query);
583 const char **cx2341x_ctrl_get_menu(u32 id)
585 static const char *mpeg_stream_type[] = {
586 "MPEG-2 Program Stream",
588 "MPEG-1 System Stream",
589 "MPEG-2 DVD-compatible Stream",
590 "MPEG-1 VCD-compatible Stream",
591 "MPEG-2 SVCD-compatible Stream",
595 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
601 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
606 "2D Symmetric non-separable",
610 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
616 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
622 static const char *cx2341x_video_median_filter_type_menu[] = {
626 "Horizontal/Vertical",
632 case V4L2_CID_MPEG_STREAM_TYPE:
633 return mpeg_stream_type;
634 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
635 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
637 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
638 return cx2341x_video_spatial_filter_mode_menu;
639 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
640 return cx2341x_video_luma_spatial_filter_type_menu;
641 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
642 return cx2341x_video_chroma_spatial_filter_type_menu;
643 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
644 return cx2341x_video_temporal_filter_mode_menu;
645 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
646 return cx2341x_video_median_filter_type_menu;
648 return v4l2_ctrl_get_menu(id);
651 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
653 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
655 params->audio_properties = (params->audio_sampling_freq << 0) |
656 ((3 - params->audio_encoding) << 2) |
657 ((1 + params->audio_l2_bitrate) << 4) |
658 (params->audio_mode << 8) |
659 (params->audio_mode_extension << 10) |
660 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
661 ? 3 : params->audio_emphasis) << 12) |
662 (params->audio_crc << 14);
665 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
666 struct v4l2_ext_controls *ctrls, unsigned int cmd)
671 if (cmd == VIDIOC_G_EXT_CTRLS) {
672 for (i = 0; i < ctrls->count; i++) {
673 struct v4l2_ext_control *ctrl = ctrls->controls + i;
675 err = cx2341x_get_ctrl(params, ctrl);
677 ctrls->error_idx = i;
683 for (i = 0; i < ctrls->count; i++) {
684 struct v4l2_ext_control *ctrl = ctrls->controls + i;
685 struct v4l2_queryctrl qctrl;
686 const char **menu_items = NULL;
689 err = cx2341x_ctrl_query(params, &qctrl);
692 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
693 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
694 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
697 err = cx2341x_set_ctrl(params, busy, ctrl);
702 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
703 params->video_bitrate_peak < params->video_bitrate) {
705 ctrls->error_idx = ctrls->count;
708 ctrls->error_idx = i;
710 cx2341x_calc_audio_properties(params);
713 EXPORT_SYMBOL(cx2341x_ext_ctrls);
715 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
717 static struct cx2341x_mpeg_params default_params = {
720 .port = CX2341X_PORT_MEMORY,
726 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
727 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
728 .stream_insert_nav_packets = 0,
731 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
732 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
733 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
734 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
735 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
736 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
737 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
741 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
742 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
744 .video_gop_size = 12,
745 .video_gop_closure = 1,
746 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
747 .video_bitrate = 6000000,
748 .video_bitrate_peak = 8000000,
749 .video_temporal_decimation = 0,
751 .video_mute_yuv = 0x008080, /* YCbCr value for black */
753 /* encoding filters */
754 .video_spatial_filter_mode =
755 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
756 .video_spatial_filter = 0,
757 .video_luma_spatial_filter_type =
758 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
759 .video_chroma_spatial_filter_type =
760 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
761 .video_temporal_filter_mode =
762 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
763 .video_temporal_filter = 8,
764 .video_median_filter_type =
765 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
766 .video_luma_median_filter_top = 255,
767 .video_luma_median_filter_bottom = 0,
768 .video_chroma_median_filter_top = 255,
769 .video_chroma_median_filter_bottom = 0,
773 cx2341x_calc_audio_properties(p);
775 EXPORT_SYMBOL(cx2341x_fill_defaults);
777 static int cx2341x_api(void *priv, cx2341x_mbox_func func,
778 u32 cmd, int args, ...)
780 u32 data[CX2341X_MBOX_MAX_DATA];
784 va_start(vargs, args);
786 for (i = 0; i < args; i++)
787 data[i] = va_arg(vargs, int);
789 return func(priv, cmd, args, 0, data);
792 #define NEQ(field) (old->field != new->field)
794 int cx2341x_update(void *priv, cx2341x_mbox_func func,
795 const struct cx2341x_mpeg_params *old,
796 const struct cx2341x_mpeg_params *new)
798 static int mpeg_stream_type[] = {
808 int force = (old == NULL);
809 u16 temporal = new->video_temporal_filter;
811 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
813 if (force || NEQ(is_50hz)) {
814 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
819 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
823 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
827 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
832 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
833 /* Adjust temporal filter if necessary. The problem with the
834 temporal filter is that it works well with full resolution
835 capturing, but not when the capture window is scaled (the
836 filter introduces a ghosting effect). So if the capture
837 window is scaled, then force the filter to 0.
839 For full resolution the filter really improves the video
840 quality, especially if the original video quality is
845 if (force || NEQ(stream_type)) {
846 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
847 mpeg_stream_type[new->stream_type]);
850 if (force || NEQ(video_aspect)) {
851 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
852 1 + new->video_aspect);
855 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
856 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
857 new->video_gop_size, new->video_b_frames + 1);
860 if (force || NEQ(video_gop_closure)) {
861 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
862 new->video_gop_closure);
865 if (force || NEQ(audio_properties)) {
866 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
867 1, new->audio_properties);
870 if (force || NEQ(audio_mute)) {
871 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
875 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
876 NEQ(video_bitrate_peak)) {
877 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
878 new->video_bitrate_mode, new->video_bitrate,
879 new->video_bitrate_peak / 400, 0, 0);
882 if (force || NEQ(video_spatial_filter_mode) ||
883 NEQ(video_temporal_filter_mode) ||
884 NEQ(video_median_filter_type)) {
885 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
886 2, new->video_spatial_filter_mode |
887 (new->video_temporal_filter_mode << 1),
888 new->video_median_filter_type);
891 if (force || NEQ(video_luma_median_filter_bottom) ||
892 NEQ(video_luma_median_filter_top) ||
893 NEQ(video_chroma_median_filter_bottom) ||
894 NEQ(video_chroma_median_filter_top)) {
895 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
896 new->video_luma_median_filter_bottom,
897 new->video_luma_median_filter_top,
898 new->video_chroma_median_filter_bottom,
899 new->video_chroma_median_filter_top);
902 if (force || NEQ(video_luma_spatial_filter_type) ||
903 NEQ(video_chroma_spatial_filter_type)) {
904 err = cx2341x_api(priv, func,
905 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
906 2, new->video_luma_spatial_filter_type,
907 new->video_chroma_spatial_filter_type);
910 if (force || NEQ(video_spatial_filter) ||
911 old->video_temporal_filter != temporal) {
912 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
913 2, new->video_spatial_filter, temporal);
916 if (force || NEQ(video_temporal_decimation)) {
917 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
918 1, new->video_temporal_decimation);
921 if (force || NEQ(video_mute) ||
922 (new->video_mute && NEQ(video_mute_yuv))) {
923 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
924 new->video_mute | (new->video_mute_yuv << 8));
927 if (force || NEQ(stream_insert_nav_packets)) {
928 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
929 7, new->stream_insert_nav_packets);
934 EXPORT_SYMBOL(cx2341x_update);
936 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
938 const char **menu = cx2341x_ctrl_get_menu(id);
939 struct v4l2_ext_control ctrl;
944 if (cx2341x_get_ctrl(p, &ctrl))
946 while (ctrl.value-- && *menu) menu++;
955 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
957 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
958 int temporal = p->video_temporal_filter;
961 printk(KERN_INFO "%s: Stream: %s",
963 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
964 if (p->stream_insert_nav_packets)
965 printk(" (with navigation packets)");
967 printk(KERN_INFO "%s: VBI Format: %s\n",
969 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
972 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
974 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
975 p->is_50hz ? 25 : 30,
976 (p->video_mute) ? " (muted)" : "");
977 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
979 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
980 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
981 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
983 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
984 printk(", Peak %d", p->video_bitrate_peak);
987 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
989 p->video_gop_size, p->video_b_frames,
990 p->video_gop_closure ? "" : "No ");
991 if (p->video_temporal_decimation)
992 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
993 prefix, p->video_temporal_decimation);
996 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
998 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
999 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1000 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1001 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1002 p->audio_mute ? " (muted)" : "");
1003 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1004 printk(", %s", cx2341x_menu_item(p,
1005 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1006 printk(", %s, %s\n",
1007 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1008 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1010 /* Encoding filters */
1011 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1013 cx2341x_menu_item(p,
1014 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1015 cx2341x_menu_item(p,
1016 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1017 cx2341x_menu_item(p,
1018 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1019 p->video_spatial_filter);
1021 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1024 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1026 cx2341x_menu_item(p,
1027 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1030 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
1032 cx2341x_menu_item(p,
1033 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1034 p->video_luma_median_filter_bottom,
1035 p->video_luma_median_filter_top,
1036 p->video_chroma_median_filter_bottom,
1037 p->video_chroma_median_filter_top);
1039 EXPORT_SYMBOL(cx2341x_log_status);