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_AUDIO_SAMPLING_FREQ
,
47 V4L2_CID_MPEG_AUDIO_ENCODING
,
48 V4L2_CID_MPEG_AUDIO_L2_BITRATE
,
49 V4L2_CID_MPEG_AUDIO_MODE
,
50 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION
,
51 V4L2_CID_MPEG_AUDIO_EMPHASIS
,
52 V4L2_CID_MPEG_AUDIO_CRC
,
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_PULLDOWN
,
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_PULLDOWN
:
121 ctrl
->value
= params
->video_pulldown
;
123 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE
:
124 ctrl
->value
= params
->video_bitrate_mode
;
126 case V4L2_CID_MPEG_VIDEO_BITRATE
:
127 ctrl
->value
= params
->video_bitrate
;
129 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK
:
130 ctrl
->value
= params
->video_bitrate_peak
;
132 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION
:
133 ctrl
->value
= params
->video_temporal_decimation
;
135 case V4L2_CID_MPEG_STREAM_TYPE
:
136 ctrl
->value
= params
->stream_type
;
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_PULLDOWN
:
231 params
->video_pulldown
= ctrl
->value
;
233 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE
:
234 /* MPEG-1 only allows CBR */
235 if (params
->video_encoding
== V4L2_MPEG_VIDEO_ENCODING_MPEG_1
&&
236 ctrl
->value
!= V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
)
238 params
->video_bitrate_mode
= ctrl
->value
;
240 case V4L2_CID_MPEG_VIDEO_BITRATE
:
241 params
->video_bitrate
= ctrl
->value
;
243 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK
:
244 params
->video_bitrate_peak
= ctrl
->value
;
246 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION
:
247 params
->video_temporal_decimation
= ctrl
->value
;
249 case V4L2_CID_MPEG_STREAM_TYPE
:
250 params
->stream_type
= ctrl
->value
;
251 params
->video_encoding
=
252 (params
->stream_type
== V4L2_MPEG_STREAM_TYPE_MPEG1_SS
||
253 params
->stream_type
== V4L2_MPEG_STREAM_TYPE_MPEG1_VCD
) ?
254 V4L2_MPEG_VIDEO_ENCODING_MPEG_1
: V4L2_MPEG_VIDEO_ENCODING_MPEG_2
;
255 if (params
->video_encoding
== V4L2_MPEG_VIDEO_ENCODING_MPEG_1
) {
256 /* MPEG-1 implies CBR */
257 params
->video_bitrate_mode
= V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
;
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 /* CX23415/6 specific */
422 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE
:
423 return cx2341x_ctrl_query_fill(qctrl
,
424 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL
,
425 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO
, 1,
426 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL
);
428 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER
:
429 cx2341x_ctrl_query_fill(qctrl
, 0, 15, 1, 0);
430 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
431 if (params
->video_spatial_filter_mode
== V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO
)
432 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
435 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE
:
436 cx2341x_ctrl_query_fill(qctrl
,
437 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF
,
438 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE
, 1,
439 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF
);
440 if (params
->video_spatial_filter_mode
== V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO
)
441 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
444 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE
:
445 cx2341x_ctrl_query_fill(qctrl
,
446 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF
,
447 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR
, 1,
448 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF
);
449 if (params
->video_spatial_filter_mode
== V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO
)
450 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
453 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE
:
454 return cx2341x_ctrl_query_fill(qctrl
,
455 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL
,
456 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO
, 1,
457 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL
);
459 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER
:
460 cx2341x_ctrl_query_fill(qctrl
, 0, 31, 1, 0);
461 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
462 if (params
->video_temporal_filter_mode
== V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO
)
463 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
466 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE
:
467 return cx2341x_ctrl_query_fill(qctrl
,
468 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
,
469 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG
, 1,
470 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
);
472 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP
:
473 cx2341x_ctrl_query_fill(qctrl
, 0, 255, 1, 255);
474 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
475 if (params
->video_median_filter_type
== V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
)
476 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
479 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM
:
480 cx2341x_ctrl_query_fill(qctrl
, 0, 255, 1, 0);
481 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
482 if (params
->video_median_filter_type
== V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
)
483 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
486 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP
:
487 cx2341x_ctrl_query_fill(qctrl
, 0, 255, 1, 255);
488 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
489 if (params
->video_median_filter_type
== V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
)
490 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
493 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM
:
494 cx2341x_ctrl_query_fill(qctrl
, 0, 255, 1, 0);
495 qctrl
->flags
|= V4L2_CTRL_FLAG_SLIDER
;
496 if (params
->video_median_filter_type
== V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
)
497 qctrl
->flags
|= V4L2_CTRL_FLAG_INACTIVE
;
501 return v4l2_ctrl_query_fill_std(qctrl
);
506 const char **cx2341x_ctrl_get_menu(u32 id
)
508 static const char *mpeg_stream_type
[] = {
509 "MPEG-2 Program Stream",
511 "MPEG-1 System Stream",
512 "MPEG-2 DVD-compatible Stream",
513 "MPEG-1 VCD-compatible Stream",
514 "MPEG-2 SVCD-compatible Stream",
518 static const char *cx2341x_video_spatial_filter_mode_menu
[] = {
524 static const char *cx2341x_video_luma_spatial_filter_type_menu
[] = {
529 "2D Symmetric non-separable",
533 static const char *cx2341x_video_chroma_spatial_filter_type_menu
[] = {
539 static const char *cx2341x_video_temporal_filter_mode_menu
[] = {
545 static const char *cx2341x_video_median_filter_type_menu
[] = {
549 "Horizontal/Vertical",
555 case V4L2_CID_MPEG_STREAM_TYPE
:
556 return mpeg_stream_type
;
557 case V4L2_CID_MPEG_AUDIO_L1_BITRATE
:
558 case V4L2_CID_MPEG_AUDIO_L3_BITRATE
:
560 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE
:
561 return cx2341x_video_spatial_filter_mode_menu
;
562 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE
:
563 return cx2341x_video_luma_spatial_filter_type_menu
;
564 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE
:
565 return cx2341x_video_chroma_spatial_filter_type_menu
;
566 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE
:
567 return cx2341x_video_temporal_filter_mode_menu
;
568 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE
:
569 return cx2341x_video_median_filter_type_menu
;
571 return v4l2_ctrl_get_menu(id
);
575 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params
*params
)
577 params
->audio_properties
= (params
->audio_sampling_freq
<< 0) |
578 ((3 - params
->audio_encoding
) << 2) |
579 ((1 + params
->audio_l2_bitrate
) << 4) |
580 (params
->audio_mode
<< 8) |
581 (params
->audio_mode_extension
<< 10) |
582 (((params
->audio_emphasis
== V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17
) ?
584 params
->audio_emphasis
) << 12) |
585 (params
->audio_crc
<< 14);
588 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params
*params
,
589 struct v4l2_ext_controls
*ctrls
, int cmd
)
594 if (cmd
== VIDIOC_G_EXT_CTRLS
) {
595 for (i
= 0; i
< ctrls
->count
; i
++) {
596 struct v4l2_ext_control
*ctrl
= ctrls
->controls
+ i
;
598 err
= cx2341x_get_ctrl(params
, ctrl
);
600 ctrls
->error_idx
= i
;
606 for (i
= 0; i
< ctrls
->count
; i
++) {
607 struct v4l2_ext_control
*ctrl
= ctrls
->controls
+ i
;
608 struct v4l2_queryctrl qctrl
;
609 const char **menu_items
= NULL
;
612 err
= cx2341x_ctrl_query(params
, &qctrl
);
615 if (qctrl
.type
== V4L2_CTRL_TYPE_MENU
)
616 menu_items
= cx2341x_ctrl_get_menu(qctrl
.id
);
617 err
= v4l2_ctrl_check(ctrl
, &qctrl
, menu_items
);
620 err
= cx2341x_set_ctrl(params
, ctrl
);
624 if (err
== 0 && params
->video_bitrate_mode
== V4L2_MPEG_VIDEO_BITRATE_MODE_VBR
&&
625 params
->video_bitrate_peak
< params
->video_bitrate
) {
627 ctrls
->error_idx
= ctrls
->count
;
630 ctrls
->error_idx
= i
;
633 cx2341x_calc_audio_properties(params
);
638 void cx2341x_fill_defaults(struct cx2341x_mpeg_params
*p
)
640 static struct cx2341x_mpeg_params default_params
= {
647 .stream_type
= V4L2_MPEG_STREAM_TYPE_MPEG2_PS
,
650 .audio_sampling_freq
= V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000
,
651 .audio_encoding
= V4L2_MPEG_AUDIO_ENCODING_LAYER_2
,
652 .audio_l2_bitrate
= V4L2_MPEG_AUDIO_L2_BITRATE_224K
,
653 .audio_mode
= V4L2_MPEG_AUDIO_MODE_STEREO
,
654 .audio_mode_extension
= V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4
,
655 .audio_emphasis
= V4L2_MPEG_AUDIO_EMPHASIS_NONE
,
656 .audio_crc
= V4L2_MPEG_AUDIO_CRC_NONE
,
659 .video_encoding
= V4L2_MPEG_VIDEO_ENCODING_MPEG_2
,
660 .video_aspect
= V4L2_MPEG_VIDEO_ASPECT_4x3
,
662 .video_gop_size
= 12,
663 .video_gop_closure
= 1,
665 .video_bitrate_mode
= V4L2_MPEG_VIDEO_BITRATE_MODE_VBR
,
666 .video_bitrate
= 6000000,
667 .video_bitrate_peak
= 8000000,
668 .video_temporal_decimation
= 0,
670 /* encoding filters */
671 .video_spatial_filter_mode
= V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL
,
672 .video_spatial_filter
= 0,
673 .video_luma_spatial_filter_type
= V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR
,
674 .video_chroma_spatial_filter_type
= V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR
,
675 .video_temporal_filter_mode
= V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL
,
676 .video_temporal_filter
= 0,
677 .video_median_filter_type
= V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF
,
678 .video_luma_median_filter_top
= 255,
679 .video_luma_median_filter_bottom
= 0,
680 .video_chroma_median_filter_top
= 255,
681 .video_chroma_median_filter_bottom
= 0,
685 cx2341x_calc_audio_properties(p
);
688 static int cx2341x_api(void *priv
, cx2341x_mbox_func func
, int cmd
, int args
, ...)
690 u32 data
[CX2341X_MBOX_MAX_DATA
];
694 va_start(vargs
, args
);
696 for (i
= 0; i
< args
; i
++) {
697 data
[i
] = va_arg(vargs
, int);
700 return func(priv
, cmd
, args
, 0, data
);
703 int cx2341x_update(void *priv
, cx2341x_mbox_func func
,
704 const struct cx2341x_mpeg_params
*old
, const struct cx2341x_mpeg_params
*new)
706 static int mpeg_stream_type
[] = {
717 cx2341x_api(priv
, func
, CX2341X_ENC_SET_OUTPUT_PORT
, 1, 0); /* 0 = Memory */
719 if (old
== NULL
|| old
->is_50hz
!= new->is_50hz
) {
720 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_FRAME_RATE
, 1, new->is_50hz
);
724 if (old
== NULL
|| old
->width
!= new->width
|| old
->height
!= new->height
||
725 old
->video_encoding
!= new->video_encoding
) {
729 if (new->video_encoding
== V4L2_MPEG_VIDEO_ENCODING_MPEG_1
) {
733 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_FRAME_SIZE
, 2, h
, w
);
737 if (old
== NULL
|| old
->stream_type
!= new->stream_type
) {
738 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_STREAM_TYPE
, 1, mpeg_stream_type
[new->stream_type
]);
741 if (old
== NULL
|| old
->video_aspect
!= new->video_aspect
) {
742 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_ASPECT_RATIO
, 1, 1 + new->video_aspect
);
745 if (old
== NULL
|| old
->video_b_frames
!= new->video_b_frames
||
746 old
->video_gop_size
!= new->video_gop_size
) {
747 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_GOP_PROPERTIES
, 2,
748 new->video_gop_size
, new->video_b_frames
+ 1);
751 if (old
== NULL
|| old
->video_gop_closure
!= new->video_gop_closure
) {
752 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_GOP_CLOSURE
, 1, new->video_gop_closure
);
755 if (old
== NULL
|| old
->video_pulldown
!= new->video_pulldown
) {
756 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_3_2_PULLDOWN
, 1, new->video_pulldown
);
759 if (old
== NULL
|| old
->audio_properties
!= new->audio_properties
) {
760 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_AUDIO_PROPERTIES
, 1, new->audio_properties
);
763 if (old
== NULL
|| old
->video_bitrate_mode
!= new->video_bitrate_mode
||
764 old
->video_bitrate
!= new->video_bitrate
||
765 old
->video_bitrate_peak
!= new->video_bitrate_peak
) {
766 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_BIT_RATE
, 5,
767 new->video_bitrate_mode
, new->video_bitrate
,
768 new->video_bitrate_peak
/ 400, 0, 0);
771 if (old
== NULL
|| old
->video_spatial_filter_mode
!= new->video_spatial_filter_mode
||
772 old
->video_temporal_filter_mode
!= new->video_temporal_filter_mode
||
773 old
->video_median_filter_type
!= new->video_median_filter_type
) {
774 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_DNR_FILTER_MODE
, 2,
775 new->video_spatial_filter_mode
| (new->video_temporal_filter_mode
<< 1),
776 new->video_median_filter_type
);
780 old
->video_luma_median_filter_bottom
!= new->video_luma_median_filter_bottom
||
781 old
->video_luma_median_filter_top
!= new->video_luma_median_filter_top
||
782 old
->video_chroma_median_filter_bottom
!= new->video_chroma_median_filter_bottom
||
783 old
->video_chroma_median_filter_top
!= new->video_chroma_median_filter_top
) {
784 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_CORING_LEVELS
, 4,
785 new->video_luma_median_filter_bottom
,
786 new->video_luma_median_filter_top
,
787 new->video_chroma_median_filter_bottom
,
788 new->video_chroma_median_filter_top
);
792 old
->video_luma_spatial_filter_type
!= new->video_luma_spatial_filter_type
||
793 old
->video_chroma_spatial_filter_type
!= new->video_chroma_spatial_filter_type
) {
794 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
, 2,
795 new->video_luma_spatial_filter_type
, new->video_chroma_spatial_filter_type
);
799 old
->video_spatial_filter
!= new->video_spatial_filter
||
800 old
->video_temporal_filter
!= new->video_temporal_filter
) {
801 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_DNR_FILTER_PROPS
, 2,
802 new->video_spatial_filter
, new->video_temporal_filter
);
805 if (old
== NULL
|| old
->video_temporal_decimation
!= new->video_temporal_decimation
) {
806 err
= cx2341x_api(priv
, func
, CX2341X_ENC_SET_FRAME_DROP_RATE
, 1,
807 new->video_temporal_decimation
);
813 static const char *cx2341x_menu_item(struct cx2341x_mpeg_params
*p
, u32 id
)
815 const char **menu
= cx2341x_ctrl_get_menu(id
);
816 struct v4l2_ext_control ctrl
;
821 if (cx2341x_get_ctrl(p
, &ctrl
))
823 while (ctrl
.value
-- && *menu
) menu
++;
832 void cx2341x_log_status(struct cx2341x_mpeg_params
*p
, int card_id
)
834 int is_mpeg1
= p
->video_encoding
== V4L2_MPEG_VIDEO_ENCODING_MPEG_1
;
837 printk(KERN_INFO
"cx2341x-%d: Stream: %s\n",
839 cx2341x_menu_item(p
, V4L2_CID_MPEG_STREAM_TYPE
));
842 printk(KERN_INFO
"cx2341x-%d: Video: %dx%d, %d fps\n",
844 p
->width
/ (is_mpeg1
? 2 : 1), p
->height
/ (is_mpeg1
? 2 : 1),
845 p
->is_50hz
? 25 : 30);
846 printk(KERN_INFO
"cx2341x-%d: Video: %s, %s, %s, %d",
848 cx2341x_menu_item(p
, V4L2_CID_MPEG_VIDEO_ENCODING
),
849 cx2341x_menu_item(p
, V4L2_CID_MPEG_VIDEO_ASPECT
),
850 cx2341x_menu_item(p
, V4L2_CID_MPEG_VIDEO_BITRATE_MODE
),
852 if (p
->video_bitrate_mode
== V4L2_MPEG_VIDEO_BITRATE_MODE_VBR
) {
853 printk(", Peak %d", p
->video_bitrate_peak
);
856 printk(KERN_INFO
"cx2341x-%d: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
858 p
->video_gop_size
, p
->video_b_frames
,
859 p
->video_gop_closure
? "" : "No ",
860 p
->video_pulldown
? "" : "No ");
861 if (p
->video_temporal_decimation
) {
862 printk(KERN_INFO
"cx2341x-%d: Video: Temporal Decimation %d\n",
863 card_id
, p
->video_temporal_decimation
);
867 printk(KERN_INFO
"cx2341x-%d: Audio: %s, %s, %s, %s",
869 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ
),
870 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_ENCODING
),
871 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_L2_BITRATE
),
872 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_MODE
));
873 if (p
->audio_mode
== V4L2_MPEG_AUDIO_MODE_JOINT_STEREO
) {
875 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION
));
878 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_EMPHASIS
),
879 cx2341x_menu_item(p
, V4L2_CID_MPEG_AUDIO_CRC
));
881 /* Encoding filters */
882 printk(KERN_INFO
"cx2341x-%d: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
884 cx2341x_menu_item(p
, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE
),
885 cx2341x_menu_item(p
, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE
),
886 cx2341x_menu_item(p
, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE
),
887 p
->video_spatial_filter
);
888 printk(KERN_INFO
"cx2341x-%d: Temporal Filter: %s, %d\n",
890 cx2341x_menu_item(p
, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE
),
891 p
->video_temporal_filter
);
892 printk(KERN_INFO
"cx2341x-%d: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
894 cx2341x_menu_item(p
, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE
),
895 p
->video_luma_median_filter_bottom
,
896 p
->video_luma_median_filter_top
,
897 p
->video_chroma_median_filter_bottom
,
898 p
->video_chroma_median_filter_top
);
901 EXPORT_SYMBOL(cx2341x_fill_defaults
);
902 EXPORT_SYMBOL(cx2341x_ctrl_query
);
903 EXPORT_SYMBOL(cx2341x_ctrl_get_menu
);
904 EXPORT_SYMBOL(cx2341x_ext_ctrls
);
905 EXPORT_SYMBOL(cx2341x_update
);
906 EXPORT_SYMBOL(cx2341x_log_status
);
907 EXPORT_SYMBOL(cx2341x_mpeg_ctrls
);