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