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_PULLDOWN,
60 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
61 V4L2_CID_MPEG_VIDEO_BITRATE,
62 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
63 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
64 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
65 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
66 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
68 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
70 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
71 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
72 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
73 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
74 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
79 /* Map the control ID to the correct field in the cx2341x_mpeg_params
80 struct. Return -EINVAL if the ID is unknown, else return 0. */
81 static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
82 struct v4l2_ext_control *ctrl)
85 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
86 ctrl->value = params->audio_sampling_freq;
88 case V4L2_CID_MPEG_AUDIO_ENCODING:
89 ctrl->value = params->audio_encoding;
91 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
92 ctrl->value = params->audio_l2_bitrate;
94 case V4L2_CID_MPEG_AUDIO_MODE:
95 ctrl->value = params->audio_mode;
97 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
98 ctrl->value = params->audio_mode_extension;
100 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
101 ctrl->value = params->audio_emphasis;
103 case V4L2_CID_MPEG_AUDIO_CRC:
104 ctrl->value = params->audio_crc;
106 case V4L2_CID_MPEG_VIDEO_ENCODING:
107 ctrl->value = params->video_encoding;
109 case V4L2_CID_MPEG_VIDEO_ASPECT:
110 ctrl->value = params->video_aspect;
112 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
113 ctrl->value = params->video_b_frames;
115 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
116 ctrl->value = params->video_gop_size;
118 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
119 ctrl->value = params->video_gop_closure;
121 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
122 ctrl->value = params->video_pulldown;
124 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
125 ctrl->value = params->video_bitrate_mode;
127 case V4L2_CID_MPEG_VIDEO_BITRATE:
128 ctrl->value = params->video_bitrate;
130 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
131 ctrl->value = params->video_bitrate_peak;
133 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
134 ctrl->value = params->video_temporal_decimation;
136 case V4L2_CID_MPEG_STREAM_TYPE:
137 ctrl->value = params->stream_type;
139 case V4L2_CID_MPEG_STREAM_VBI_FMT:
140 ctrl->value = params->stream_vbi_fmt;
142 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
143 ctrl->value = params->video_spatial_filter_mode;
145 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
146 ctrl->value = params->video_spatial_filter;
148 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
149 ctrl->value = params->video_luma_spatial_filter_type;
151 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
152 ctrl->value = params->video_chroma_spatial_filter_type;
154 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
155 ctrl->value = params->video_temporal_filter_mode;
157 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
158 ctrl->value = params->video_temporal_filter;
160 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
161 ctrl->value = params->video_median_filter_type;
163 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
164 ctrl->value = params->video_luma_median_filter_top;
166 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
167 ctrl->value = params->video_luma_median_filter_bottom;
169 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
170 ctrl->value = params->video_chroma_median_filter_top;
172 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
173 ctrl->value = params->video_chroma_median_filter_bottom;
181 /* Map the control ID to the correct field in the cx2341x_mpeg_params
182 struct. Return -EINVAL if the ID is unknown, else return 0. */
183 static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
184 struct v4l2_ext_control *ctrl)
187 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
188 params->audio_sampling_freq = ctrl->value;
190 case V4L2_CID_MPEG_AUDIO_ENCODING:
191 params->audio_encoding = ctrl->value;
193 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
194 params->audio_l2_bitrate = ctrl->value;
196 case V4L2_CID_MPEG_AUDIO_MODE:
197 params->audio_mode = ctrl->value;
199 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
200 params->audio_mode_extension = ctrl->value;
202 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
203 params->audio_emphasis = ctrl->value;
205 case V4L2_CID_MPEG_AUDIO_CRC:
206 params->audio_crc = ctrl->value;
208 case V4L2_CID_MPEG_VIDEO_ASPECT:
209 params->video_aspect = ctrl->value;
211 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
212 int b = ctrl->value + 1;
213 int gop = params->video_gop_size;
214 params->video_b_frames = ctrl->value;
215 params->video_gop_size = b * ((gop + b - 1) / b);
216 /* Max GOP size = 34 */
217 while (params->video_gop_size > 34)
218 params->video_gop_size -= b;
221 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
222 int b = params->video_b_frames + 1;
223 int gop = ctrl->value;
224 params->video_gop_size = b * ((gop + b - 1) / b);
225 /* Max GOP size = 34 */
226 while (params->video_gop_size > 34)
227 params->video_gop_size -= b;
228 ctrl->value = params->video_gop_size;
231 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
232 params->video_gop_closure = ctrl->value;
234 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
235 params->video_pulldown = ctrl->value;
237 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
238 /* MPEG-1 only allows CBR */
239 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
240 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
242 params->video_bitrate_mode = ctrl->value;
244 case V4L2_CID_MPEG_VIDEO_BITRATE:
245 params->video_bitrate = ctrl->value;
247 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
248 params->video_bitrate_peak = ctrl->value;
250 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
251 params->video_temporal_decimation = ctrl->value;
253 case V4L2_CID_MPEG_STREAM_TYPE:
254 params->stream_type = ctrl->value;
255 params->video_encoding =
256 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
257 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
258 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
259 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
260 /* MPEG-1 implies CBR */
261 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
264 case V4L2_CID_MPEG_STREAM_VBI_FMT:
265 params->stream_vbi_fmt = ctrl->value;
267 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
268 params->video_spatial_filter_mode = ctrl->value;
270 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
271 params->video_spatial_filter = ctrl->value;
273 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
274 params->video_luma_spatial_filter_type = ctrl->value;
276 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
277 params->video_chroma_spatial_filter_type = ctrl->value;
279 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
280 params->video_temporal_filter_mode = ctrl->value;
282 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
283 params->video_temporal_filter = ctrl->value;
285 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
286 params->video_median_filter_type = ctrl->value;
288 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
289 params->video_luma_median_filter_top = ctrl->value;
291 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
292 params->video_luma_median_filter_bottom = ctrl->value;
294 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
295 params->video_chroma_median_filter_top = ctrl->value;
297 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
298 params->video_chroma_median_filter_bottom = ctrl->value;
306 static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
313 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
314 name = "Spatial Filter Mode";
316 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
317 name = "Spatial Filter";
319 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
320 name = "Spatial Luma Filter Type";
322 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
323 name = "Spatial Chroma Filter Type";
325 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
326 name = "Temporal Filter Mode";
328 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
329 name = "Temporal Filter";
331 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
332 name = "Median Filter Type";
334 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
335 name = "Median Luma Filter Maximum";
337 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
338 name = "Median Luma Filter Minimum";
340 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
341 name = "Median Chroma Filter Maximum";
343 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
344 name = "Median Chroma Filter Minimum";
348 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
351 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
352 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
353 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
354 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
355 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
356 qctrl->type = V4L2_CTRL_TYPE_MENU;
361 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
365 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
366 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
367 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
368 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
371 qctrl->minimum = min;
372 qctrl->maximum = max;
374 qctrl->default_value = def;
375 qctrl->reserved[0] = qctrl->reserved[1] = 0;
376 snprintf(qctrl->name, sizeof(qctrl->name), name);
380 int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
385 case V4L2_CID_MPEG_AUDIO_ENCODING:
386 return v4l2_ctrl_query_fill(qctrl,
387 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
388 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
389 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
391 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
392 return v4l2_ctrl_query_fill(qctrl,
393 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
394 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
395 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
397 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
398 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
401 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
402 err = v4l2_ctrl_query_fill_std(qctrl);
403 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
404 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
407 case V4L2_CID_MPEG_VIDEO_ENCODING:
408 /* this setting is read-only for the cx2341x since the
409 V4L2_CID_MPEG_STREAM_TYPE really determines the
411 err = v4l2_ctrl_query_fill_std(qctrl);
413 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
416 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
417 err = v4l2_ctrl_query_fill_std(qctrl);
418 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
419 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
422 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
423 err = v4l2_ctrl_query_fill_std(qctrl);
424 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
425 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
428 case V4L2_CID_MPEG_STREAM_VBI_FMT:
429 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
430 return v4l2_ctrl_query_fill_std(qctrl);
431 return cx2341x_ctrl_query_fill(qctrl,
432 V4L2_MPEG_STREAM_VBI_FMT_NONE,
433 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
434 V4L2_MPEG_STREAM_VBI_FMT_NONE);
436 /* CX23415/6 specific */
437 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
438 return cx2341x_ctrl_query_fill(qctrl,
439 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
440 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
441 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
443 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
444 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
445 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
446 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
447 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
450 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
451 cx2341x_ctrl_query_fill(qctrl,
452 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
453 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
454 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
455 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
456 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
459 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
460 cx2341x_ctrl_query_fill(qctrl,
461 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
462 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
463 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
464 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
468 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
469 return cx2341x_ctrl_query_fill(qctrl,
470 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
471 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
472 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
474 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
475 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
476 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
477 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
478 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
481 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
482 return cx2341x_ctrl_query_fill(qctrl,
483 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
484 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
485 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
487 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
488 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
489 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
490 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
491 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
494 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
495 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
496 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
497 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
498 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
501 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
502 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
503 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
504 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
505 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
508 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
509 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
510 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
511 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
512 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
516 return v4l2_ctrl_query_fill_std(qctrl);
521 const char **cx2341x_ctrl_get_menu(u32 id)
523 static const char *mpeg_stream_type[] = {
524 "MPEG-2 Program Stream",
526 "MPEG-1 System Stream",
527 "MPEG-2 DVD-compatible Stream",
528 "MPEG-1 VCD-compatible Stream",
529 "MPEG-2 SVCD-compatible Stream",
533 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
539 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
544 "2D Symmetric non-separable",
548 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
554 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
560 static const char *cx2341x_video_median_filter_type_menu[] = {
564 "Horizontal/Vertical",
570 case V4L2_CID_MPEG_STREAM_TYPE:
571 return mpeg_stream_type;
572 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
573 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
575 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
576 return cx2341x_video_spatial_filter_mode_menu;
577 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
578 return cx2341x_video_luma_spatial_filter_type_menu;
579 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
580 return cx2341x_video_chroma_spatial_filter_type_menu;
581 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
582 return cx2341x_video_temporal_filter_mode_menu;
583 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
584 return cx2341x_video_median_filter_type_menu;
586 return v4l2_ctrl_get_menu(id);
590 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
592 params->audio_properties = (params->audio_sampling_freq << 0) |
593 ((3 - params->audio_encoding) << 2) |
594 ((1 + params->audio_l2_bitrate) << 4) |
595 (params->audio_mode << 8) |
596 (params->audio_mode_extension << 10) |
597 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
599 params->audio_emphasis) << 12) |
600 (params->audio_crc << 14);
603 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
604 struct v4l2_ext_controls *ctrls, unsigned int cmd)
609 if (cmd == VIDIOC_G_EXT_CTRLS) {
610 for (i = 0; i < ctrls->count; i++) {
611 struct v4l2_ext_control *ctrl = ctrls->controls + i;
613 err = cx2341x_get_ctrl(params, ctrl);
615 ctrls->error_idx = i;
621 for (i = 0; i < ctrls->count; i++) {
622 struct v4l2_ext_control *ctrl = ctrls->controls + i;
623 struct v4l2_queryctrl qctrl;
624 const char **menu_items = NULL;
627 err = cx2341x_ctrl_query(params, &qctrl);
630 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
631 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
632 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
635 err = cx2341x_set_ctrl(params, ctrl);
639 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
640 params->video_bitrate_peak < params->video_bitrate) {
642 ctrls->error_idx = ctrls->count;
645 ctrls->error_idx = i;
648 cx2341x_calc_audio_properties(params);
653 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
655 static struct cx2341x_mpeg_params default_params = {
658 .port = CX2341X_PORT_MEMORY,
664 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
665 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
668 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
669 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
670 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
671 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
672 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
673 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
674 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
677 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
678 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
680 .video_gop_size = 12,
681 .video_gop_closure = 1,
683 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
684 .video_bitrate = 6000000,
685 .video_bitrate_peak = 8000000,
686 .video_temporal_decimation = 0,
688 /* encoding filters */
689 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
690 .video_spatial_filter = 0,
691 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
692 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
693 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
694 .video_temporal_filter = 0,
695 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
696 .video_luma_median_filter_top = 255,
697 .video_luma_median_filter_bottom = 0,
698 .video_chroma_median_filter_top = 255,
699 .video_chroma_median_filter_bottom = 0,
703 cx2341x_calc_audio_properties(p);
706 static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
708 u32 data[CX2341X_MBOX_MAX_DATA];
712 va_start(vargs, args);
714 for (i = 0; i < args; i++) {
715 data[i] = va_arg(vargs, int);
718 return func(priv, cmd, args, 0, data);
721 int cx2341x_update(void *priv, cx2341x_mbox_func func,
722 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
724 static int mpeg_stream_type[] = {
735 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
737 if (old == NULL || old->is_50hz != new->is_50hz) {
738 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
742 if (old == NULL || old->width != new->width || old->height != new->height ||
743 old->video_encoding != new->video_encoding) {
747 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
751 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
755 if (old == NULL || old->stream_type != new->stream_type) {
756 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
759 if (old == NULL || old->video_aspect != new->video_aspect) {
760 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
763 if (old == NULL || old->video_b_frames != new->video_b_frames ||
764 old->video_gop_size != new->video_gop_size) {
765 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
766 new->video_gop_size, new->video_b_frames + 1);
769 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
770 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
773 if (old == NULL || old->video_pulldown != new->video_pulldown) {
774 err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
777 if (old == NULL || old->audio_properties != new->audio_properties) {
778 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
781 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
782 old->video_bitrate != new->video_bitrate ||
783 old->video_bitrate_peak != new->video_bitrate_peak) {
784 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
785 new->video_bitrate_mode, new->video_bitrate,
786 new->video_bitrate_peak / 400, 0, 0);
789 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
790 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
791 old->video_median_filter_type != new->video_median_filter_type) {
792 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
793 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
794 new->video_median_filter_type);
798 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
799 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
800 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
801 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
802 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
803 new->video_luma_median_filter_bottom,
804 new->video_luma_median_filter_top,
805 new->video_chroma_median_filter_bottom,
806 new->video_chroma_median_filter_top);
810 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
811 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
812 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
813 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
817 old->video_spatial_filter != new->video_spatial_filter ||
818 old->video_temporal_filter != new->video_temporal_filter) {
819 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
820 new->video_spatial_filter, new->video_temporal_filter);
823 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
824 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
825 new->video_temporal_decimation);
831 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
833 const char **menu = cx2341x_ctrl_get_menu(id);
834 struct v4l2_ext_control ctrl;
839 if (cx2341x_get_ctrl(p, &ctrl))
841 while (ctrl.value-- && *menu) menu++;
850 void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
852 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
855 printk(KERN_INFO "%s: Stream: %s\n",
857 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
860 printk(KERN_INFO "%s: Video: %dx%d, %d fps\n",
862 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
863 p->is_50hz ? 25 : 30);
864 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
866 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
867 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
868 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
870 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
871 printk(", Peak %d", p->video_bitrate_peak);
874 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
876 p->video_gop_size, p->video_b_frames,
877 p->video_gop_closure ? "" : "No ",
878 p->video_pulldown ? "" : "No ");
879 if (p->video_temporal_decimation) {
880 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
881 prefix, p->video_temporal_decimation);
885 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s",
887 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
888 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
889 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
890 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
891 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
893 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
896 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
897 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
899 /* Encoding filters */
900 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
902 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
903 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
904 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
905 p->video_spatial_filter);
906 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
908 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
909 p->video_temporal_filter);
910 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
912 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
913 p->video_luma_median_filter_bottom,
914 p->video_luma_median_filter_top,
915 p->video_chroma_median_filter_bottom,
916 p->video_chroma_median_filter_top);
919 EXPORT_SYMBOL(cx2341x_fill_defaults);
920 EXPORT_SYMBOL(cx2341x_ctrl_query);
921 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
922 EXPORT_SYMBOL(cx2341x_ext_ctrls);
923 EXPORT_SYMBOL(cx2341x_update);
924 EXPORT_SYMBOL(cx2341x_log_status);
925 EXPORT_SYMBOL(cx2341x_mpeg_ctrls);