blob: 88dbdddeec42afaa34c9fded534cd5f9cbd0ab10 [file] [log] [blame]
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001/*
2 * cx2341x - generic code for cx23415/6 based devices
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>
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>
30
31#include <media/tuner.h>
32#include <media/cx2341x.h>
33#include <media/v4l2-common.h>
34
35MODULE_DESCRIPTION("cx23415/6 driver");
36MODULE_AUTHOR("Hans Verkuil");
37MODULE_LICENSE("GPL");
38
39static int debug = 0;
40module_param(debug, int, 0644);
41MODULE_PARM_DESC(debug, "Debug level (0-1)");
42
Hans Verkuilcc7bc642006-06-19 17:53:08 -030043const u32 cx2341x_mpeg_ctrls[] = {
44 V4L2_CID_MPEG_CLASS,
45 V4L2_CID_MPEG_STREAM_TYPE,
Hans Verkuil8cbde942006-06-24 14:36:02 -030046 V4L2_CID_MPEG_STREAM_VBI_FMT,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030047 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
48 V4L2_CID_MPEG_AUDIO_ENCODING,
49 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
50 V4L2_CID_MPEG_AUDIO_MODE,
51 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
52 V4L2_CID_MPEG_AUDIO_EMPHASIS,
53 V4L2_CID_MPEG_AUDIO_CRC,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030054 V4L2_CID_MPEG_AUDIO_MUTE,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030055 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,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030060 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030064 V4L2_CID_MPEG_VIDEO_MUTE,
65 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030066 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,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030077 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030078 0
79};
80
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030081
82/* Map the control ID to the correct field in the cx2341x_mpeg_params
83 struct. Return -EINVAL if the ID is unknown, else return 0. */
84static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
85 struct v4l2_ext_control *ctrl)
86{
87 switch (ctrl->id) {
88 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
89 ctrl->value = params->audio_sampling_freq;
90 break;
91 case V4L2_CID_MPEG_AUDIO_ENCODING:
92 ctrl->value = params->audio_encoding;
93 break;
94 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
95 ctrl->value = params->audio_l2_bitrate;
96 break;
97 case V4L2_CID_MPEG_AUDIO_MODE:
98 ctrl->value = params->audio_mode;
99 break;
100 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
101 ctrl->value = params->audio_mode_extension;
102 break;
103 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
104 ctrl->value = params->audio_emphasis;
105 break;
106 case V4L2_CID_MPEG_AUDIO_CRC:
107 ctrl->value = params->audio_crc;
108 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300109 case V4L2_CID_MPEG_AUDIO_MUTE:
110 ctrl->value = params->audio_mute;
111 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300112 case V4L2_CID_MPEG_VIDEO_ENCODING:
113 ctrl->value = params->video_encoding;
114 break;
115 case V4L2_CID_MPEG_VIDEO_ASPECT:
116 ctrl->value = params->video_aspect;
117 break;
118 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
119 ctrl->value = params->video_b_frames;
120 break;
121 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
122 ctrl->value = params->video_gop_size;
123 break;
124 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
125 ctrl->value = params->video_gop_closure;
126 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300127 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
128 ctrl->value = params->video_bitrate_mode;
129 break;
130 case V4L2_CID_MPEG_VIDEO_BITRATE:
131 ctrl->value = params->video_bitrate;
132 break;
133 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
134 ctrl->value = params->video_bitrate_peak;
135 break;
136 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
137 ctrl->value = params->video_temporal_decimation;
138 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300139 case V4L2_CID_MPEG_VIDEO_MUTE:
140 ctrl->value = params->video_mute;
141 break;
142 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
143 ctrl->value = params->video_mute_yuv;
144 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300145 case V4L2_CID_MPEG_STREAM_TYPE:
146 ctrl->value = params->stream_type;
147 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300148 case V4L2_CID_MPEG_STREAM_VBI_FMT:
149 ctrl->value = params->stream_vbi_fmt;
150 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300151 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
152 ctrl->value = params->video_spatial_filter_mode;
153 break;
154 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
155 ctrl->value = params->video_spatial_filter;
156 break;
157 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
158 ctrl->value = params->video_luma_spatial_filter_type;
159 break;
160 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
161 ctrl->value = params->video_chroma_spatial_filter_type;
162 break;
163 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
164 ctrl->value = params->video_temporal_filter_mode;
165 break;
166 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
167 ctrl->value = params->video_temporal_filter;
168 break;
169 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
170 ctrl->value = params->video_median_filter_type;
171 break;
172 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
173 ctrl->value = params->video_luma_median_filter_top;
174 break;
175 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
176 ctrl->value = params->video_luma_median_filter_bottom;
177 break;
178 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
179 ctrl->value = params->video_chroma_median_filter_top;
180 break;
181 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
182 ctrl->value = params->video_chroma_median_filter_bottom;
183 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300184 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
185 ctrl->value = params->stream_insert_nav_packets;
186 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300187 default:
188 return -EINVAL;
189 }
190 return 0;
191}
192
193/* Map the control ID to the correct field in the cx2341x_mpeg_params
194 struct. Return -EINVAL if the ID is unknown, else return 0. */
195static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
196 struct v4l2_ext_control *ctrl)
197{
198 switch (ctrl->id) {
199 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
200 params->audio_sampling_freq = ctrl->value;
201 break;
202 case V4L2_CID_MPEG_AUDIO_ENCODING:
203 params->audio_encoding = ctrl->value;
204 break;
205 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
206 params->audio_l2_bitrate = ctrl->value;
207 break;
208 case V4L2_CID_MPEG_AUDIO_MODE:
209 params->audio_mode = ctrl->value;
210 break;
211 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
212 params->audio_mode_extension = ctrl->value;
213 break;
214 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
215 params->audio_emphasis = ctrl->value;
216 break;
217 case V4L2_CID_MPEG_AUDIO_CRC:
218 params->audio_crc = ctrl->value;
219 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300220 case V4L2_CID_MPEG_AUDIO_MUTE:
221 params->audio_mute = ctrl->value;
222 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300223 case V4L2_CID_MPEG_VIDEO_ASPECT:
224 params->video_aspect = ctrl->value;
225 break;
226 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
227 int b = ctrl->value + 1;
228 int gop = params->video_gop_size;
229 params->video_b_frames = ctrl->value;
230 params->video_gop_size = b * ((gop + b - 1) / b);
231 /* Max GOP size = 34 */
232 while (params->video_gop_size > 34)
233 params->video_gop_size -= b;
234 break;
235 }
236 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
237 int b = params->video_b_frames + 1;
238 int gop = ctrl->value;
239 params->video_gop_size = b * ((gop + b - 1) / b);
240 /* Max GOP size = 34 */
241 while (params->video_gop_size > 34)
242 params->video_gop_size -= b;
243 ctrl->value = params->video_gop_size;
244 break;
245 }
246 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
247 params->video_gop_closure = ctrl->value;
248 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300249 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
250 /* MPEG-1 only allows CBR */
251 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
252 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
253 return -EINVAL;
254 params->video_bitrate_mode = ctrl->value;
255 break;
256 case V4L2_CID_MPEG_VIDEO_BITRATE:
257 params->video_bitrate = ctrl->value;
258 break;
259 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
260 params->video_bitrate_peak = ctrl->value;
261 break;
262 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
263 params->video_temporal_decimation = ctrl->value;
264 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300265 case V4L2_CID_MPEG_VIDEO_MUTE:
266 params->video_mute = (ctrl->value != 0);
267 break;
268 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
269 params->video_mute_yuv = ctrl->value;
270 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300271 case V4L2_CID_MPEG_STREAM_TYPE:
272 params->stream_type = ctrl->value;
273 params->video_encoding =
274 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
275 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
276 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
277 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
278 /* MPEG-1 implies CBR */
279 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
280 }
281 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300282 case V4L2_CID_MPEG_STREAM_VBI_FMT:
283 params->stream_vbi_fmt = ctrl->value;
284 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300285 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
286 params->video_spatial_filter_mode = ctrl->value;
287 break;
288 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
289 params->video_spatial_filter = ctrl->value;
290 break;
291 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
292 params->video_luma_spatial_filter_type = ctrl->value;
293 break;
294 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
295 params->video_chroma_spatial_filter_type = ctrl->value;
296 break;
297 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
298 params->video_temporal_filter_mode = ctrl->value;
299 break;
300 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
301 params->video_temporal_filter = ctrl->value;
302 break;
303 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
304 params->video_median_filter_type = ctrl->value;
305 break;
306 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
307 params->video_luma_median_filter_top = ctrl->value;
308 break;
309 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
310 params->video_luma_median_filter_bottom = ctrl->value;
311 break;
312 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
313 params->video_chroma_median_filter_top = ctrl->value;
314 break;
315 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
316 params->video_chroma_median_filter_bottom = ctrl->value;
317 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300318 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
319 params->stream_insert_nav_packets = ctrl->value;
320 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300321 default:
322 return -EINVAL;
323 }
324 return 0;
325}
326
327static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
328{
329 const char *name;
330
331 qctrl->flags = 0;
332 switch (qctrl->id) {
333 /* MPEG controls */
334 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
335 name = "Spatial Filter Mode";
336 break;
337 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
338 name = "Spatial Filter";
339 break;
340 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
341 name = "Spatial Luma Filter Type";
342 break;
343 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
344 name = "Spatial Chroma Filter Type";
345 break;
346 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
347 name = "Temporal Filter Mode";
348 break;
349 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
350 name = "Temporal Filter";
351 break;
352 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
353 name = "Median Filter Type";
354 break;
355 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
356 name = "Median Luma Filter Maximum";
357 break;
358 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
359 name = "Median Luma Filter Minimum";
360 break;
361 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
362 name = "Median Chroma Filter Maximum";
363 break;
364 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
365 name = "Median Chroma Filter Minimum";
366 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300367 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
368 name = "Insert Navigation Packets";
369 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300370
371 default:
372 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
373 }
374 switch (qctrl->id) {
375 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
376 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
377 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
378 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
379 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
380 qctrl->type = V4L2_CTRL_TYPE_MENU;
381 min = 0;
382 step = 1;
383 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300384 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
385 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
386 min = 0;
387 max = 1;
388 step = 1;
389 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300390 default:
391 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
392 break;
393 }
394 switch (qctrl->id) {
395 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
396 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
397 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
398 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
399 break;
400 }
401 qctrl->minimum = min;
402 qctrl->maximum = max;
403 qctrl->step = step;
404 qctrl->default_value = def;
405 qctrl->reserved[0] = qctrl->reserved[1] = 0;
406 snprintf(qctrl->name, sizeof(qctrl->name), name);
407 return 0;
408}
409
410int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
411{
412 int err;
413
414 switch (qctrl->id) {
415 case V4L2_CID_MPEG_AUDIO_ENCODING:
416 return v4l2_ctrl_query_fill(qctrl,
417 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
418 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
419 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
420
421 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
422 return v4l2_ctrl_query_fill(qctrl,
423 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
424 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
425 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
426
427 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
428 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
429 return -EINVAL;
430
431 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
432 err = v4l2_ctrl_query_fill_std(qctrl);
433 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
434 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
435 return err;
436
437 case V4L2_CID_MPEG_VIDEO_ENCODING:
438 /* this setting is read-only for the cx2341x since the
439 V4L2_CID_MPEG_STREAM_TYPE really determines the
440 MPEG-1/2 setting */
441 err = v4l2_ctrl_query_fill_std(qctrl);
442 if (err == 0)
443 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
444 return err;
445
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300446 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
447 err = v4l2_ctrl_query_fill_std(qctrl);
448 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
449 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
450 return err;
451
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300452 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
453 err = v4l2_ctrl_query_fill_std(qctrl);
454 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
455 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
456 return err;
457
Hans Verkuil8cbde942006-06-24 14:36:02 -0300458 case V4L2_CID_MPEG_STREAM_VBI_FMT:
459 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
460 return v4l2_ctrl_query_fill_std(qctrl);
461 return cx2341x_ctrl_query_fill(qctrl,
462 V4L2_MPEG_STREAM_VBI_FMT_NONE,
463 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
464 V4L2_MPEG_STREAM_VBI_FMT_NONE);
465
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300466 /* CX23415/6 specific */
467 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
468 return cx2341x_ctrl_query_fill(qctrl,
469 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
470 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
471 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
472
473 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
474 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
475 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
476 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
477 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
478 return 0;
479
480 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
481 cx2341x_ctrl_query_fill(qctrl,
482 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
483 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
484 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
485 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
486 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
487 return 0;
488
489 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
490 cx2341x_ctrl_query_fill(qctrl,
491 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
492 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
493 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
494 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
495 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
496 return 0;
497
498 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
499 return cx2341x_ctrl_query_fill(qctrl,
500 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
501 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
502 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
503
504 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
505 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
506 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
507 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
508 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
509 return 0;
510
511 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
512 return cx2341x_ctrl_query_fill(qctrl,
513 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
514 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
515 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
516
517 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
518 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
519 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
520 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
521 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
522 return 0;
523
524 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
525 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
526 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
527 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
528 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
529 return 0;
530
531 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
532 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
533 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
534 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
535 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
536 return 0;
537
538 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
539 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
540 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
541 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
542 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
543 return 0;
544
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300545 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
546 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
547
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300548 default:
549 return v4l2_ctrl_query_fill_std(qctrl);
550
551 }
552}
553
554const char **cx2341x_ctrl_get_menu(u32 id)
555{
556 static const char *mpeg_stream_type[] = {
557 "MPEG-2 Program Stream",
558 "",
559 "MPEG-1 System Stream",
560 "MPEG-2 DVD-compatible Stream",
561 "MPEG-1 VCD-compatible Stream",
562 "MPEG-2 SVCD-compatible Stream",
563 NULL
564 };
565
566 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
567 "Manual",
568 "Auto",
569 NULL
570 };
571
572 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
573 "Off",
574 "1D Horizontal",
575 "1D Vertical",
576 "2D H/V Separable",
577 "2D Symmetric non-separable",
578 NULL
579 };
580
581 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
582 "Off",
583 "1D Horizontal",
584 NULL
585 };
586
587 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
588 "Manual",
589 "Auto",
590 NULL
591 };
592
593 static const char *cx2341x_video_median_filter_type_menu[] = {
594 "Off",
595 "Horizontal",
596 "Vertical",
597 "Horizontal/Vertical",
598 "Diagonal",
599 NULL
600 };
601
602 switch (id) {
603 case V4L2_CID_MPEG_STREAM_TYPE:
604 return mpeg_stream_type;
605 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
606 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
607 return NULL;
608 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
609 return cx2341x_video_spatial_filter_mode_menu;
610 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
611 return cx2341x_video_luma_spatial_filter_type_menu;
612 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
613 return cx2341x_video_chroma_spatial_filter_type_menu;
614 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
615 return cx2341x_video_temporal_filter_mode_menu;
616 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
617 return cx2341x_video_median_filter_type_menu;
618 default:
619 return v4l2_ctrl_get_menu(id);
620 }
621}
622
623static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
624{
625 params->audio_properties = (params->audio_sampling_freq << 0) |
626 ((3 - params->audio_encoding) << 2) |
627 ((1 + params->audio_l2_bitrate) << 4) |
628 (params->audio_mode << 8) |
629 (params->audio_mode_extension << 10) |
630 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
631 3 :
632 params->audio_emphasis) << 12) |
633 (params->audio_crc << 14);
634}
635
636int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300637 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300638{
639 int err = 0;
640 int i;
641
642 if (cmd == VIDIOC_G_EXT_CTRLS) {
643 for (i = 0; i < ctrls->count; i++) {
644 struct v4l2_ext_control *ctrl = ctrls->controls + i;
645
646 err = cx2341x_get_ctrl(params, ctrl);
647 if (err) {
648 ctrls->error_idx = i;
649 break;
650 }
651 }
652 return err;
653 }
654 for (i = 0; i < ctrls->count; i++) {
655 struct v4l2_ext_control *ctrl = ctrls->controls + i;
656 struct v4l2_queryctrl qctrl;
657 const char **menu_items = NULL;
658
659 qctrl.id = ctrl->id;
660 err = cx2341x_ctrl_query(params, &qctrl);
661 if (err)
662 break;
663 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
664 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
665 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
666 if (err)
667 break;
668 err = cx2341x_set_ctrl(params, ctrl);
669 if (err)
670 break;
671 }
672 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
673 params->video_bitrate_peak < params->video_bitrate) {
674 err = -ERANGE;
675 ctrls->error_idx = ctrls->count;
676 }
677 if (err) {
678 ctrls->error_idx = i;
679 }
680 else {
681 cx2341x_calc_audio_properties(params);
682 }
683 return err;
684}
685
686void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
687{
688 static struct cx2341x_mpeg_params default_params = {
689 /* misc */
Hans Verkuil8cbde942006-06-24 14:36:02 -0300690 .capabilities = 0,
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300691 .port = CX2341X_PORT_MEMORY,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300692 .width = 720,
693 .height = 480,
694 .is_50hz = 0,
695
696 /* stream */
697 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
Hans Verkuil8cbde942006-06-24 14:36:02 -0300698 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300699 .stream_insert_nav_packets = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300700
701 /* audio */
702 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
703 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
704 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
705 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
706 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
707 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
708 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300709 .audio_mute = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300710
711 /* video */
712 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
713 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
714 .video_b_frames = 2,
715 .video_gop_size = 12,
716 .video_gop_closure = 1,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300717 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
718 .video_bitrate = 6000000,
719 .video_bitrate_peak = 8000000,
720 .video_temporal_decimation = 0,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300721 .video_mute = 0,
722 .video_mute_yuv = 0x008080, /* YCbCr value for black */
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300723
724 /* encoding filters */
725 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
726 .video_spatial_filter = 0,
727 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
728 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
729 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300730 .video_temporal_filter = 8,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300731 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
732 .video_luma_median_filter_top = 255,
733 .video_luma_median_filter_bottom = 0,
734 .video_chroma_median_filter_top = 255,
735 .video_chroma_median_filter_bottom = 0,
736 };
737
738 *p = default_params;
739 cx2341x_calc_audio_properties(p);
740}
741
742static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
743{
744 u32 data[CX2341X_MBOX_MAX_DATA];
745 va_list vargs;
746 int i;
747
748 va_start(vargs, args);
749
750 for (i = 0; i < args; i++) {
751 data[i] = va_arg(vargs, int);
752 }
753 va_end(vargs);
754 return func(priv, cmd, args, 0, data);
755}
756
757int cx2341x_update(void *priv, cx2341x_mbox_func func,
758 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
759{
760 static int mpeg_stream_type[] = {
761 0, /* MPEG-2 PS */
762 1, /* MPEG-2 TS */
763 2, /* MPEG-1 SS */
764 14, /* DVD */
765 11, /* VCD */
766 12, /* SVCD */
767 };
768
769 int err = 0;
Hans Verkuil44b579d2006-08-27 19:22:15 -0300770 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300771
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300772 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300773
774 if (old == NULL || old->is_50hz != new->is_50hz) {
775 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
776 if (err) return err;
777 }
778
779 if (old == NULL || old->width != new->width || old->height != new->height ||
780 old->video_encoding != new->video_encoding) {
781 u16 w = new->width;
782 u16 h = new->height;
783
784 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
785 w /= 2;
786 h /= 2;
787 }
788 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
789 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300790 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300791
Hans Verkuil12b896e2006-12-18 13:37:50 -0300792 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil44b579d2006-08-27 19:22:15 -0300793 /* Adjust temporal filter if necessary. The problem with the temporal
794 filter is that it works well with full resolution capturing, but
795 not when the capture window is scaled (the filter introduces
Hans Verkuil12b896e2006-12-18 13:37:50 -0300796 a ghosting effect). So if the capture window is scaled, then
797 force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300798
Hans Verkuil12b896e2006-12-18 13:37:50 -0300799 For full resolution the filter really improves the video
Hans Verkuil44b579d2006-08-27 19:22:15 -0300800 quality, especially if the original video quality is suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300801 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300802 }
803
804 if (old == NULL || old->stream_type != new->stream_type) {
805 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
806 if (err) return err;
807 }
808 if (old == NULL || old->video_aspect != new->video_aspect) {
809 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
810 if (err) return err;
811 }
812 if (old == NULL || old->video_b_frames != new->video_b_frames ||
813 old->video_gop_size != new->video_gop_size) {
814 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
815 new->video_gop_size, new->video_b_frames + 1);
816 if (err) return err;
817 }
818 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
819 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
820 if (err) return err;
821 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300822 if (old == NULL || old->audio_properties != new->audio_properties) {
823 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
824 if (err) return err;
825 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300826 if (old == NULL || old->audio_mute != new->audio_mute) {
827 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, new->audio_mute);
828 if (err) return err;
829 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300830 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
831 old->video_bitrate != new->video_bitrate ||
832 old->video_bitrate_peak != new->video_bitrate_peak) {
833 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
834 new->video_bitrate_mode, new->video_bitrate,
835 new->video_bitrate_peak / 400, 0, 0);
836 if (err) return err;
837 }
838 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
839 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
840 old->video_median_filter_type != new->video_median_filter_type) {
841 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
842 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
843 new->video_median_filter_type);
844 if (err) return err;
845 }
846 if (old == NULL ||
847 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
848 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
849 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
850 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
851 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
852 new->video_luma_median_filter_bottom,
853 new->video_luma_median_filter_top,
854 new->video_chroma_median_filter_bottom,
855 new->video_chroma_median_filter_top);
856 if (err) return err;
857 }
858 if (old == NULL ||
859 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
860 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
861 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
862 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
863 if (err) return err;
864 }
865 if (old == NULL ||
866 old->video_spatial_filter != new->video_spatial_filter ||
Hans Verkuil44b579d2006-08-27 19:22:15 -0300867 old->video_temporal_filter != temporal) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300868 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300869 new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300870 if (err) return err;
871 }
872 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
873 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
874 new->video_temporal_decimation);
875 if (err) return err;
876 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300877 if (old == NULL || old->video_mute != new->video_mute ||
878 (new->video_mute && old->video_mute_yuv != new->video_mute_yuv)) {
879 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, new->video_mute | (new->video_mute_yuv << 8));
880 if (err) return err;
881 }
882 if (old == NULL || old->stream_insert_nav_packets != new->stream_insert_nav_packets) {
883 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 7, new->stream_insert_nav_packets);
884 if (err) return err;
885 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300886 return 0;
887}
888
889static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
890{
891 const char **menu = cx2341x_ctrl_get_menu(id);
892 struct v4l2_ext_control ctrl;
893
894 if (menu == NULL)
895 goto invalid;
896 ctrl.id = id;
897 if (cx2341x_get_ctrl(p, &ctrl))
898 goto invalid;
899 while (ctrl.value-- && *menu) menu++;
900 if (*menu == NULL)
901 goto invalid;
902 return *menu;
903
904invalid:
905 return "<invalid>";
906}
907
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300908void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300909{
910 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300911 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300912
913 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300914 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300915 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300916 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300917 if (p->stream_insert_nav_packets)
918 printk(" (with navigation packets)");
919 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300920 printk(KERN_INFO "%s: VBI Format: %s\n",
921 prefix,
922 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300923
924 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300925 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300926 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300927 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300928 p->is_50hz ? 25 : 30,
929 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300930 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
931 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300932 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
933 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
934 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
935 p->video_bitrate);
936 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
937 printk(", Peak %d", p->video_bitrate_peak);
938 }
939 printk("\n");
Hans Verkuil75558ab2006-12-18 22:52:21 -0300940 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300941 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300942 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -0300943 p->video_gop_closure ? "" : "No ");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300944 if (p->video_temporal_decimation) {
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300945 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
946 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300947 }
948
949 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300950 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300951 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300952 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
953 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
954 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300955 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
956 p->audio_mute ? " (muted)" : "");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300957 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
958 printk(", %s",
959 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
960 }
961 printk(", %s, %s\n",
962 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
963 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
964
965 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300966 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
967 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300968 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
969 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
970 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
971 p->video_spatial_filter);
Hans Verkuil83aaf132006-12-18 13:40:23 -0300972 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
973 temporal = 0;
974 }
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300975 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
976 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300977 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -0300978 temporal);
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300979 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
980 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300981 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
982 p->video_luma_median_filter_bottom,
983 p->video_luma_median_filter_top,
984 p->video_chroma_median_filter_bottom,
985 p->video_chroma_median_filter_top);
986}
987
988EXPORT_SYMBOL(cx2341x_fill_defaults);
989EXPORT_SYMBOL(cx2341x_ctrl_query);
990EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
991EXPORT_SYMBOL(cx2341x_ext_ctrls);
992EXPORT_SYMBOL(cx2341x_update);
993EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuilcc7bc642006-06-19 17:53:08 -0300994EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300995
996/*
997 * Local variables:
998 * c-basic-offset: 8
999 * End:
1000 */
1001