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/moduleparam.h>
24 #include <linux/errno.h>
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/types.h>
28 #include <linux/videodev2.h>
29 #include <linux/i2c.h>
31 #include <media/tuner.h>
32 #include <media/cx2341x.h>
33 #include <media/v4l2-common.h>
35 MODULE_DESCRIPTION("cx23415/6 driver");
36 MODULE_AUTHOR("Hans Verkuil");
37 MODULE_LICENSE("GPL");
40 module_param(debug, int, 0644);
41 MODULE_PARM_DESC(debug, "Debug level (0-1)");
43 const u32 cx2341x_mpeg_ctrls[] = {
45 V4L2_CID_MPEG_STREAM_TYPE,
46 V4L2_CID_MPEG_STREAM_VBI_FMT,
47 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
48 V4L2_CID_MPEG_AUDIO_ENCODING,
49 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
50 V4L2_CID_MPEG_AUDIO_MODE,
51 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
52 V4L2_CID_MPEG_AUDIO_EMPHASIS,
53 V4L2_CID_MPEG_AUDIO_CRC,
54 V4L2_CID_MPEG_VIDEO_ENCODING,
55 V4L2_CID_MPEG_VIDEO_ASPECT,
56 V4L2_CID_MPEG_VIDEO_B_FRAMES,
57 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
58 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
59 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
60 V4L2_CID_MPEG_VIDEO_BITRATE,
61 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
62 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
63 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
64 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
65 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
66 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
68 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
69 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
70 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
71 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
72 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
73 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
78 /* Map the control ID to the correct field in the cx2341x_mpeg_params
79 struct. Return -EINVAL if the ID is unknown, else return 0. */
80 static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
81 struct v4l2_ext_control *ctrl)
84 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
85 ctrl->value = params->audio_sampling_freq;
87 case V4L2_CID_MPEG_AUDIO_ENCODING:
88 ctrl->value = params->audio_encoding;
90 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
91 ctrl->value = params->audio_l2_bitrate;
93 case V4L2_CID_MPEG_AUDIO_MODE:
94 ctrl->value = params->audio_mode;
96 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
97 ctrl->value = params->audio_mode_extension;
99 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
100 ctrl->value = params->audio_emphasis;
102 case V4L2_CID_MPEG_AUDIO_CRC:
103 ctrl->value = params->audio_crc;
105 case V4L2_CID_MPEG_VIDEO_ENCODING:
106 ctrl->value = params->video_encoding;
108 case V4L2_CID_MPEG_VIDEO_ASPECT:
109 ctrl->value = params->video_aspect;
111 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
112 ctrl->value = params->video_b_frames;
114 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
115 ctrl->value = params->video_gop_size;
117 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
118 ctrl->value = params->video_gop_closure;
120 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
121 ctrl->value = params->video_bitrate_mode;
123 case V4L2_CID_MPEG_VIDEO_BITRATE:
124 ctrl->value = params->video_bitrate;
126 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
127 ctrl->value = params->video_bitrate_peak;
129 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
130 ctrl->value = params->video_temporal_decimation;
132 case V4L2_CID_MPEG_STREAM_TYPE:
133 ctrl->value = params->stream_type;
135 case V4L2_CID_MPEG_STREAM_VBI_FMT:
136 ctrl->value = params->stream_vbi_fmt;
138 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
139 ctrl->value = params->video_spatial_filter_mode;
141 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
142 ctrl->value = params->video_spatial_filter;
144 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
145 ctrl->value = params->video_luma_spatial_filter_type;
147 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
148 ctrl->value = params->video_chroma_spatial_filter_type;
150 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
151 ctrl->value = params->video_temporal_filter_mode;
153 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
154 ctrl->value = params->video_temporal_filter;
156 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
157 ctrl->value = params->video_median_filter_type;
159 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
160 ctrl->value = params->video_luma_median_filter_top;
162 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
163 ctrl->value = params->video_luma_median_filter_bottom;
165 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
166 ctrl->value = params->video_chroma_median_filter_top;
168 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
169 ctrl->value = params->video_chroma_median_filter_bottom;
177 /* Map the control ID to the correct field in the cx2341x_mpeg_params
178 struct. Return -EINVAL if the ID is unknown, else return 0. */
179 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
180 struct v4l2_ext_control *ctrl)
183 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
184 params->audio_sampling_freq = ctrl->value;
186 case V4L2_CID_MPEG_AUDIO_ENCODING:
187 params->audio_encoding = ctrl->value;
189 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
190 params->audio_l2_bitrate = ctrl->value;
192 case V4L2_CID_MPEG_AUDIO_MODE:
193 params->audio_mode = ctrl->value;
195 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
196 params->audio_mode_extension = ctrl->value;
198 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
199 params->audio_emphasis = ctrl->value;
201 case V4L2_CID_MPEG_AUDIO_CRC:
202 params->audio_crc = ctrl->value;
204 case V4L2_CID_MPEG_VIDEO_ASPECT:
205 params->video_aspect = ctrl->value;
207 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
208 int b = ctrl->value + 1;
209 int gop = params->video_gop_size;
210 params->video_b_frames = ctrl->value;
211 params->video_gop_size = b * ((gop + b - 1) / b);
212 /* Max GOP size = 34 */
213 while (params->video_gop_size > 34)
214 params->video_gop_size -= b;
217 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
218 int b = params->video_b_frames + 1;
219 int gop = ctrl->value;
220 params->video_gop_size = b * ((gop + b - 1) / b);
221 /* Max GOP size = 34 */
222 while (params->video_gop_size > 34)
223 params->video_gop_size -= b;
224 ctrl->value = params->video_gop_size;
227 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
228 params->video_gop_closure = ctrl->value;
230 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
231 /* MPEG-1 only allows CBR */
232 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
233 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
235 params->video_bitrate_mode = ctrl->value;
237 case V4L2_CID_MPEG_VIDEO_BITRATE:
238 params->video_bitrate = ctrl->value;
240 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
241 params->video_bitrate_peak = ctrl->value;
243 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
244 params->video_temporal_decimation = ctrl->value;
246 case V4L2_CID_MPEG_STREAM_TYPE:
247 params->stream_type = ctrl->value;
248 params->video_encoding =
249 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
250 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
251 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
252 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
253 /* MPEG-1 implies CBR */
254 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
257 case V4L2_CID_MPEG_STREAM_VBI_FMT:
258 params->stream_vbi_fmt = ctrl->value;
260 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
261 params->video_spatial_filter_mode = ctrl->value;
263 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
264 params->video_spatial_filter = ctrl->value;
266 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
267 params->video_luma_spatial_filter_type = ctrl->value;
269 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
270 params->video_chroma_spatial_filter_type = ctrl->value;
272 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
273 params->video_temporal_filter_mode = ctrl->value;
275 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
276 params->video_temporal_filter = ctrl->value;
278 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
279 params->video_median_filter_type = ctrl->value;
281 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
282 params->video_luma_median_filter_top = ctrl->value;
284 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
285 params->video_luma_median_filter_bottom = ctrl->value;
287 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
288 params->video_chroma_median_filter_top = ctrl->value;
290 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
291 params->video_chroma_median_filter_bottom = ctrl->value;
299 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
306 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
307 name = "Spatial Filter Mode";
309 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
310 name = "Spatial Filter";
312 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
313 name = "Spatial Luma Filter Type";
315 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
316 name = "Spatial Chroma Filter Type";
318 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
319 name = "Temporal Filter Mode";
321 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
322 name = "Temporal Filter";
324 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
325 name = "Median Filter Type";
327 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
328 name = "Median Luma Filter Maximum";
330 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
331 name = "Median Luma Filter Minimum";
333 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
334 name = "Median Chroma Filter Maximum";
336 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
337 name = "Median Chroma Filter Minimum";
341 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
344 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
345 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
346 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
347 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
348 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
349 qctrl->type = V4L2_CTRL_TYPE_MENU;
354 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
358 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
359 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
360 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
361 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
364 qctrl->minimum = min;
365 qctrl->maximum = max;
367 qctrl->default_value = def;
368 qctrl->reserved[0] = qctrl->reserved[1] = 0;
369 snprintf(qctrl->name, sizeof(qctrl->name), name);
373 int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
378 case V4L2_CID_MPEG_AUDIO_ENCODING:
379 return v4l2_ctrl_query_fill(qctrl,
380 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
381 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
382 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
384 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
385 return v4l2_ctrl_query_fill(qctrl,
386 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
387 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
388 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
390 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
391 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
394 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
395 err = v4l2_ctrl_query_fill_std(qctrl);
396 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
397 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
400 case V4L2_CID_MPEG_VIDEO_ENCODING:
401 /* this setting is read-only for the cx2341x since the
402 V4L2_CID_MPEG_STREAM_TYPE really determines the
404 err = v4l2_ctrl_query_fill_std(qctrl);
406 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
409 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
410 err = v4l2_ctrl_query_fill_std(qctrl);
411 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
412 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
415 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
416 err = v4l2_ctrl_query_fill_std(qctrl);
417 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
418 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
421 case V4L2_CID_MPEG_STREAM_VBI_FMT:
422 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
423 return v4l2_ctrl_query_fill_std(qctrl);
424 return cx2341x_ctrl_query_fill(qctrl,
425 V4L2_MPEG_STREAM_VBI_FMT_NONE,
426 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
427 V4L2_MPEG_STREAM_VBI_FMT_NONE);
429 /* CX23415/6 specific */
430 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
431 return cx2341x_ctrl_query_fill(qctrl,
432 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
433 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
434 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
436 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
437 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
438 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
439 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
440 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
443 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
444 cx2341x_ctrl_query_fill(qctrl,
445 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
446 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
447 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
448 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
449 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
452 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
453 cx2341x_ctrl_query_fill(qctrl,
454 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
455 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
456 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
457 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
458 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
461 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
462 return cx2341x_ctrl_query_fill(qctrl,
463 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
464 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
465 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
467 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
468 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
469 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
470 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
471 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
474 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
475 return cx2341x_ctrl_query_fill(qctrl,
476 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
477 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
478 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
480 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
481 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
482 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
483 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
484 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
487 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
488 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
489 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
490 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
491 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
494 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
495 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
496 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
497 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
498 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
501 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
502 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
503 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
504 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
505 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
509 return v4l2_ctrl_query_fill_std(qctrl);
514 const char **cx2341x_ctrl_get_menu(u32 id)
516 static const char *mpeg_stream_type[] = {
517 "MPEG-2 Program Stream",
519 "MPEG-1 System Stream",
520 "MPEG-2 DVD-compatible Stream",
521 "MPEG-1 VCD-compatible Stream",
522 "MPEG-2 SVCD-compatible Stream",
526 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
532 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
537 "2D Symmetric non-separable",
541 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
547 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
553 static const char *cx2341x_video_median_filter_type_menu[] = {
557 "Horizontal/Vertical",
563 case V4L2_CID_MPEG_STREAM_TYPE:
564 return mpeg_stream_type;
565 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
566 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
568 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
569 return cx2341x_video_spatial_filter_mode_menu;
570 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
571 return cx2341x_video_luma_spatial_filter_type_menu;
572 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
573 return cx2341x_video_chroma_spatial_filter_type_menu;
574 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
575 return cx2341x_video_temporal_filter_mode_menu;
576 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
577 return cx2341x_video_median_filter_type_menu;
579 return v4l2_ctrl_get_menu(id);
583 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
585 params->audio_properties = (params->audio_sampling_freq << 0) |
586 ((3 - params->audio_encoding) << 2) |
587 ((1 + params->audio_l2_bitrate) << 4) |
588 (params->audio_mode << 8) |
589 (params->audio_mode_extension << 10) |
590 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
592 params->audio_emphasis) << 12) |
593 (params->audio_crc << 14);
596 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
597 struct v4l2_ext_controls *ctrls, unsigned int cmd)
602 if (cmd == VIDIOC_G_EXT_CTRLS) {
603 for (i = 0; i < ctrls->count; i++) {
604 struct v4l2_ext_control *ctrl = ctrls->controls + i;
606 err = cx2341x_get_ctrl(params, ctrl);
608 ctrls->error_idx = i;
614 for (i = 0; i < ctrls->count; i++) {
615 struct v4l2_ext_control *ctrl = ctrls->controls + i;
616 struct v4l2_queryctrl qctrl;
617 const char **menu_items = NULL;
620 err = cx2341x_ctrl_query(params, &qctrl);
623 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
624 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
625 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
628 err = cx2341x_set_ctrl(params, ctrl);
632 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
633 params->video_bitrate_peak < params->video_bitrate) {
635 ctrls->error_idx = ctrls->count;
638 ctrls->error_idx = i;
641 cx2341x_calc_audio_properties(params);
646 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
648 static struct cx2341x_mpeg_params default_params = {
651 .port = CX2341X_PORT_MEMORY,
657 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
658 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
661 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
662 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
663 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
664 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
665 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
666 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
667 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
670 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
671 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
673 .video_gop_size = 12,
674 .video_gop_closure = 1,
675 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
676 .video_bitrate = 6000000,
677 .video_bitrate_peak = 8000000,
678 .video_temporal_decimation = 0,
680 /* encoding filters */
681 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
682 .video_spatial_filter = 0,
683 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
684 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
685 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
686 .video_temporal_filter = 8,
687 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
688 .video_luma_median_filter_top = 255,
689 .video_luma_median_filter_bottom = 0,
690 .video_chroma_median_filter_top = 255,
691 .video_chroma_median_filter_bottom = 0,
695 cx2341x_calc_audio_properties(p);
698 static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
700 u32 data[CX2341X_MBOX_MAX_DATA];
704 va_start(vargs, args);
706 for (i = 0; i < args; i++) {
707 data[i] = va_arg(vargs, int);
710 return func(priv, cmd, args, 0, data);
713 int cx2341x_update(void *priv, cx2341x_mbox_func func,
714 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
716 static int mpeg_stream_type[] = {
726 u16 temporal = new->video_temporal_filter;
728 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
730 if (old == NULL || old->is_50hz != new->is_50hz) {
731 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
735 if (old == NULL || old->width != new->width || old->height != new->height ||
736 old->video_encoding != new->video_encoding) {
740 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
744 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
748 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
749 /* Adjust temporal filter if necessary. The problem with the temporal
750 filter is that it works well with full resolution capturing, but
751 not when the capture window is scaled (the filter introduces
752 a ghosting effect). So if the capture window is scaled, then
753 force the filter to 0.
755 For full resolution the filter really improves the video
756 quality, especially if the original video quality is suboptimal. */
760 if (old == NULL || old->stream_type != new->stream_type) {
761 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
764 if (old == NULL || old->video_aspect != new->video_aspect) {
765 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
768 if (old == NULL || old->video_b_frames != new->video_b_frames ||
769 old->video_gop_size != new->video_gop_size) {
770 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
771 new->video_gop_size, new->video_b_frames + 1);
774 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
775 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
778 if (old == NULL || old->audio_properties != new->audio_properties) {
779 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
782 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
783 old->video_bitrate != new->video_bitrate ||
784 old->video_bitrate_peak != new->video_bitrate_peak) {
785 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
786 new->video_bitrate_mode, new->video_bitrate,
787 new->video_bitrate_peak / 400, 0, 0);
790 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
791 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
792 old->video_median_filter_type != new->video_median_filter_type) {
793 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
794 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
795 new->video_median_filter_type);
799 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
800 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
801 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
802 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
803 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
804 new->video_luma_median_filter_bottom,
805 new->video_luma_median_filter_top,
806 new->video_chroma_median_filter_bottom,
807 new->video_chroma_median_filter_top);
811 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
812 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
813 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
814 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
818 old->video_spatial_filter != new->video_spatial_filter ||
819 old->video_temporal_filter != temporal) {
820 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
821 new->video_spatial_filter, temporal);
824 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
825 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
826 new->video_temporal_decimation);
832 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
834 const char **menu = cx2341x_ctrl_get_menu(id);
835 struct v4l2_ext_control ctrl;
840 if (cx2341x_get_ctrl(p, &ctrl))
842 while (ctrl.value-- && *menu) menu++;
851 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
853 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
854 int temporal = p->video_temporal_filter;
857 printk(KERN_INFO "%s: Stream: %s\n",
859 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
860 printk(KERN_INFO "%s: VBI Format: %s\n",
862 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
865 printk(KERN_INFO "%s: Video: %dx%d, %d fps\n",
867 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
868 p->is_50hz ? 25 : 30);
869 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
871 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
872 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
873 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
875 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
876 printk(", Peak %d", p->video_bitrate_peak);
879 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
881 p->video_gop_size, p->video_b_frames,
882 p->video_gop_closure ? "" : "No ");
883 if (p->video_temporal_decimation) {
884 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
885 prefix, p->video_temporal_decimation);
889 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s",
891 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
892 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
893 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
894 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
895 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
897 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
900 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
901 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
903 /* Encoding filters */
904 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
906 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
907 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
908 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
909 p->video_spatial_filter);
910 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
913 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
915 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
917 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
919 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
920 p->video_luma_median_filter_bottom,
921 p->video_luma_median_filter_top,
922 p->video_chroma_median_filter_bottom,
923 p->video_chroma_median_filter_top);
926 EXPORT_SYMBOL(cx2341x_fill_defaults);
927 EXPORT_SYMBOL(cx2341x_ctrl_query);
928 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
929 EXPORT_SYMBOL(cx2341x_ext_ctrls);
930 EXPORT_SYMBOL(cx2341x_update);
931 EXPORT_SYMBOL(cx2341x_log_status);
932 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);