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
);