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);
80 static const struct cx2341x_mpeg_params default_params = {
83 .port = CX2341X_PORT_MEMORY,
89 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
90 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
91 .stream_insert_nav_packets = 0,
94 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
95 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
96 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
97 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
98 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
99 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
100 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
104 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
105 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
107 .video_gop_size = 12,
108 .video_gop_closure = 1,
109 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
110 .video_bitrate = 6000000,
111 .video_bitrate_peak = 8000000,
112 .video_temporal_decimation = 0,
114 .video_mute_yuv = 0x008080, /* YCbCr value for black */
116 /* encoding filters */
117 .video_spatial_filter_mode =
118 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
119 .video_spatial_filter = 0,
120 .video_luma_spatial_filter_type =
121 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
122 .video_chroma_spatial_filter_type =
123 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
124 .video_temporal_filter_mode =
125 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
126 .video_temporal_filter = 8,
127 .video_median_filter_type =
128 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
129 .video_luma_median_filter_top = 255,
130 .video_luma_median_filter_bottom = 0,
131 .video_chroma_median_filter_top = 255,
132 .video_chroma_median_filter_bottom = 0,
136 /* Map the control ID to the correct field in the cx2341x_mpeg_params
137 struct. Return -EINVAL if the ID is unknown, else return 0. */
138 static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
139 struct v4l2_ext_control *ctrl)
142 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
143 ctrl->value = params->audio_sampling_freq;
145 case V4L2_CID_MPEG_AUDIO_ENCODING:
146 ctrl->value = params->audio_encoding;
148 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
149 ctrl->value = params->audio_l2_bitrate;
151 case V4L2_CID_MPEG_AUDIO_MODE:
152 ctrl->value = params->audio_mode;
154 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
155 ctrl->value = params->audio_mode_extension;
157 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
158 ctrl->value = params->audio_emphasis;
160 case V4L2_CID_MPEG_AUDIO_CRC:
161 ctrl->value = params->audio_crc;
163 case V4L2_CID_MPEG_AUDIO_MUTE:
164 ctrl->value = params->audio_mute;
166 case V4L2_CID_MPEG_VIDEO_ENCODING:
167 ctrl->value = params->video_encoding;
169 case V4L2_CID_MPEG_VIDEO_ASPECT:
170 ctrl->value = params->video_aspect;
172 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
173 ctrl->value = params->video_b_frames;
175 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
176 ctrl->value = params->video_gop_size;
178 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
179 ctrl->value = params->video_gop_closure;
181 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
182 ctrl->value = params->video_bitrate_mode;
184 case V4L2_CID_MPEG_VIDEO_BITRATE:
185 ctrl->value = params->video_bitrate;
187 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
188 ctrl->value = params->video_bitrate_peak;
190 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
191 ctrl->value = params->video_temporal_decimation;
193 case V4L2_CID_MPEG_VIDEO_MUTE:
194 ctrl->value = params->video_mute;
196 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
197 ctrl->value = params->video_mute_yuv;
199 case V4L2_CID_MPEG_STREAM_TYPE:
200 ctrl->value = params->stream_type;
202 case V4L2_CID_MPEG_STREAM_VBI_FMT:
203 ctrl->value = params->stream_vbi_fmt;
205 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
206 ctrl->value = params->video_spatial_filter_mode;
208 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
209 ctrl->value = params->video_spatial_filter;
211 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
212 ctrl->value = params->video_luma_spatial_filter_type;
214 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
215 ctrl->value = params->video_chroma_spatial_filter_type;
217 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
218 ctrl->value = params->video_temporal_filter_mode;
220 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
221 ctrl->value = params->video_temporal_filter;
223 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
224 ctrl->value = params->video_median_filter_type;
226 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
227 ctrl->value = params->video_luma_median_filter_top;
229 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
230 ctrl->value = params->video_luma_median_filter_bottom;
232 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
233 ctrl->value = params->video_chroma_median_filter_top;
235 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
236 ctrl->value = params->video_chroma_median_filter_bottom;
238 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
239 ctrl->value = params->stream_insert_nav_packets;
247 /* Map the control ID to the correct field in the cx2341x_mpeg_params
248 struct. Return -EINVAL if the ID is unknown, else return 0. */
249 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
250 struct v4l2_ext_control *ctrl)
253 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
256 params->audio_sampling_freq = ctrl->value;
258 case V4L2_CID_MPEG_AUDIO_ENCODING:
259 params->audio_encoding = ctrl->value;
261 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
264 params->audio_l2_bitrate = ctrl->value;
266 case V4L2_CID_MPEG_AUDIO_MODE:
267 params->audio_mode = ctrl->value;
269 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
270 params->audio_mode_extension = ctrl->value;
272 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
273 params->audio_emphasis = ctrl->value;
275 case V4L2_CID_MPEG_AUDIO_CRC:
276 params->audio_crc = ctrl->value;
278 case V4L2_CID_MPEG_AUDIO_MUTE:
279 params->audio_mute = ctrl->value;
281 case V4L2_CID_MPEG_VIDEO_ASPECT:
282 params->video_aspect = ctrl->value;
284 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
285 int b = ctrl->value + 1;
286 int gop = params->video_gop_size;
287 params->video_b_frames = ctrl->value;
288 params->video_gop_size = b * ((gop + b - 1) / b);
289 /* Max GOP size = 34 */
290 while (params->video_gop_size > 34)
291 params->video_gop_size -= b;
294 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
295 int b = params->video_b_frames + 1;
296 int gop = ctrl->value;
297 params->video_gop_size = b * ((gop + b - 1) / b);
298 /* Max GOP size = 34 */
299 while (params->video_gop_size > 34)
300 params->video_gop_size -= b;
301 ctrl->value = params->video_gop_size;
304 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
305 params->video_gop_closure = ctrl->value;
307 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
310 /* MPEG-1 only allows CBR */
311 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
312 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
314 params->video_bitrate_mode = ctrl->value;
316 case V4L2_CID_MPEG_VIDEO_BITRATE:
319 params->video_bitrate = ctrl->value;
321 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
324 params->video_bitrate_peak = ctrl->value;
326 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
327 params->video_temporal_decimation = ctrl->value;
329 case V4L2_CID_MPEG_VIDEO_MUTE:
330 params->video_mute = (ctrl->value != 0);
332 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
333 params->video_mute_yuv = ctrl->value;
335 case V4L2_CID_MPEG_STREAM_TYPE:
338 params->stream_type = ctrl->value;
339 params->video_encoding =
340 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
341 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
342 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
343 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
344 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
345 /* MPEG-1 implies CBR */
346 params->video_bitrate_mode =
347 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
349 case V4L2_CID_MPEG_STREAM_VBI_FMT:
350 params->stream_vbi_fmt = ctrl->value;
352 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
353 params->video_spatial_filter_mode = ctrl->value;
355 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
356 params->video_spatial_filter = ctrl->value;
358 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
359 params->video_luma_spatial_filter_type = ctrl->value;
361 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
362 params->video_chroma_spatial_filter_type = ctrl->value;
364 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
365 params->video_temporal_filter_mode = ctrl->value;
367 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
368 params->video_temporal_filter = ctrl->value;
370 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
371 params->video_median_filter_type = ctrl->value;
373 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
374 params->video_luma_median_filter_top = ctrl->value;
376 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
377 params->video_luma_median_filter_bottom = ctrl->value;
379 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
380 params->video_chroma_median_filter_top = ctrl->value;
382 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
383 params->video_chroma_median_filter_bottom = ctrl->value;
385 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
386 params->stream_insert_nav_packets = ctrl->value;
394 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
395 s32 min, s32 max, s32 step, s32 def)
402 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
403 name = "Spatial Filter Mode";
405 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
406 name = "Spatial Filter";
408 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
409 name = "Spatial Luma Filter Type";
411 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
412 name = "Spatial Chroma Filter Type";
414 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
415 name = "Temporal Filter Mode";
417 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
418 name = "Temporal Filter";
420 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
421 name = "Median Filter Type";
423 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
424 name = "Median Luma Filter Maximum";
426 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
427 name = "Median Luma Filter Minimum";
429 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
430 name = "Median Chroma Filter Maximum";
432 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
433 name = "Median Chroma Filter Minimum";
435 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
436 name = "Insert Navigation Packets";
440 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
443 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
444 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
445 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
446 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
447 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
448 qctrl->type = V4L2_CTRL_TYPE_MENU;
452 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
453 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
459 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
463 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
464 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
465 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
466 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
469 qctrl->minimum = min;
470 qctrl->maximum = max;
472 qctrl->default_value = def;
473 qctrl->reserved[0] = qctrl->reserved[1] = 0;
474 snprintf(qctrl->name, sizeof(qctrl->name), name);
478 int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
479 struct v4l2_queryctrl *qctrl)
484 case V4L2_CID_MPEG_AUDIO_ENCODING:
485 return v4l2_ctrl_query_fill(qctrl,
486 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
487 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
488 default_params.audio_encoding);
490 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
491 return v4l2_ctrl_query_fill(qctrl,
492 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
493 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
494 default_params.audio_l2_bitrate);
496 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
497 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
500 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
501 err = v4l2_ctrl_query_fill_std(qctrl);
503 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
504 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
507 case V4L2_CID_MPEG_VIDEO_ENCODING:
508 /* this setting is read-only for the cx2341x since the
509 V4L2_CID_MPEG_STREAM_TYPE really determines the
511 err = v4l2_ctrl_query_fill(qctrl,
512 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
513 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
514 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
516 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
519 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
520 err = v4l2_ctrl_query_fill_std(qctrl);
522 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
523 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
526 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
527 err = v4l2_ctrl_query_fill_std(qctrl);
529 params->video_bitrate_mode ==
530 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
531 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
534 case V4L2_CID_MPEG_STREAM_VBI_FMT:
535 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
536 return v4l2_ctrl_query_fill_std(qctrl);
537 return cx2341x_ctrl_query_fill(qctrl,
538 V4L2_MPEG_STREAM_VBI_FMT_NONE,
539 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
540 default_params.stream_vbi_fmt);
542 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
543 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
544 params->is_50hz ? 12 : 15);
546 /* CX23415/6 specific */
547 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
548 return cx2341x_ctrl_query_fill(qctrl,
549 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
550 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
551 default_params.video_spatial_filter_mode);
553 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
554 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
555 default_params.video_spatial_filter);
556 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
557 if (params->video_spatial_filter_mode ==
558 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
559 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
562 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
563 cx2341x_ctrl_query_fill(qctrl,
564 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
565 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
567 default_params.video_luma_spatial_filter_type);
568 if (params->video_spatial_filter_mode ==
569 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
570 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
573 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
574 cx2341x_ctrl_query_fill(qctrl,
575 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
576 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
578 default_params.video_chroma_spatial_filter_type);
579 if (params->video_spatial_filter_mode ==
580 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
581 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
584 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
585 return cx2341x_ctrl_query_fill(qctrl,
586 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
587 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
588 default_params.video_temporal_filter_mode);
590 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
591 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
592 default_params.video_temporal_filter);
593 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
594 if (params->video_temporal_filter_mode ==
595 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
596 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
599 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
600 return cx2341x_ctrl_query_fill(qctrl,
601 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
602 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
603 default_params.video_median_filter_type);
605 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
606 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
607 default_params.video_luma_median_filter_top);
608 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
609 if (params->video_median_filter_type ==
610 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
611 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
614 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
615 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
616 default_params.video_luma_median_filter_bottom);
617 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
618 if (params->video_median_filter_type ==
619 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
620 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
623 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
624 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
625 default_params.video_chroma_median_filter_top);
626 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
627 if (params->video_median_filter_type ==
628 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
629 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
632 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
633 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
634 default_params.video_chroma_median_filter_bottom);
635 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
636 if (params->video_median_filter_type ==
637 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
638 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
641 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
642 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
643 default_params.stream_insert_nav_packets);
646 return v4l2_ctrl_query_fill_std(qctrl);
650 EXPORT_SYMBOL(cx2341x_ctrl_query);
652 const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
654 static const char *mpeg_stream_type_without_ts[] = {
655 "MPEG-2 Program Stream",
657 "MPEG-1 System Stream",
658 "MPEG-2 DVD-compatible Stream",
659 "MPEG-1 VCD-compatible Stream",
660 "MPEG-2 SVCD-compatible Stream",
664 static const char *mpeg_stream_type_with_ts[] = {
665 "MPEG-2 Program Stream",
666 "MPEG-2 Transport Stream",
667 "MPEG-1 System Stream",
668 "MPEG-2 DVD-compatible Stream",
669 "MPEG-1 VCD-compatible Stream",
670 "MPEG-2 SVCD-compatible Stream",
674 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
680 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
685 "2D Symmetric non-separable",
689 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
695 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
701 static const char *cx2341x_video_median_filter_type_menu[] = {
705 "Horizontal/Vertical",
711 case V4L2_CID_MPEG_STREAM_TYPE:
712 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
713 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
714 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
715 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
717 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
718 return cx2341x_video_spatial_filter_mode_menu;
719 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
720 return cx2341x_video_luma_spatial_filter_type_menu;
721 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
722 return cx2341x_video_chroma_spatial_filter_type_menu;
723 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
724 return cx2341x_video_temporal_filter_mode_menu;
725 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
726 return cx2341x_video_median_filter_type_menu;
728 return v4l2_ctrl_get_menu(id);
731 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
733 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
735 params->audio_properties = (params->audio_sampling_freq << 0) |
736 ((3 - params->audio_encoding) << 2) |
737 ((1 + params->audio_l2_bitrate) << 4) |
738 (params->audio_mode << 8) |
739 (params->audio_mode_extension << 10) |
740 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
741 ? 3 : params->audio_emphasis) << 12) |
742 (params->audio_crc << 14);
745 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
746 struct v4l2_ext_controls *ctrls, unsigned int cmd)
751 if (cmd == VIDIOC_G_EXT_CTRLS) {
752 for (i = 0; i < ctrls->count; i++) {
753 struct v4l2_ext_control *ctrl = ctrls->controls + i;
755 err = cx2341x_get_ctrl(params, ctrl);
757 ctrls->error_idx = i;
763 for (i = 0; i < ctrls->count; i++) {
764 struct v4l2_ext_control *ctrl = ctrls->controls + i;
765 struct v4l2_queryctrl qctrl;
766 const char **menu_items = NULL;
769 err = cx2341x_ctrl_query(params, &qctrl);
772 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
773 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
774 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
777 err = cx2341x_set_ctrl(params, busy, ctrl);
782 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
783 params->video_bitrate_peak < params->video_bitrate) {
785 ctrls->error_idx = ctrls->count;
788 ctrls->error_idx = i;
790 cx2341x_calc_audio_properties(params);
793 EXPORT_SYMBOL(cx2341x_ext_ctrls);
795 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
798 cx2341x_calc_audio_properties(p);
800 EXPORT_SYMBOL(cx2341x_fill_defaults);
802 static int cx2341x_api(void *priv, cx2341x_mbox_func func,
803 u32 cmd, int args, ...)
805 u32 data[CX2341X_MBOX_MAX_DATA];
809 va_start(vargs, args);
811 for (i = 0; i < args; i++)
812 data[i] = va_arg(vargs, int);
814 return func(priv, cmd, args, 0, data);
817 #define NEQ(field) (old->field != new->field)
819 int cx2341x_update(void *priv, cx2341x_mbox_func func,
820 const struct cx2341x_mpeg_params *old,
821 const struct cx2341x_mpeg_params *new)
823 static int mpeg_stream_type[] = {
833 int force = (old == NULL);
834 u16 temporal = new->video_temporal_filter;
836 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
838 if (force || NEQ(is_50hz)) {
839 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
844 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
848 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
852 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
857 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
858 /* Adjust temporal filter if necessary. The problem with the
859 temporal filter is that it works well with full resolution
860 capturing, but not when the capture window is scaled (the
861 filter introduces a ghosting effect). So if the capture
862 window is scaled, then force the filter to 0.
864 For full resolution the filter really improves the video
865 quality, especially if the original video quality is
870 if (force || NEQ(stream_type)) {
871 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
872 mpeg_stream_type[new->stream_type]);
875 if (force || NEQ(video_aspect)) {
876 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
877 1 + new->video_aspect);
880 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
881 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
882 new->video_gop_size, new->video_b_frames + 1);
885 if (force || NEQ(video_gop_closure)) {
886 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
887 new->video_gop_closure);
890 if (force || NEQ(audio_properties)) {
891 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
892 1, new->audio_properties);
895 if (force || NEQ(audio_mute)) {
896 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
900 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
901 NEQ(video_bitrate_peak)) {
902 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
903 new->video_bitrate_mode, new->video_bitrate,
904 new->video_bitrate_peak / 400, 0, 0);
907 if (force || NEQ(video_spatial_filter_mode) ||
908 NEQ(video_temporal_filter_mode) ||
909 NEQ(video_median_filter_type)) {
910 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
911 2, new->video_spatial_filter_mode |
912 (new->video_temporal_filter_mode << 1),
913 new->video_median_filter_type);
916 if (force || NEQ(video_luma_median_filter_bottom) ||
917 NEQ(video_luma_median_filter_top) ||
918 NEQ(video_chroma_median_filter_bottom) ||
919 NEQ(video_chroma_median_filter_top)) {
920 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
921 new->video_luma_median_filter_bottom,
922 new->video_luma_median_filter_top,
923 new->video_chroma_median_filter_bottom,
924 new->video_chroma_median_filter_top);
927 if (force || NEQ(video_luma_spatial_filter_type) ||
928 NEQ(video_chroma_spatial_filter_type)) {
929 err = cx2341x_api(priv, func,
930 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
931 2, new->video_luma_spatial_filter_type,
932 new->video_chroma_spatial_filter_type);
935 if (force || NEQ(video_spatial_filter) ||
936 old->video_temporal_filter != temporal) {
937 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
938 2, new->video_spatial_filter, temporal);
941 if (force || NEQ(video_temporal_decimation)) {
942 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
943 1, new->video_temporal_decimation);
946 if (force || NEQ(video_mute) ||
947 (new->video_mute && NEQ(video_mute_yuv))) {
948 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
949 new->video_mute | (new->video_mute_yuv << 8));
952 if (force || NEQ(stream_insert_nav_packets)) {
953 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
954 7, new->stream_insert_nav_packets);
959 EXPORT_SYMBOL(cx2341x_update);
961 static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
963 const char **menu = cx2341x_ctrl_get_menu(p, id);
964 struct v4l2_ext_control ctrl;
969 if (cx2341x_get_ctrl(p, &ctrl))
971 while (ctrl.value-- && *menu) menu++;
980 void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
982 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
983 int temporal = p->video_temporal_filter;
986 printk(KERN_INFO "%s: Stream: %s",
988 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
989 if (p->stream_insert_nav_packets)
990 printk(" (with navigation packets)");
992 printk(KERN_INFO "%s: VBI Format: %s\n",
994 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
997 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
999 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1000 p->is_50hz ? 25 : 30,
1001 (p->video_mute) ? " (muted)" : "");
1002 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
1004 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1005 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1006 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1008 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1009 printk(", Peak %d", p->video_bitrate_peak);
1012 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
1014 p->video_gop_size, p->video_b_frames,
1015 p->video_gop_closure ? "" : "No ");
1016 if (p->video_temporal_decimation)
1017 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1018 prefix, p->video_temporal_decimation);
1021 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
1023 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1024 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1025 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1026 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1027 p->audio_mute ? " (muted)" : "");
1028 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1029 printk(", %s", cx2341x_menu_item(p,
1030 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1031 printk(", %s, %s\n",
1032 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1033 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1035 /* Encoding filters */
1036 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1038 cx2341x_menu_item(p,
1039 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1040 cx2341x_menu_item(p,
1041 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1042 cx2341x_menu_item(p,
1043 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1044 p->video_spatial_filter);
1046 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1049 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1051 cx2341x_menu_item(p,
1052 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1055 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
1057 cx2341x_menu_item(p,
1058 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1059 p->video_luma_median_filter_bottom,
1060 p->video_luma_median_filter_top,
1061 p->video_chroma_median_filter_bottom,
1062 p->video_chroma_median_filter_top);
1064 EXPORT_SYMBOL(cx2341x_log_status);