blob: 62304255dcae120cbf669f451942003227f4330e [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>
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030023#include <linux/errno.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/videodev2.h>
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030028
29#include <media/tuner.h>
30#include <media/cx2341x.h>
31#include <media/v4l2-common.h>
32
33MODULE_DESCRIPTION("cx23415/6 driver");
34MODULE_AUTHOR("Hans Verkuil");
35MODULE_LICENSE("GPL");
36
37static int debug = 0;
38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Debug level (0-1)");
40
Hans Verkuilcc7bc642006-06-19 17:53:08 -030041const u32 cx2341x_mpeg_ctrls[] = {
42 V4L2_CID_MPEG_CLASS,
43 V4L2_CID_MPEG_STREAM_TYPE,
Hans Verkuil8cbde942006-06-24 14:36:02 -030044 V4L2_CID_MPEG_STREAM_VBI_FMT,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030045 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
46 V4L2_CID_MPEG_AUDIO_ENCODING,
47 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
48 V4L2_CID_MPEG_AUDIO_MODE,
49 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
50 V4L2_CID_MPEG_AUDIO_EMPHASIS,
51 V4L2_CID_MPEG_AUDIO_CRC,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030052 V4L2_CID_MPEG_AUDIO_MUTE,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030053 V4L2_CID_MPEG_VIDEO_ENCODING,
54 V4L2_CID_MPEG_VIDEO_ASPECT,
55 V4L2_CID_MPEG_VIDEO_B_FRAMES,
56 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
57 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030058 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
59 V4L2_CID_MPEG_VIDEO_BITRATE,
60 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
61 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030062 V4L2_CID_MPEG_VIDEO_MUTE,
63 V4L2_CID_MPEG_VIDEO_MUTE_YUV,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030064 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
65 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
66 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
67 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
68 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
69 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
70 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
71 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
72 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
73 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
74 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
Hans Verkuil5eee72e2007-04-27 12:31:00 -030075 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
Hans Verkuilcc7bc642006-06-19 17:53:08 -030076 0
77};
78
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030079
80/* Map the control ID to the correct field in the cx2341x_mpeg_params
81 struct. Return -EINVAL if the ID is unknown, else return 0. */
82static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
83 struct v4l2_ext_control *ctrl)
84{
85 switch (ctrl->id) {
86 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
87 ctrl->value = params->audio_sampling_freq;
88 break;
89 case V4L2_CID_MPEG_AUDIO_ENCODING:
90 ctrl->value = params->audio_encoding;
91 break;
92 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
93 ctrl->value = params->audio_l2_bitrate;
94 break;
95 case V4L2_CID_MPEG_AUDIO_MODE:
96 ctrl->value = params->audio_mode;
97 break;
98 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
99 ctrl->value = params->audio_mode_extension;
100 break;
101 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
102 ctrl->value = params->audio_emphasis;
103 break;
104 case V4L2_CID_MPEG_AUDIO_CRC:
105 ctrl->value = params->audio_crc;
106 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300107 case V4L2_CID_MPEG_AUDIO_MUTE:
108 ctrl->value = params->audio_mute;
109 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300110 case V4L2_CID_MPEG_VIDEO_ENCODING:
111 ctrl->value = params->video_encoding;
112 break;
113 case V4L2_CID_MPEG_VIDEO_ASPECT:
114 ctrl->value = params->video_aspect;
115 break;
116 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
117 ctrl->value = params->video_b_frames;
118 break;
119 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
120 ctrl->value = params->video_gop_size;
121 break;
122 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
123 ctrl->value = params->video_gop_closure;
124 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300125 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
126 ctrl->value = params->video_bitrate_mode;
127 break;
128 case V4L2_CID_MPEG_VIDEO_BITRATE:
129 ctrl->value = params->video_bitrate;
130 break;
131 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
132 ctrl->value = params->video_bitrate_peak;
133 break;
134 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
135 ctrl->value = params->video_temporal_decimation;
136 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300137 case V4L2_CID_MPEG_VIDEO_MUTE:
138 ctrl->value = params->video_mute;
139 break;
140 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
141 ctrl->value = params->video_mute_yuv;
142 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300143 case V4L2_CID_MPEG_STREAM_TYPE:
144 ctrl->value = params->stream_type;
145 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300146 case V4L2_CID_MPEG_STREAM_VBI_FMT:
147 ctrl->value = params->stream_vbi_fmt;
148 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300149 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
150 ctrl->value = params->video_spatial_filter_mode;
151 break;
152 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
153 ctrl->value = params->video_spatial_filter;
154 break;
155 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
156 ctrl->value = params->video_luma_spatial_filter_type;
157 break;
158 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
159 ctrl->value = params->video_chroma_spatial_filter_type;
160 break;
161 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
162 ctrl->value = params->video_temporal_filter_mode;
163 break;
164 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
165 ctrl->value = params->video_temporal_filter;
166 break;
167 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
168 ctrl->value = params->video_median_filter_type;
169 break;
170 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
171 ctrl->value = params->video_luma_median_filter_top;
172 break;
173 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
174 ctrl->value = params->video_luma_median_filter_bottom;
175 break;
176 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
177 ctrl->value = params->video_chroma_median_filter_top;
178 break;
179 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
180 ctrl->value = params->video_chroma_median_filter_bottom;
181 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300182 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
183 ctrl->value = params->stream_insert_nav_packets;
184 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300185 default:
186 return -EINVAL;
187 }
188 return 0;
189}
190
191/* Map the control ID to the correct field in the cx2341x_mpeg_params
192 struct. Return -EINVAL if the ID is unknown, else return 0. */
Hans Verkuil01f1e442007-08-21 18:32:42 -0300193static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300194 struct v4l2_ext_control *ctrl)
195{
196 switch (ctrl->id) {
197 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300198 if (busy)
199 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300200 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:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300206 if (busy)
207 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300208 params->audio_l2_bitrate = ctrl->value;
209 break;
210 case V4L2_CID_MPEG_AUDIO_MODE:
211 params->audio_mode = ctrl->value;
212 break;
213 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
214 params->audio_mode_extension = ctrl->value;
215 break;
216 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
217 params->audio_emphasis = ctrl->value;
218 break;
219 case V4L2_CID_MPEG_AUDIO_CRC:
220 params->audio_crc = ctrl->value;
221 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300222 case V4L2_CID_MPEG_AUDIO_MUTE:
223 params->audio_mute = ctrl->value;
224 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300225 case V4L2_CID_MPEG_VIDEO_ASPECT:
226 params->video_aspect = ctrl->value;
227 break;
228 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
229 int b = ctrl->value + 1;
230 int gop = params->video_gop_size;
231 params->video_b_frames = ctrl->value;
232 params->video_gop_size = b * ((gop + b - 1) / b);
233 /* Max GOP size = 34 */
234 while (params->video_gop_size > 34)
235 params->video_gop_size -= b;
236 break;
237 }
238 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
239 int b = params->video_b_frames + 1;
240 int gop = ctrl->value;
241 params->video_gop_size = b * ((gop + b - 1) / b);
242 /* Max GOP size = 34 */
243 while (params->video_gop_size > 34)
244 params->video_gop_size -= b;
245 ctrl->value = params->video_gop_size;
246 break;
247 }
248 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
249 params->video_gop_closure = ctrl->value;
250 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300251 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300252 if (busy)
253 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300254 /* MPEG-1 only allows CBR */
255 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
256 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
257 return -EINVAL;
258 params->video_bitrate_mode = ctrl->value;
259 break;
260 case V4L2_CID_MPEG_VIDEO_BITRATE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300261 if (busy)
262 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300263 params->video_bitrate = ctrl->value;
264 break;
265 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300266 if (busy)
267 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300268 params->video_bitrate_peak = ctrl->value;
269 break;
270 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
271 params->video_temporal_decimation = ctrl->value;
272 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300273 case V4L2_CID_MPEG_VIDEO_MUTE:
274 params->video_mute = (ctrl->value != 0);
275 break;
276 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
277 params->video_mute_yuv = ctrl->value;
278 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300279 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300280 if (busy)
281 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300282 params->stream_type = ctrl->value;
283 params->video_encoding =
284 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
285 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
286 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
287 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
288 /* MPEG-1 implies CBR */
289 params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
290 }
291 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300292 case V4L2_CID_MPEG_STREAM_VBI_FMT:
293 params->stream_vbi_fmt = ctrl->value;
294 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300295 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
296 params->video_spatial_filter_mode = ctrl->value;
297 break;
298 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
299 params->video_spatial_filter = ctrl->value;
300 break;
301 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
302 params->video_luma_spatial_filter_type = ctrl->value;
303 break;
304 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
305 params->video_chroma_spatial_filter_type = ctrl->value;
306 break;
307 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
308 params->video_temporal_filter_mode = ctrl->value;
309 break;
310 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
311 params->video_temporal_filter = ctrl->value;
312 break;
313 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
314 params->video_median_filter_type = ctrl->value;
315 break;
316 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
317 params->video_luma_median_filter_top = ctrl->value;
318 break;
319 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
320 params->video_luma_median_filter_bottom = ctrl->value;
321 break;
322 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
323 params->video_chroma_median_filter_top = ctrl->value;
324 break;
325 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
326 params->video_chroma_median_filter_bottom = ctrl->value;
327 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300328 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
329 params->stream_insert_nav_packets = ctrl->value;
330 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300331 default:
332 return -EINVAL;
333 }
334 return 0;
335}
336
337static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
338{
339 const char *name;
340
341 qctrl->flags = 0;
342 switch (qctrl->id) {
343 /* MPEG controls */
344 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
345 name = "Spatial Filter Mode";
346 break;
347 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
348 name = "Spatial Filter";
349 break;
350 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
351 name = "Spatial Luma Filter Type";
352 break;
353 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
354 name = "Spatial Chroma Filter Type";
355 break;
356 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
357 name = "Temporal Filter Mode";
358 break;
359 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
360 name = "Temporal Filter";
361 break;
362 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
363 name = "Median Filter Type";
364 break;
365 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
366 name = "Median Luma Filter Maximum";
367 break;
368 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
369 name = "Median Luma Filter Minimum";
370 break;
371 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
372 name = "Median Chroma Filter Maximum";
373 break;
374 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
375 name = "Median Chroma Filter Minimum";
376 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300377 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
378 name = "Insert Navigation Packets";
379 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300380
381 default:
382 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
383 }
384 switch (qctrl->id) {
385 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
386 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
387 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
388 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
389 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
390 qctrl->type = V4L2_CTRL_TYPE_MENU;
391 min = 0;
392 step = 1;
393 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300394 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
395 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
396 min = 0;
397 max = 1;
398 step = 1;
399 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300400 default:
401 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
402 break;
403 }
404 switch (qctrl->id) {
405 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
406 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
407 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
408 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
409 break;
410 }
411 qctrl->minimum = min;
412 qctrl->maximum = max;
413 qctrl->step = step;
414 qctrl->default_value = def;
415 qctrl->reserved[0] = qctrl->reserved[1] = 0;
416 snprintf(qctrl->name, sizeof(qctrl->name), name);
417 return 0;
418}
419
420int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
421{
422 int err;
423
424 switch (qctrl->id) {
425 case V4L2_CID_MPEG_AUDIO_ENCODING:
426 return v4l2_ctrl_query_fill(qctrl,
427 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
428 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
429 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
430
431 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
432 return v4l2_ctrl_query_fill(qctrl,
433 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
434 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
435 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
436
437 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
438 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
439 return -EINVAL;
440
441 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
442 err = v4l2_ctrl_query_fill_std(qctrl);
443 if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
444 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
445 return err;
446
447 case V4L2_CID_MPEG_VIDEO_ENCODING:
448 /* this setting is read-only for the cx2341x since the
449 V4L2_CID_MPEG_STREAM_TYPE really determines the
450 MPEG-1/2 setting */
451 err = v4l2_ctrl_query_fill_std(qctrl);
452 if (err == 0)
453 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
454 return err;
455
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300456 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
457 err = v4l2_ctrl_query_fill_std(qctrl);
458 if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
459 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
460 return err;
461
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300462 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
463 err = v4l2_ctrl_query_fill_std(qctrl);
464 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
466 return err;
467
Hans Verkuil8cbde942006-06-24 14:36:02 -0300468 case V4L2_CID_MPEG_STREAM_VBI_FMT:
469 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
470 return v4l2_ctrl_query_fill_std(qctrl);
471 return cx2341x_ctrl_query_fill(qctrl,
472 V4L2_MPEG_STREAM_VBI_FMT_NONE,
473 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
474 V4L2_MPEG_STREAM_VBI_FMT_NONE);
475
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300476 /* CX23415/6 specific */
477 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
478 return cx2341x_ctrl_query_fill(qctrl,
479 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
480 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
481 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
482
483 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
484 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
485 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
486 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
487 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
488 return 0;
489
490 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
491 cx2341x_ctrl_query_fill(qctrl,
492 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
493 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
494 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
495 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
496 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
497 return 0;
498
499 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
500 cx2341x_ctrl_query_fill(qctrl,
501 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
502 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
503 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
504 if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
505 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
506 return 0;
507
508 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
509 return cx2341x_ctrl_query_fill(qctrl,
510 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
511 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
512 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
513
514 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
515 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
516 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
517 if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
518 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
519 return 0;
520
521 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
522 return cx2341x_ctrl_query_fill(qctrl,
523 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
524 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
525 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
526
527 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
528 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
529 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
530 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
531 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
532 return 0;
533
534 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
535 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
536 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
537 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
538 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
539 return 0;
540
541 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
542 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
543 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
544 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
545 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
546 return 0;
547
548 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
549 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
550 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
551 if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
552 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
553 return 0;
554
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300555 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
556 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
557
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300558 default:
559 return v4l2_ctrl_query_fill_std(qctrl);
560
561 }
562}
563
564const char **cx2341x_ctrl_get_menu(u32 id)
565{
566 static const char *mpeg_stream_type[] = {
567 "MPEG-2 Program Stream",
568 "",
569 "MPEG-1 System Stream",
570 "MPEG-2 DVD-compatible Stream",
571 "MPEG-1 VCD-compatible Stream",
572 "MPEG-2 SVCD-compatible Stream",
573 NULL
574 };
575
576 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
577 "Manual",
578 "Auto",
579 NULL
580 };
581
582 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
583 "Off",
584 "1D Horizontal",
585 "1D Vertical",
586 "2D H/V Separable",
587 "2D Symmetric non-separable",
588 NULL
589 };
590
591 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
592 "Off",
593 "1D Horizontal",
594 NULL
595 };
596
597 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
598 "Manual",
599 "Auto",
600 NULL
601 };
602
603 static const char *cx2341x_video_median_filter_type_menu[] = {
604 "Off",
605 "Horizontal",
606 "Vertical",
607 "Horizontal/Vertical",
608 "Diagonal",
609 NULL
610 };
611
612 switch (id) {
613 case V4L2_CID_MPEG_STREAM_TYPE:
614 return mpeg_stream_type;
615 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
616 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
617 return NULL;
618 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
619 return cx2341x_video_spatial_filter_mode_menu;
620 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
621 return cx2341x_video_luma_spatial_filter_type_menu;
622 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
623 return cx2341x_video_chroma_spatial_filter_type_menu;
624 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
625 return cx2341x_video_temporal_filter_mode_menu;
626 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
627 return cx2341x_video_median_filter_type_menu;
628 default:
629 return v4l2_ctrl_get_menu(id);
630 }
631}
632
633static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
634{
635 params->audio_properties = (params->audio_sampling_freq << 0) |
636 ((3 - params->audio_encoding) << 2) |
637 ((1 + params->audio_l2_bitrate) << 4) |
638 (params->audio_mode << 8) |
639 (params->audio_mode_extension << 10) |
640 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
641 3 :
642 params->audio_emphasis) << 12) |
643 (params->audio_crc << 14);
644}
645
Hans Verkuil01f1e442007-08-21 18:32:42 -0300646int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300647 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300648{
649 int err = 0;
650 int i;
651
652 if (cmd == VIDIOC_G_EXT_CTRLS) {
653 for (i = 0; i < ctrls->count; i++) {
654 struct v4l2_ext_control *ctrl = ctrls->controls + i;
655
656 err = cx2341x_get_ctrl(params, ctrl);
657 if (err) {
658 ctrls->error_idx = i;
659 break;
660 }
661 }
662 return err;
663 }
664 for (i = 0; i < ctrls->count; i++) {
665 struct v4l2_ext_control *ctrl = ctrls->controls + i;
666 struct v4l2_queryctrl qctrl;
667 const char **menu_items = NULL;
668
669 qctrl.id = ctrl->id;
670 err = cx2341x_ctrl_query(params, &qctrl);
671 if (err)
672 break;
673 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
674 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
675 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
676 if (err)
677 break;
Hans Verkuil01f1e442007-08-21 18:32:42 -0300678 err = cx2341x_set_ctrl(params, busy, ctrl);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300679 if (err)
680 break;
681 }
682 if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
683 params->video_bitrate_peak < params->video_bitrate) {
684 err = -ERANGE;
685 ctrls->error_idx = ctrls->count;
686 }
687 if (err) {
688 ctrls->error_idx = i;
689 }
690 else {
691 cx2341x_calc_audio_properties(params);
692 }
693 return err;
694}
695
696void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
697{
698 static struct cx2341x_mpeg_params default_params = {
699 /* misc */
Hans Verkuil8cbde942006-06-24 14:36:02 -0300700 .capabilities = 0,
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300701 .port = CX2341X_PORT_MEMORY,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300702 .width = 720,
703 .height = 480,
704 .is_50hz = 0,
705
706 /* stream */
707 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
Hans Verkuil8cbde942006-06-24 14:36:02 -0300708 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300709 .stream_insert_nav_packets = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300710
711 /* audio */
712 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
713 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
714 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
715 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
716 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
717 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
718 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300719 .audio_mute = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300720
721 /* video */
722 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
723 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
724 .video_b_frames = 2,
725 .video_gop_size = 12,
726 .video_gop_closure = 1,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300727 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
728 .video_bitrate = 6000000,
729 .video_bitrate_peak = 8000000,
730 .video_temporal_decimation = 0,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300731 .video_mute = 0,
732 .video_mute_yuv = 0x008080, /* YCbCr value for black */
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300733
734 /* encoding filters */
735 .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
736 .video_spatial_filter = 0,
737 .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
738 .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
739 .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300740 .video_temporal_filter = 8,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300741 .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
742 .video_luma_median_filter_top = 255,
743 .video_luma_median_filter_bottom = 0,
744 .video_chroma_median_filter_top = 255,
745 .video_chroma_median_filter_bottom = 0,
746 };
747
748 *p = default_params;
749 cx2341x_calc_audio_properties(p);
750}
751
752static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
753{
754 u32 data[CX2341X_MBOX_MAX_DATA];
755 va_list vargs;
756 int i;
757
758 va_start(vargs, args);
759
760 for (i = 0; i < args; i++) {
761 data[i] = va_arg(vargs, int);
762 }
763 va_end(vargs);
764 return func(priv, cmd, args, 0, data);
765}
766
767int cx2341x_update(void *priv, cx2341x_mbox_func func,
768 const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
769{
770 static int mpeg_stream_type[] = {
771 0, /* MPEG-2 PS */
772 1, /* MPEG-2 TS */
773 2, /* MPEG-1 SS */
774 14, /* DVD */
775 11, /* VCD */
776 12, /* SVCD */
777 };
778
779 int err = 0;
Hans Verkuil44b579d2006-08-27 19:22:15 -0300780 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300781
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300782 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300783
784 if (old == NULL || old->is_50hz != new->is_50hz) {
785 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
786 if (err) return err;
787 }
788
789 if (old == NULL || old->width != new->width || old->height != new->height ||
790 old->video_encoding != new->video_encoding) {
791 u16 w = new->width;
792 u16 h = new->height;
793
794 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
795 w /= 2;
796 h /= 2;
797 }
798 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
799 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300800 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300801
Hans Verkuil12b896e2006-12-18 13:37:50 -0300802 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil44b579d2006-08-27 19:22:15 -0300803 /* Adjust temporal filter if necessary. The problem with the temporal
804 filter is that it works well with full resolution capturing, but
805 not when the capture window is scaled (the filter introduces
Hans Verkuil12b896e2006-12-18 13:37:50 -0300806 a ghosting effect). So if the capture window is scaled, then
807 force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300808
Hans Verkuil12b896e2006-12-18 13:37:50 -0300809 For full resolution the filter really improves the video
Hans Verkuil44b579d2006-08-27 19:22:15 -0300810 quality, especially if the original video quality is suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300811 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300812 }
813
814 if (old == NULL || old->stream_type != new->stream_type) {
815 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
816 if (err) return err;
817 }
818 if (old == NULL || old->video_aspect != new->video_aspect) {
819 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
820 if (err) return err;
821 }
822 if (old == NULL || old->video_b_frames != new->video_b_frames ||
823 old->video_gop_size != new->video_gop_size) {
824 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
825 new->video_gop_size, new->video_b_frames + 1);
826 if (err) return err;
827 }
828 if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
829 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
830 if (err) return err;
831 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300832 if (old == NULL || old->audio_properties != new->audio_properties) {
833 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
834 if (err) return err;
835 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300836 if (old == NULL || old->audio_mute != new->audio_mute) {
837 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, new->audio_mute);
838 if (err) return err;
839 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300840 if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
841 old->video_bitrate != new->video_bitrate ||
842 old->video_bitrate_peak != new->video_bitrate_peak) {
843 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
844 new->video_bitrate_mode, new->video_bitrate,
845 new->video_bitrate_peak / 400, 0, 0);
846 if (err) return err;
847 }
848 if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
849 old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
850 old->video_median_filter_type != new->video_median_filter_type) {
851 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
852 new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
853 new->video_median_filter_type);
854 if (err) return err;
855 }
856 if (old == NULL ||
857 old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
858 old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
859 old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
860 old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
861 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
862 new->video_luma_median_filter_bottom,
863 new->video_luma_median_filter_top,
864 new->video_chroma_median_filter_bottom,
865 new->video_chroma_median_filter_top);
866 if (err) return err;
867 }
868 if (old == NULL ||
869 old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
870 old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
871 err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
872 new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
873 if (err) return err;
874 }
875 if (old == NULL ||
876 old->video_spatial_filter != new->video_spatial_filter ||
Hans Verkuil44b579d2006-08-27 19:22:15 -0300877 old->video_temporal_filter != temporal) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300878 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300879 new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300880 if (err) return err;
881 }
882 if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
883 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
884 new->video_temporal_decimation);
885 if (err) return err;
886 }
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300887 if (old == NULL || old->video_mute != new->video_mute ||
888 (new->video_mute && old->video_mute_yuv != new->video_mute_yuv)) {
889 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, new->video_mute | (new->video_mute_yuv << 8));
890 if (err) return err;
891 }
892 if (old == NULL || old->stream_insert_nav_packets != new->stream_insert_nav_packets) {
893 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, 7, new->stream_insert_nav_packets);
894 if (err) return err;
895 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300896 return 0;
897}
898
899static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
900{
901 const char **menu = cx2341x_ctrl_get_menu(id);
902 struct v4l2_ext_control ctrl;
903
904 if (menu == NULL)
905 goto invalid;
906 ctrl.id = id;
907 if (cx2341x_get_ctrl(p, &ctrl))
908 goto invalid;
909 while (ctrl.value-- && *menu) menu++;
910 if (*menu == NULL)
911 goto invalid;
912 return *menu;
913
914invalid:
915 return "<invalid>";
916}
917
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300918void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300919{
920 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300921 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300922
923 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300924 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300925 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300926 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300927 if (p->stream_insert_nav_packets)
928 printk(" (with navigation packets)");
929 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300930 printk(KERN_INFO "%s: VBI Format: %s\n",
931 prefix,
932 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300933
934 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300935 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300936 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300937 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300938 p->is_50hz ? 25 : 30,
939 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300940 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
941 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300942 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
943 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
944 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
945 p->video_bitrate);
946 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
947 printk(", Peak %d", p->video_bitrate_peak);
948 }
949 printk("\n");
Hans Verkuil75558ab2006-12-18 22:52:21 -0300950 printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300951 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300952 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -0300953 p->video_gop_closure ? "" : "No ");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300954 if (p->video_temporal_decimation) {
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300955 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
956 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300957 }
958
959 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300960 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300961 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300962 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
963 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
964 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300965 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
966 p->audio_mute ? " (muted)" : "");
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300967 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
968 printk(", %s",
969 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
970 }
971 printk(", %s, %s\n",
972 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
973 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
974
975 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300976 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
977 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300978 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
979 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
980 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
981 p->video_spatial_filter);
Hans Verkuil83aaf132006-12-18 13:40:23 -0300982 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
983 temporal = 0;
984 }
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300985 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
986 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300987 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -0300988 temporal);
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300989 printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
990 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300991 cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
992 p->video_luma_median_filter_bottom,
993 p->video_luma_median_filter_top,
994 p->video_chroma_median_filter_bottom,
995 p->video_chroma_median_filter_top);
996}
997
998EXPORT_SYMBOL(cx2341x_fill_defaults);
999EXPORT_SYMBOL(cx2341x_ctrl_query);
1000EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
1001EXPORT_SYMBOL(cx2341x_ext_ctrls);
1002EXPORT_SYMBOL(cx2341x_update);
1003EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuilcc7bc642006-06-19 17:53:08 -03001004EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001005
1006/*
1007 * Local variables:
1008 * c-basic-offset: 8
1009 * End:
1010 */
1011