V4L/DVB (12102): em28xx: add Remote control support for EVGA inDtube
[deliverable/linux.git] / drivers / media / video / cx2341x.c
CommitLineData
5d1a9ae6 1/*
0d82fe80 2 * cx2341x - generic code for cx23415/6/8 based devices
5d1a9ae6
HV
3 *
4 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
5 *
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.
10 *
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.
15 *
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.
19 */
20
21
22#include <linux/module.h>
5d1a9ae6
HV
23#include <linux/errno.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/videodev2.h>
5d1a9ae6
HV
28
29#include <media/tuner.h>
30#include <media/cx2341x.h>
31#include <media/v4l2-common.h>
32
0d82fe80 33MODULE_DESCRIPTION("cx23415/6/8 driver");
5d1a9ae6
HV
34MODULE_AUTHOR("Hans Verkuil");
35MODULE_LICENSE("GPL");
36
737bd410 37static int debug;
5d1a9ae6
HV
38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Debug level (0-1)");
40
2ba58894 41/* Must be sorted from low to high control ID! */
cc7bc648
HV
42const u32 cx2341x_mpeg_ctrls[] = {
43 V4L2_CID_MPEG_CLASS,
44 V4L2_CID_MPEG_STREAM_TYPE,
8cbde94b 45 V4L2_CID_MPEG_STREAM_VBI_FMT,
cc7bc648
HV
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,
5eee72e8 53 V4L2_CID_MPEG_AUDIO_MUTE,
ee6f78cd 54 V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
cc7bc648
HV
55 V4L2_CID_MPEG_VIDEO_ENCODING,
56 V4L2_CID_MPEG_VIDEO_ASPECT,
57 V4L2_CID_MPEG_VIDEO_B_FRAMES,
58 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
59 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
cc7bc648
HV
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,
5eee72e8
HV
64 V4L2_CID_MPEG_VIDEO_MUTE,
65 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
cc7bc648
HV
66 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
68 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
70 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
71 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
72 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
73 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
74 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
75 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
76 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
5eee72e8 77 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
cc7bc648
HV
78 0
79};
737bd410 80EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
cc7bc648 81
ca130eef
HV
82static const struct cx2341x_mpeg_params default_params = {
83 /* misc */
84 .capabilities = 0,
85 .port = CX2341X_PORT_MEMORY,
86 .width = 720,
87 .height = 480,
88 .is_50hz = 0,
89
90 /* stream */
91 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
92 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
93 .stream_insert_nav_packets = 0,
94
95 /* audio */
96 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
97 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
98 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
0d82fe80 99 .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
ca130eef
HV
100 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
101 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
102 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
103 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
104 .audio_mute = 0,
105
106 /* video */
107 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
108 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
109 .video_b_frames = 2,
110 .video_gop_size = 12,
111 .video_gop_closure = 1,
112 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
113 .video_bitrate = 6000000,
114 .video_bitrate_peak = 8000000,
115 .video_temporal_decimation = 0,
116 .video_mute = 0,
117 .video_mute_yuv = 0x008080, /* YCbCr value for black */
118
119 /* encoding filters */
120 .video_spatial_filter_mode =
121 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
122 .video_spatial_filter = 0,
123 .video_luma_spatial_filter_type =
124 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
125 .video_chroma_spatial_filter_type =
126 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
127 .video_temporal_filter_mode =
128 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
129 .video_temporal_filter = 8,
130 .video_median_filter_type =
131 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
132 .video_luma_median_filter_top = 255,
133 .video_luma_median_filter_bottom = 0,
134 .video_chroma_median_filter_top = 255,
135 .video_chroma_median_filter_bottom = 0,
136};
137
5d1a9ae6
HV
138
139/* Map the control ID to the correct field in the cx2341x_mpeg_params
140 struct. Return -EINVAL if the ID is unknown, else return 0. */
e0e31cdb 141static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
5d1a9ae6
HV
142 struct v4l2_ext_control *ctrl)
143{
144 switch (ctrl->id) {
145 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
146 ctrl->value = params->audio_sampling_freq;
147 break;
148 case V4L2_CID_MPEG_AUDIO_ENCODING:
149 ctrl->value = params->audio_encoding;
150 break;
151 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
152 ctrl->value = params->audio_l2_bitrate;
153 break;
0d82fe80
AW
154 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
155 ctrl->value = params->audio_ac3_bitrate;
156 break;
5d1a9ae6
HV
157 case V4L2_CID_MPEG_AUDIO_MODE:
158 ctrl->value = params->audio_mode;
159 break;
160 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
161 ctrl->value = params->audio_mode_extension;
162 break;
163 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
164 ctrl->value = params->audio_emphasis;
165 break;
166 case V4L2_CID_MPEG_AUDIO_CRC:
167 ctrl->value = params->audio_crc;
168 break;
5eee72e8
HV
169 case V4L2_CID_MPEG_AUDIO_MUTE:
170 ctrl->value = params->audio_mute;
171 break;
5d1a9ae6
HV
172 case V4L2_CID_MPEG_VIDEO_ENCODING:
173 ctrl->value = params->video_encoding;
174 break;
175 case V4L2_CID_MPEG_VIDEO_ASPECT:
176 ctrl->value = params->video_aspect;
177 break;
178 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
179 ctrl->value = params->video_b_frames;
180 break;
181 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
182 ctrl->value = params->video_gop_size;
183 break;
184 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
185 ctrl->value = params->video_gop_closure;
186 break;
5d1a9ae6
HV
187 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
188 ctrl->value = params->video_bitrate_mode;
189 break;
190 case V4L2_CID_MPEG_VIDEO_BITRATE:
191 ctrl->value = params->video_bitrate;
192 break;
193 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
194 ctrl->value = params->video_bitrate_peak;
195 break;
196 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
197 ctrl->value = params->video_temporal_decimation;
198 break;
5eee72e8
HV
199 case V4L2_CID_MPEG_VIDEO_MUTE:
200 ctrl->value = params->video_mute;
201 break;
202 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
203 ctrl->value = params->video_mute_yuv;
204 break;
5d1a9ae6
HV
205 case V4L2_CID_MPEG_STREAM_TYPE:
206 ctrl->value = params->stream_type;
207 break;
8cbde94b
HV
208 case V4L2_CID_MPEG_STREAM_VBI_FMT:
209 ctrl->value = params->stream_vbi_fmt;
210 break;
5d1a9ae6
HV
211 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
212 ctrl->value = params->video_spatial_filter_mode;
213 break;
214 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
215 ctrl->value = params->video_spatial_filter;
216 break;
217 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
218 ctrl->value = params->video_luma_spatial_filter_type;
219 break;
220 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
221 ctrl->value = params->video_chroma_spatial_filter_type;
222 break;
223 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
224 ctrl->value = params->video_temporal_filter_mode;
225 break;
226 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
227 ctrl->value = params->video_temporal_filter;
228 break;
229 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
230 ctrl->value = params->video_median_filter_type;
231 break;
232 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
233 ctrl->value = params->video_luma_median_filter_top;
234 break;
235 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
236 ctrl->value = params->video_luma_median_filter_bottom;
237 break;
238 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
239 ctrl->value = params->video_chroma_median_filter_top;
240 break;
241 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
242 ctrl->value = params->video_chroma_median_filter_bottom;
243 break;
5eee72e8
HV
244 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
245 ctrl->value = params->stream_insert_nav_packets;
246 break;
5d1a9ae6
HV
247 default:
248 return -EINVAL;
249 }
250 return 0;
251}
252
253/* Map the control ID to the correct field in the cx2341x_mpeg_params
254 struct. Return -EINVAL if the ID is unknown, else return 0. */
01f1e44f 255static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
5d1a9ae6
HV
256 struct v4l2_ext_control *ctrl)
257{
258 switch (ctrl->id) {
259 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
01f1e44f
HV
260 if (busy)
261 return -EBUSY;
5d1a9ae6
HV
262 params->audio_sampling_freq = ctrl->value;
263 break;
264 case V4L2_CID_MPEG_AUDIO_ENCODING:
0d82fe80
AW
265 if (busy)
266 return -EBUSY;
31230c5f
AW
267 if (params->capabilities & CX2341X_CAP_HAS_AC3)
268 if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
269 ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
270 return -ERANGE;
5d1a9ae6
HV
271 params->audio_encoding = ctrl->value;
272 break;
273 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
01f1e44f
HV
274 if (busy)
275 return -EBUSY;
5d1a9ae6
HV
276 params->audio_l2_bitrate = ctrl->value;
277 break;
0d82fe80
AW
278 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
279 if (busy)
280 return -EBUSY;
31230c5f
AW
281 if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
282 return -EINVAL;
0d82fe80
AW
283 params->audio_ac3_bitrate = ctrl->value;
284 break;
5d1a9ae6
HV
285 case V4L2_CID_MPEG_AUDIO_MODE:
286 params->audio_mode = ctrl->value;
287 break;
288 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
289 params->audio_mode_extension = ctrl->value;
290 break;
291 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
292 params->audio_emphasis = ctrl->value;
293 break;
294 case V4L2_CID_MPEG_AUDIO_CRC:
295 params->audio_crc = ctrl->value;
296 break;
5eee72e8
HV
297 case V4L2_CID_MPEG_AUDIO_MUTE:
298 params->audio_mute = ctrl->value;
299 break;
5d1a9ae6
HV
300 case V4L2_CID_MPEG_VIDEO_ASPECT:
301 params->video_aspect = ctrl->value;
302 break;
303 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
304 int b = ctrl->value + 1;
305 int gop = params->video_gop_size;
306 params->video_b_frames = ctrl->value;
307 params->video_gop_size = b * ((gop + b - 1) / b);
308 /* Max GOP size = 34 */
309 while (params->video_gop_size > 34)
310 params->video_gop_size -= b;
311 break;
312 }
313 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
314 int b = params->video_b_frames + 1;
315 int gop = ctrl->value;
316 params->video_gop_size = b * ((gop + b - 1) / b);
317 /* Max GOP size = 34 */
318 while (params->video_gop_size > 34)
319 params->video_gop_size -= b;
320 ctrl->value = params->video_gop_size;
321 break;
322 }
323 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
324 params->video_gop_closure = ctrl->value;
325 break;
5d1a9ae6 326 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
01f1e44f
HV
327 if (busy)
328 return -EBUSY;
5d1a9ae6
HV
329 /* MPEG-1 only allows CBR */
330 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
331 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
332 return -EINVAL;
333 params->video_bitrate_mode = ctrl->value;
334 break;
335 case V4L2_CID_MPEG_VIDEO_BITRATE:
01f1e44f
HV
336 if (busy)
337 return -EBUSY;
5d1a9ae6
HV
338 params->video_bitrate = ctrl->value;
339 break;
340 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
01f1e44f
HV
341 if (busy)
342 return -EBUSY;
5d1a9ae6
HV
343 params->video_bitrate_peak = ctrl->value;
344 break;
345 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
346 params->video_temporal_decimation = ctrl->value;
347 break;
5eee72e8
HV
348 case V4L2_CID_MPEG_VIDEO_MUTE:
349 params->video_mute = (ctrl->value != 0);
350 break;
351 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
352 params->video_mute_yuv = ctrl->value;
353 break;
5d1a9ae6 354 case V4L2_CID_MPEG_STREAM_TYPE:
01f1e44f
HV
355 if (busy)
356 return -EBUSY;
5d1a9ae6
HV
357 params->stream_type = ctrl->value;
358 params->video_encoding =
737bd410
HV
359 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
360 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
361 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
362 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
363 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
5d1a9ae6 364 /* MPEG-1 implies CBR */
737bd410
HV
365 params->video_bitrate_mode =
366 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
5d1a9ae6 367 break;
8cbde94b
HV
368 case V4L2_CID_MPEG_STREAM_VBI_FMT:
369 params->stream_vbi_fmt = ctrl->value;
370 break;
5d1a9ae6
HV
371 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
372 params->video_spatial_filter_mode = ctrl->value;
373 break;
374 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
375 params->video_spatial_filter = ctrl->value;
376 break;
377 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
378 params->video_luma_spatial_filter_type = ctrl->value;
379 break;
380 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
381 params->video_chroma_spatial_filter_type = ctrl->value;
382 break;
383 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
384 params->video_temporal_filter_mode = ctrl->value;
385 break;
386 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
387 params->video_temporal_filter = ctrl->value;
388 break;
389 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
390 params->video_median_filter_type = ctrl->value;
391 break;
392 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
393 params->video_luma_median_filter_top = ctrl->value;
394 break;
395 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
396 params->video_luma_median_filter_bottom = ctrl->value;
397 break;
398 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
399 params->video_chroma_median_filter_top = ctrl->value;
400 break;
401 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
402 params->video_chroma_median_filter_bottom = ctrl->value;
403 break;
5eee72e8
HV
404 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
405 params->stream_insert_nav_packets = ctrl->value;
406 break;
5d1a9ae6
HV
407 default:
408 return -EINVAL;
409 }
410 return 0;
411}
412
737bd410
HV
413static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
414 s32 min, s32 max, s32 step, s32 def)
5d1a9ae6
HV
415{
416 const char *name;
417
418 qctrl->flags = 0;
419 switch (qctrl->id) {
420 /* MPEG controls */
421 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
422 name = "Spatial Filter Mode";
423 break;
424 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
425 name = "Spatial Filter";
426 break;
427 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
428 name = "Spatial Luma Filter Type";
429 break;
430 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
431 name = "Spatial Chroma Filter Type";
432 break;
433 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
434 name = "Temporal Filter Mode";
435 break;
436 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
437 name = "Temporal Filter";
438 break;
439 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
440 name = "Median Filter Type";
441 break;
442 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
443 name = "Median Luma Filter Maximum";
444 break;
445 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
446 name = "Median Luma Filter Minimum";
447 break;
448 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
449 name = "Median Chroma Filter Maximum";
450 break;
451 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
452 name = "Median Chroma Filter Minimum";
453 break;
5eee72e8
HV
454 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
455 name = "Insert Navigation Packets";
456 break;
5d1a9ae6
HV
457
458 default:
459 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
460 }
461 switch (qctrl->id) {
462 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
463 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
464 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
465 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
466 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
467 qctrl->type = V4L2_CTRL_TYPE_MENU;
468 min = 0;
469 step = 1;
470 break;
5eee72e8
HV
471 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
472 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
473 min = 0;
474 max = 1;
475 step = 1;
476 break;
5d1a9ae6
HV
477 default:
478 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
479 break;
480 }
481 switch (qctrl->id) {
482 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
483 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
484 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
485 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
486 break;
487 }
488 qctrl->minimum = min;
489 qctrl->maximum = max;
490 qctrl->step = step;
491 qctrl->default_value = def;
492 qctrl->reserved[0] = qctrl->reserved[1] = 0;
493 snprintf(qctrl->name, sizeof(qctrl->name), name);
494 return 0;
495}
496
e0e31cdb 497int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
737bd410 498 struct v4l2_queryctrl *qctrl)
5d1a9ae6
HV
499{
500 int err;
501
502 switch (qctrl->id) {
10afbef1
HV
503 case V4L2_CID_MPEG_STREAM_TYPE:
504 return v4l2_ctrl_query_fill(qctrl,
505 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
506 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
507 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
508
509 case V4L2_CID_MPEG_STREAM_VBI_FMT:
510 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
511 return v4l2_ctrl_query_fill(qctrl,
512 V4L2_MPEG_STREAM_VBI_FMT_NONE,
513 V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
514 V4L2_MPEG_STREAM_VBI_FMT_NONE);
515 return cx2341x_ctrl_query_fill(qctrl,
516 V4L2_MPEG_STREAM_VBI_FMT_NONE,
517 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
518 default_params.stream_vbi_fmt);
519
520 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
521 return v4l2_ctrl_query_fill(qctrl,
522 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
523 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
524 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
525
5d1a9ae6 526 case V4L2_CID_MPEG_AUDIO_ENCODING:
31230c5f
AW
527 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
528 /*
529 * The state of L2 & AC3 bitrate controls can change
530 * when this control changes, but v4l2_ctrl_query_fill()
531 * already sets V4L2_CTRL_FLAG_UPDATE for
532 * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
533 */
0d82fe80
AW
534 return v4l2_ctrl_query_fill(qctrl,
535 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
536 V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
537 default_params.audio_encoding);
31230c5f 538 }
0d82fe80 539
5d1a9ae6
HV
540 return v4l2_ctrl_query_fill(qctrl,
541 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
542 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
ca130eef 543 default_params.audio_encoding);
5d1a9ae6
HV
544
545 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
31230c5f 546 err = v4l2_ctrl_query_fill(qctrl,
5d1a9ae6
HV
547 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
548 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
ca130eef 549 default_params.audio_l2_bitrate);
31230c5f
AW
550 if (err)
551 return err;
552 if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
553 params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
554 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
555 return 0;
5d1a9ae6 556
10afbef1
HV
557 case V4L2_CID_MPEG_AUDIO_MODE:
558 return v4l2_ctrl_query_fill(qctrl,
559 V4L2_MPEG_AUDIO_MODE_STEREO,
560 V4L2_MPEG_AUDIO_MODE_MONO, 1,
561 V4L2_MPEG_AUDIO_MODE_STEREO);
562
563 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
564 err = v4l2_ctrl_query_fill(qctrl,
565 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
566 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
567 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
568 if (err == 0 &&
569 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
570 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
571 return err;
572
573 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
574 return v4l2_ctrl_query_fill(qctrl,
575 V4L2_MPEG_AUDIO_EMPHASIS_NONE,
576 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
577 V4L2_MPEG_AUDIO_EMPHASIS_NONE);
578
579 case V4L2_CID_MPEG_AUDIO_CRC:
580 return v4l2_ctrl_query_fill(qctrl,
581 V4L2_MPEG_AUDIO_CRC_NONE,
582 V4L2_MPEG_AUDIO_CRC_CRC16, 1,
583 V4L2_MPEG_AUDIO_CRC_NONE);
584
585 case V4L2_CID_MPEG_AUDIO_MUTE:
586 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
5d1a9ae6 587
0d82fe80 588 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
31230c5f 589 err = v4l2_ctrl_query_fill(qctrl,
0d82fe80
AW
590 V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
591 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
592 default_params.audio_ac3_bitrate);
31230c5f
AW
593 if (err)
594 return err;
595 if (params->capabilities & CX2341X_CAP_HAS_AC3) {
596 if (params->audio_encoding !=
597 V4L2_MPEG_AUDIO_ENCODING_AC3)
598 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
599 } else
600 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
601 return 0;
0d82fe80 602
5d1a9ae6
HV
603 case V4L2_CID_MPEG_VIDEO_ENCODING:
604 /* this setting is read-only for the cx2341x since the
605 V4L2_CID_MPEG_STREAM_TYPE really determines the
606 MPEG-1/2 setting */
188919ac
JG
607 err = v4l2_ctrl_query_fill(qctrl,
608 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
609 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
610 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
5d1a9ae6
HV
611 if (err == 0)
612 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
613 return err;
614
10afbef1
HV
615 case V4L2_CID_MPEG_VIDEO_ASPECT:
616 return v4l2_ctrl_query_fill(qctrl,
617 V4L2_MPEG_VIDEO_ASPECT_1x1,
618 V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
619 V4L2_MPEG_VIDEO_ASPECT_4x3);
620
621 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
622 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
623
624 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
625 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
626 params->is_50hz ? 12 : 15);
627
628 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
629 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
630
54aa9a21 631 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
10afbef1
HV
632 err = v4l2_ctrl_query_fill(qctrl,
633 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
634 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
635 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
737bd410
HV
636 if (err == 0 &&
637 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
54aa9a21
HV
638 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
639 return err;
640
10afbef1
HV
641 case V4L2_CID_MPEG_VIDEO_BITRATE:
642 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
643
5d1a9ae6 644 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
10afbef1 645 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
737bd410
HV
646 if (err == 0 &&
647 params->video_bitrate_mode ==
648 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
5d1a9ae6
HV
649 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
650 return err;
651
10afbef1
HV
652 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
653 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
ca130eef 654
10afbef1
HV
655 case V4L2_CID_MPEG_VIDEO_MUTE:
656 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
657
658 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */
659 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
8cbde94b 660
5d1a9ae6
HV
661 /* CX23415/6 specific */
662 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
663 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
664 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
665 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
ca130eef 666 default_params.video_spatial_filter_mode);
5d1a9ae6
HV
667
668 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
ca130eef
HV
669 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
670 default_params.video_spatial_filter);
5d1a9ae6 671 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
672 if (params->video_spatial_filter_mode ==
673 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
674 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
675 return 0;
676
677 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
678 cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
679 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
680 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
681 1,
ca130eef 682 default_params.video_luma_spatial_filter_type);
737bd410
HV
683 if (params->video_spatial_filter_mode ==
684 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
685 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
686 return 0;
687
688 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
689 cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
690 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
691 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
692 1,
ca130eef 693 default_params.video_chroma_spatial_filter_type);
737bd410
HV
694 if (params->video_spatial_filter_mode ==
695 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
696 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
697 return 0;
698
699 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
700 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
701 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
702 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
ca130eef 703 default_params.video_temporal_filter_mode);
5d1a9ae6
HV
704
705 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
ca130eef
HV
706 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
707 default_params.video_temporal_filter);
5d1a9ae6 708 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
709 if (params->video_temporal_filter_mode ==
710 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
711 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
712 return 0;
713
714 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
715 return cx2341x_ctrl_query_fill(qctrl,
737bd410
HV
716 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
717 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
ca130eef 718 default_params.video_median_filter_type);
5d1a9ae6
HV
719
720 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
ca130eef
HV
721 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
722 default_params.video_luma_median_filter_top);
5d1a9ae6 723 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
724 if (params->video_median_filter_type ==
725 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
726 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
727 return 0;
728
729 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
ca130eef
HV
730 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
731 default_params.video_luma_median_filter_bottom);
5d1a9ae6 732 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
733 if (params->video_median_filter_type ==
734 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
735 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
736 return 0;
737
738 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
ca130eef
HV
739 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
740 default_params.video_chroma_median_filter_top);
5d1a9ae6 741 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
742 if (params->video_median_filter_type ==
743 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
744 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
745 return 0;
746
747 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
ca130eef
HV
748 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
749 default_params.video_chroma_median_filter_bottom);
5d1a9ae6 750 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
737bd410
HV
751 if (params->video_median_filter_type ==
752 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
753 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
5d1a9ae6
HV
754 return 0;
755
5eee72e8 756 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
ca130eef
HV
757 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
758 default_params.stream_insert_nav_packets);
5eee72e8 759
5d1a9ae6 760 default:
10afbef1 761 return -EINVAL;
5d1a9ae6
HV
762
763 }
764}
737bd410 765EXPORT_SYMBOL(cx2341x_ctrl_query);
5d1a9ae6 766
e0e31cdb 767const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
5d1a9ae6 768{
e0e31cdb 769 static const char *mpeg_stream_type_without_ts[] = {
5d1a9ae6
HV
770 "MPEG-2 Program Stream",
771 "",
772 "MPEG-1 System Stream",
773 "MPEG-2 DVD-compatible Stream",
774 "MPEG-1 VCD-compatible Stream",
775 "MPEG-2 SVCD-compatible Stream",
776 NULL
777 };
778
e0e31cdb
HV
779 static const char *mpeg_stream_type_with_ts[] = {
780 "MPEG-2 Program Stream",
781 "MPEG-2 Transport Stream",
782 "MPEG-1 System Stream",
783 "MPEG-2 DVD-compatible Stream",
784 "MPEG-1 VCD-compatible Stream",
785 "MPEG-2 SVCD-compatible Stream",
786 NULL
787 };
788
0d82fe80
AW
789 static const char *mpeg_audio_encoding_l2_ac3[] = {
790 "",
791 "MPEG-1/2 Layer II",
792 "",
793 "",
794 "AC-3",
795 NULL
796 };
797
5d1a9ae6
HV
798 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
799 "Manual",
800 "Auto",
801 NULL
802 };
803
804 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
805 "Off",
806 "1D Horizontal",
807 "1D Vertical",
808 "2D H/V Separable",
809 "2D Symmetric non-separable",
810 NULL
811 };
812
813 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
814 "Off",
815 "1D Horizontal",
816 NULL
817 };
818
819 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
820 "Manual",
821 "Auto",
822 NULL
823 };
824
825 static const char *cx2341x_video_median_filter_type_menu[] = {
826 "Off",
827 "Horizontal",
828 "Vertical",
829 "Horizontal/Vertical",
830 "Diagonal",
831 NULL
832 };
833
834 switch (id) {
835 case V4L2_CID_MPEG_STREAM_TYPE:
e0e31cdb
HV
836 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
837 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
0d82fe80
AW
838 case V4L2_CID_MPEG_AUDIO_ENCODING:
839 return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
840 mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
5d1a9ae6
HV
841 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
842 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
843 return NULL;
844 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
845 return cx2341x_video_spatial_filter_mode_menu;
846 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
847 return cx2341x_video_luma_spatial_filter_type_menu;
848 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
849 return cx2341x_video_chroma_spatial_filter_type_menu;
850 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
851 return cx2341x_video_temporal_filter_mode_menu;
852 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
853 return cx2341x_video_median_filter_type_menu;
854 default:
855 return v4l2_ctrl_get_menu(id);
856 }
857}
737bd410 858EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
5d1a9ae6 859
0d82fe80 860/* definitions for audio properties bits 29-28 */
31230c5f
AW
861#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
862#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
863#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
0d82fe80 864
5d1a9ae6
HV
865static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
866{
0d82fe80
AW
867 params->audio_properties =
868 (params->audio_sampling_freq << 0) |
5d1a9ae6
HV
869 (params->audio_mode << 8) |
870 (params->audio_mode_extension << 10) |
737bd410
HV
871 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
872 ? 3 : params->audio_emphasis) << 12) |
5d1a9ae6 873 (params->audio_crc << 14);
0d82fe80
AW
874
875 if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
876 params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
877 params->audio_properties |=
878 /* Not sure if this MPEG Layer II setting is required */
879 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
880 (params->audio_ac3_bitrate << 4) |
31230c5f 881 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
0d82fe80
AW
882 } else {
883 /* Assuming MPEG Layer II */
884 params->audio_properties |=
885 ((3 - params->audio_encoding) << 2) |
886 ((1 + params->audio_l2_bitrate) << 4);
887 }
5d1a9ae6
HV
888}
889
01f1e44f 890int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
4d6b5aee 891 struct v4l2_ext_controls *ctrls, unsigned int cmd)
5d1a9ae6
HV
892{
893 int err = 0;
894 int i;
895
896 if (cmd == VIDIOC_G_EXT_CTRLS) {
897 for (i = 0; i < ctrls->count; i++) {
898 struct v4l2_ext_control *ctrl = ctrls->controls + i;
899
900 err = cx2341x_get_ctrl(params, ctrl);
901 if (err) {
902 ctrls->error_idx = i;
903 break;
904 }
905 }
906 return err;
907 }
908 for (i = 0; i < ctrls->count; i++) {
909 struct v4l2_ext_control *ctrl = ctrls->controls + i;
910 struct v4l2_queryctrl qctrl;
911 const char **menu_items = NULL;
912
913 qctrl.id = ctrl->id;
914 err = cx2341x_ctrl_query(params, &qctrl);
915 if (err)
916 break;
917 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
e0e31cdb 918 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
5d1a9ae6
HV
919 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
920 if (err)
921 break;
01f1e44f 922 err = cx2341x_set_ctrl(params, busy, ctrl);
5d1a9ae6
HV
923 if (err)
924 break;
925 }
737bd410
HV
926 if (err == 0 &&
927 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
928 params->video_bitrate_peak < params->video_bitrate) {
5d1a9ae6
HV
929 err = -ERANGE;
930 ctrls->error_idx = ctrls->count;
931 }
737bd410 932 if (err)
5d1a9ae6 933 ctrls->error_idx = i;
737bd410 934 else
5d1a9ae6 935 cx2341x_calc_audio_properties(params);
5d1a9ae6
HV
936 return err;
937}
737bd410 938EXPORT_SYMBOL(cx2341x_ext_ctrls);
5d1a9ae6
HV
939
940void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
941{
5d1a9ae6
HV
942 *p = default_params;
943 cx2341x_calc_audio_properties(p);
944}
737bd410 945EXPORT_SYMBOL(cx2341x_fill_defaults);
5d1a9ae6 946
737bd410 947static int cx2341x_api(void *priv, cx2341x_mbox_func func,
ea48c13a 948 u32 cmd, int args, ...)
5d1a9ae6
HV
949{
950 u32 data[CX2341X_MBOX_MAX_DATA];
951 va_list vargs;
952 int i;
953
954 va_start(vargs, args);
955
737bd410 956 for (i = 0; i < args; i++)
5d1a9ae6 957 data[i] = va_arg(vargs, int);
5d1a9ae6
HV
958 va_end(vargs);
959 return func(priv, cmd, args, 0, data);
960}
961
737bd410
HV
962#define NEQ(field) (old->field != new->field)
963
5d1a9ae6 964int cx2341x_update(void *priv, cx2341x_mbox_func func,
737bd410
HV
965 const struct cx2341x_mpeg_params *old,
966 const struct cx2341x_mpeg_params *new)
5d1a9ae6
HV
967{
968 static int mpeg_stream_type[] = {
969 0, /* MPEG-2 PS */
970 1, /* MPEG-2 TS */
971 2, /* MPEG-1 SS */
972 14, /* DVD */
973 11, /* VCD */
974 12, /* SVCD */
975 };
976
977 int err = 0;
737bd410 978 int force = (old == NULL);
44b579d6 979 u16 temporal = new->video_temporal_filter;
5d1a9ae6 980
45ad9f8b 981 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
5d1a9ae6 982
737bd410
HV
983 if (force || NEQ(is_50hz)) {
984 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
985 new->is_50hz);
5d1a9ae6
HV
986 if (err) return err;
987 }
988
737bd410 989 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
5d1a9ae6
HV
990 u16 w = new->width;
991 u16 h = new->height;
992
993 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
994 w /= 2;
995 h /= 2;
996 }
737bd410
HV
997 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
998 h, w);
5d1a9ae6 999 if (err) return err;
12b896e4 1000 }
44b579d6 1001
12b896e4 1002 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
737bd410
HV
1003 /* Adjust temporal filter if necessary. The problem with the
1004 temporal filter is that it works well with full resolution
1005 capturing, but not when the capture window is scaled (the
1006 filter introduces a ghosting effect). So if the capture
1007 window is scaled, then force the filter to 0.
44b579d6 1008
12b896e4 1009 For full resolution the filter really improves the video
737bd410
HV
1010 quality, especially if the original video quality is
1011 suboptimal. */
12b896e4 1012 temporal = 0;
5d1a9ae6
HV
1013 }
1014
737bd410
HV
1015 if (force || NEQ(stream_type)) {
1016 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1017 mpeg_stream_type[new->stream_type]);
5d1a9ae6
HV
1018 if (err) return err;
1019 }
737bd410
HV
1020 if (force || NEQ(video_aspect)) {
1021 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1022 1 + new->video_aspect);
5d1a9ae6
HV
1023 if (err) return err;
1024 }
737bd410 1025 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
5d1a9ae6
HV
1026 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1027 new->video_gop_size, new->video_b_frames + 1);
1028 if (err) return err;
1029 }
737bd410
HV
1030 if (force || NEQ(video_gop_closure)) {
1031 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1032 new->video_gop_closure);
5d1a9ae6
HV
1033 if (err) return err;
1034 }
737bd410
HV
1035 if (force || NEQ(audio_properties)) {
1036 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1037 1, new->audio_properties);
5d1a9ae6
HV
1038 if (err) return err;
1039 }
737bd410
HV
1040 if (force || NEQ(audio_mute)) {
1041 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1042 new->audio_mute);
5eee72e8
HV
1043 if (err) return err;
1044 }
737bd410
HV
1045 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1046 NEQ(video_bitrate_peak)) {
5d1a9ae6
HV
1047 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1048 new->video_bitrate_mode, new->video_bitrate,
1049 new->video_bitrate_peak / 400, 0, 0);
1050 if (err) return err;
1051 }
737bd410
HV
1052 if (force || NEQ(video_spatial_filter_mode) ||
1053 NEQ(video_temporal_filter_mode) ||
1054 NEQ(video_median_filter_type)) {
1055 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1056 2, new->video_spatial_filter_mode |
1057 (new->video_temporal_filter_mode << 1),
5d1a9ae6
HV
1058 new->video_median_filter_type);
1059 if (err) return err;
1060 }
737bd410
HV
1061 if (force || NEQ(video_luma_median_filter_bottom) ||
1062 NEQ(video_luma_median_filter_top) ||
1063 NEQ(video_chroma_median_filter_bottom) ||
1064 NEQ(video_chroma_median_filter_top)) {
5d1a9ae6
HV
1065 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1066 new->video_luma_median_filter_bottom,
1067 new->video_luma_median_filter_top,
1068 new->video_chroma_median_filter_bottom,
1069 new->video_chroma_median_filter_top);
1070 if (err) return err;
1071 }
737bd410
HV
1072 if (force || NEQ(video_luma_spatial_filter_type) ||
1073 NEQ(video_chroma_spatial_filter_type)) {
1074 err = cx2341x_api(priv, func,
1075 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1076 2, new->video_luma_spatial_filter_type,
1077 new->video_chroma_spatial_filter_type);
5d1a9ae6
HV
1078 if (err) return err;
1079 }
737bd410
HV
1080 if (force || NEQ(video_spatial_filter) ||
1081 old->video_temporal_filter != temporal) {
1082 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1083 2, new->video_spatial_filter, temporal);
5d1a9ae6
HV
1084 if (err) return err;
1085 }
737bd410
HV
1086 if (force || NEQ(video_temporal_decimation)) {
1087 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1088 1, new->video_temporal_decimation);
5d1a9ae6
HV
1089 if (err) return err;
1090 }
737bd410
HV
1091 if (force || NEQ(video_mute) ||
1092 (new->video_mute && NEQ(video_mute_yuv))) {
1093 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1094 new->video_mute | (new->video_mute_yuv << 8));
5eee72e8
HV
1095 if (err) return err;
1096 }
737bd410
HV
1097 if (force || NEQ(stream_insert_nav_packets)) {
1098 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1099 7, new->stream_insert_nav_packets);
5eee72e8
HV
1100 if (err) return err;
1101 }
5d1a9ae6
HV
1102 return 0;
1103}
737bd410 1104EXPORT_SYMBOL(cx2341x_update);
5d1a9ae6 1105
e0e31cdb 1106static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
5d1a9ae6 1107{
e0e31cdb 1108 const char **menu = cx2341x_ctrl_get_menu(p, id);
5d1a9ae6
HV
1109 struct v4l2_ext_control ctrl;
1110
1111 if (menu == NULL)
1112 goto invalid;
1113 ctrl.id = id;
1114 if (cx2341x_get_ctrl(p, &ctrl))
1115 goto invalid;
1116 while (ctrl.value-- && *menu) menu++;
1117 if (*menu == NULL)
1118 goto invalid;
1119 return *menu;
1120
1121invalid:
1122 return "<invalid>";
1123}
1124
e0e31cdb 1125void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
5d1a9ae6
HV
1126{
1127 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
83aaf13c 1128 int temporal = p->video_temporal_filter;
5d1a9ae6
HV
1129
1130 /* Stream */
5eee72e8 1131 printk(KERN_INFO "%s: Stream: %s",
99eb44fe 1132 prefix,
5d1a9ae6 1133 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
5eee72e8
HV
1134 if (p->stream_insert_nav_packets)
1135 printk(" (with navigation packets)");
1136 printk("\n");
44b579d6
HV
1137 printk(KERN_INFO "%s: VBI Format: %s\n",
1138 prefix,
1139 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
5d1a9ae6
HV
1140
1141 /* Video */
5eee72e8 1142 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
99eb44fe 1143 prefix,
5d1a9ae6 1144 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
5eee72e8
HV
1145 p->is_50hz ? 25 : 30,
1146 (p->video_mute) ? " (muted)" : "");
99eb44fe
HV
1147 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
1148 prefix,
5d1a9ae6
HV
1149 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1150 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1151 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1152 p->video_bitrate);
737bd410 1153 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
5d1a9ae6 1154 printk(", Peak %d", p->video_bitrate_peak);
5d1a9ae6 1155 printk("\n");
737bd410
HV
1156 printk(KERN_INFO
1157 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
99eb44fe 1158 prefix,
5d1a9ae6 1159 p->video_gop_size, p->video_b_frames,
75558ab9 1160 p->video_gop_closure ? "" : "No ");
737bd410 1161 if (p->video_temporal_decimation)
99eb44fe
HV
1162 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1163 prefix, p->video_temporal_decimation);
5d1a9ae6
HV
1164
1165 /* Audio */
5eee72e8 1166 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
99eb44fe 1167 prefix,
5d1a9ae6
HV
1168 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1169 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
0d82fe80
AW
1170 cx2341x_menu_item(p,
1171 p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1172 ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1173 : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
5eee72e8
HV
1174 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1175 p->audio_mute ? " (muted)" : "");
737bd410
HV
1176 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1177 printk(", %s", cx2341x_menu_item(p,
1178 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
5d1a9ae6
HV
1179 printk(", %s, %s\n",
1180 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1181 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1182
1183 /* Encoding filters */
99eb44fe
HV
1184 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1185 prefix,
737bd410
HV
1186 cx2341x_menu_item(p,
1187 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1188 cx2341x_menu_item(p,
1189 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1190 cx2341x_menu_item(p,
1191 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
5d1a9ae6 1192 p->video_spatial_filter);
737bd410
HV
1193
1194 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
83aaf13c 1195 temporal = 0;
737bd410 1196
99eb44fe
HV
1197 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1198 prefix,
737bd410
HV
1199 cx2341x_menu_item(p,
1200 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
83aaf13c 1201 temporal);
737bd410
HV
1202 printk(KERN_INFO
1203 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
99eb44fe 1204 prefix,
737bd410
HV
1205 cx2341x_menu_item(p,
1206 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
5d1a9ae6
HV
1207 p->video_luma_median_filter_bottom,
1208 p->video_luma_median_filter_top,
1209 p->video_chroma_median_filter_bottom,
1210 p->video_chroma_median_filter_top);
1211}
5d1a9ae6
HV
1212EXPORT_SYMBOL(cx2341x_log_status);
1213
1214/*
1215 * Local variables:
1216 * c-basic-offset: 8
1217 * End:
1218 */
1219
This page took 0.448758 seconds and 5 git commands to generate.