blob: 890c8867af1ce783a71d2e5c4957730236274696 [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
Hans Verkuil737bd412007-11-01 13:38:12 -030037static int debug;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030038module_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};
Hans Verkuil737bd412007-11-01 13:38:12 -030078EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
Hans Verkuilcc7bc642006-06-19 17:53:08 -030079
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -030080
81/* Map the control ID to the correct field in the cx2341x_mpeg_params
82 struct. Return -EINVAL if the ID is unknown, else return 0. */
83static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
84 struct v4l2_ext_control *ctrl)
85{
86 switch (ctrl->id) {
87 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
88 ctrl->value = params->audio_sampling_freq;
89 break;
90 case V4L2_CID_MPEG_AUDIO_ENCODING:
91 ctrl->value = params->audio_encoding;
92 break;
93 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
94 ctrl->value = params->audio_l2_bitrate;
95 break;
96 case V4L2_CID_MPEG_AUDIO_MODE:
97 ctrl->value = params->audio_mode;
98 break;
99 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
100 ctrl->value = params->audio_mode_extension;
101 break;
102 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
103 ctrl->value = params->audio_emphasis;
104 break;
105 case V4L2_CID_MPEG_AUDIO_CRC:
106 ctrl->value = params->audio_crc;
107 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300108 case V4L2_CID_MPEG_AUDIO_MUTE:
109 ctrl->value = params->audio_mute;
110 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300111 case V4L2_CID_MPEG_VIDEO_ENCODING:
112 ctrl->value = params->video_encoding;
113 break;
114 case V4L2_CID_MPEG_VIDEO_ASPECT:
115 ctrl->value = params->video_aspect;
116 break;
117 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
118 ctrl->value = params->video_b_frames;
119 break;
120 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
121 ctrl->value = params->video_gop_size;
122 break;
123 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
124 ctrl->value = params->video_gop_closure;
125 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300126 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
127 ctrl->value = params->video_bitrate_mode;
128 break;
129 case V4L2_CID_MPEG_VIDEO_BITRATE:
130 ctrl->value = params->video_bitrate;
131 break;
132 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
133 ctrl->value = params->video_bitrate_peak;
134 break;
135 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
136 ctrl->value = params->video_temporal_decimation;
137 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300138 case V4L2_CID_MPEG_VIDEO_MUTE:
139 ctrl->value = params->video_mute;
140 break;
141 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
142 ctrl->value = params->video_mute_yuv;
143 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300144 case V4L2_CID_MPEG_STREAM_TYPE:
145 ctrl->value = params->stream_type;
146 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300147 case V4L2_CID_MPEG_STREAM_VBI_FMT:
148 ctrl->value = params->stream_vbi_fmt;
149 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300150 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
151 ctrl->value = params->video_spatial_filter_mode;
152 break;
153 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
154 ctrl->value = params->video_spatial_filter;
155 break;
156 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
157 ctrl->value = params->video_luma_spatial_filter_type;
158 break;
159 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
160 ctrl->value = params->video_chroma_spatial_filter_type;
161 break;
162 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
163 ctrl->value = params->video_temporal_filter_mode;
164 break;
165 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
166 ctrl->value = params->video_temporal_filter;
167 break;
168 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
169 ctrl->value = params->video_median_filter_type;
170 break;
171 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
172 ctrl->value = params->video_luma_median_filter_top;
173 break;
174 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
175 ctrl->value = params->video_luma_median_filter_bottom;
176 break;
177 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
178 ctrl->value = params->video_chroma_median_filter_top;
179 break;
180 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
181 ctrl->value = params->video_chroma_median_filter_bottom;
182 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300183 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
184 ctrl->value = params->stream_insert_nav_packets;
185 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300186 default:
187 return -EINVAL;
188 }
189 return 0;
190}
191
192/* Map the control ID to the correct field in the cx2341x_mpeg_params
193 struct. Return -EINVAL if the ID is unknown, else return 0. */
Hans Verkuil01f1e442007-08-21 18:32:42 -0300194static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300195 struct v4l2_ext_control *ctrl)
196{
197 switch (ctrl->id) {
198 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300199 if (busy)
200 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300201 params->audio_sampling_freq = ctrl->value;
202 break;
203 case V4L2_CID_MPEG_AUDIO_ENCODING:
204 params->audio_encoding = ctrl->value;
205 break;
206 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300207 if (busy)
208 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300209 params->audio_l2_bitrate = ctrl->value;
210 break;
211 case V4L2_CID_MPEG_AUDIO_MODE:
212 params->audio_mode = ctrl->value;
213 break;
214 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
215 params->audio_mode_extension = ctrl->value;
216 break;
217 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
218 params->audio_emphasis = ctrl->value;
219 break;
220 case V4L2_CID_MPEG_AUDIO_CRC:
221 params->audio_crc = ctrl->value;
222 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300223 case V4L2_CID_MPEG_AUDIO_MUTE:
224 params->audio_mute = ctrl->value;
225 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300226 case V4L2_CID_MPEG_VIDEO_ASPECT:
227 params->video_aspect = ctrl->value;
228 break;
229 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
230 int b = ctrl->value + 1;
231 int gop = params->video_gop_size;
232 params->video_b_frames = ctrl->value;
233 params->video_gop_size = b * ((gop + b - 1) / b);
234 /* Max GOP size = 34 */
235 while (params->video_gop_size > 34)
236 params->video_gop_size -= b;
237 break;
238 }
239 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
240 int b = params->video_b_frames + 1;
241 int gop = ctrl->value;
242 params->video_gop_size = b * ((gop + b - 1) / b);
243 /* Max GOP size = 34 */
244 while (params->video_gop_size > 34)
245 params->video_gop_size -= b;
246 ctrl->value = params->video_gop_size;
247 break;
248 }
249 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
250 params->video_gop_closure = ctrl->value;
251 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300252 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300253 if (busy)
254 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300255 /* MPEG-1 only allows CBR */
256 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
257 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
258 return -EINVAL;
259 params->video_bitrate_mode = ctrl->value;
260 break;
261 case V4L2_CID_MPEG_VIDEO_BITRATE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300262 if (busy)
263 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300264 params->video_bitrate = ctrl->value;
265 break;
266 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300267 if (busy)
268 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300269 params->video_bitrate_peak = ctrl->value;
270 break;
271 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
272 params->video_temporal_decimation = ctrl->value;
273 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300274 case V4L2_CID_MPEG_VIDEO_MUTE:
275 params->video_mute = (ctrl->value != 0);
276 break;
277 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
278 params->video_mute_yuv = ctrl->value;
279 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300280 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuil01f1e442007-08-21 18:32:42 -0300281 if (busy)
282 return -EBUSY;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300283 params->stream_type = ctrl->value;
284 params->video_encoding =
Hans Verkuil737bd412007-11-01 13:38:12 -0300285 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
286 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
287 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
288 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
289 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300290 /* MPEG-1 implies CBR */
Hans Verkuil737bd412007-11-01 13:38:12 -0300291 params->video_bitrate_mode =
292 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300293 break;
Hans Verkuil8cbde942006-06-24 14:36:02 -0300294 case V4L2_CID_MPEG_STREAM_VBI_FMT:
295 params->stream_vbi_fmt = ctrl->value;
296 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300297 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
298 params->video_spatial_filter_mode = ctrl->value;
299 break;
300 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
301 params->video_spatial_filter = ctrl->value;
302 break;
303 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
304 params->video_luma_spatial_filter_type = ctrl->value;
305 break;
306 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
307 params->video_chroma_spatial_filter_type = ctrl->value;
308 break;
309 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
310 params->video_temporal_filter_mode = ctrl->value;
311 break;
312 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
313 params->video_temporal_filter = ctrl->value;
314 break;
315 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
316 params->video_median_filter_type = ctrl->value;
317 break;
318 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
319 params->video_luma_median_filter_top = ctrl->value;
320 break;
321 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
322 params->video_luma_median_filter_bottom = ctrl->value;
323 break;
324 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
325 params->video_chroma_median_filter_top = ctrl->value;
326 break;
327 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
328 params->video_chroma_median_filter_bottom = ctrl->value;
329 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300330 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
331 params->stream_insert_nav_packets = ctrl->value;
332 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300333 default:
334 return -EINVAL;
335 }
336 return 0;
337}
338
Hans Verkuil737bd412007-11-01 13:38:12 -0300339static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
340 s32 min, s32 max, s32 step, s32 def)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300341{
342 const char *name;
343
344 qctrl->flags = 0;
345 switch (qctrl->id) {
346 /* MPEG controls */
347 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
348 name = "Spatial Filter Mode";
349 break;
350 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
351 name = "Spatial Filter";
352 break;
353 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
354 name = "Spatial Luma Filter Type";
355 break;
356 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
357 name = "Spatial Chroma Filter Type";
358 break;
359 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
360 name = "Temporal Filter Mode";
361 break;
362 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
363 name = "Temporal Filter";
364 break;
365 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
366 name = "Median Filter Type";
367 break;
368 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
369 name = "Median Luma Filter Maximum";
370 break;
371 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
372 name = "Median Luma Filter Minimum";
373 break;
374 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
375 name = "Median Chroma Filter Maximum";
376 break;
377 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
378 name = "Median Chroma Filter Minimum";
379 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300380 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
381 name = "Insert Navigation Packets";
382 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300383
384 default:
385 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
386 }
387 switch (qctrl->id) {
388 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
389 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
390 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
391 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
392 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
393 qctrl->type = V4L2_CTRL_TYPE_MENU;
394 min = 0;
395 step = 1;
396 break;
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300397 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
398 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
399 min = 0;
400 max = 1;
401 step = 1;
402 break;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300403 default:
404 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
405 break;
406 }
407 switch (qctrl->id) {
408 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
409 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
410 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
411 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
412 break;
413 }
414 qctrl->minimum = min;
415 qctrl->maximum = max;
416 qctrl->step = step;
417 qctrl->default_value = def;
418 qctrl->reserved[0] = qctrl->reserved[1] = 0;
419 snprintf(qctrl->name, sizeof(qctrl->name), name);
420 return 0;
421}
422
Hans Verkuil737bd412007-11-01 13:38:12 -0300423int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
424 struct v4l2_queryctrl *qctrl)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300425{
426 int err;
427
428 switch (qctrl->id) {
429 case V4L2_CID_MPEG_AUDIO_ENCODING:
430 return v4l2_ctrl_query_fill(qctrl,
431 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
432 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
433 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
434
435 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436 return v4l2_ctrl_query_fill(qctrl,
437 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
438 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
439 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
440
441 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
442 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
443 return -EINVAL;
444
445 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
446 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300447 if (err == 0 &&
448 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300449 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
450 return err;
451
452 case V4L2_CID_MPEG_VIDEO_ENCODING:
453 /* this setting is read-only for the cx2341x since the
454 V4L2_CID_MPEG_STREAM_TYPE really determines the
455 MPEG-1/2 setting */
456 err = v4l2_ctrl_query_fill_std(qctrl);
457 if (err == 0)
458 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
459 return err;
460
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300461 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
462 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300463 if (err == 0 &&
464 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
Hans Verkuil54aa9a22006-06-19 18:00:06 -0300465 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
466 return err;
467
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300468 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
469 err = v4l2_ctrl_query_fill_std(qctrl);
Hans Verkuil737bd412007-11-01 13:38:12 -0300470 if (err == 0 &&
471 params->video_bitrate_mode ==
472 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300473 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
474 return err;
475
Hans Verkuil8cbde942006-06-24 14:36:02 -0300476 case V4L2_CID_MPEG_STREAM_VBI_FMT:
477 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
478 return v4l2_ctrl_query_fill_std(qctrl);
479 return cx2341x_ctrl_query_fill(qctrl,
480 V4L2_MPEG_STREAM_VBI_FMT_NONE,
481 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
482 V4L2_MPEG_STREAM_VBI_FMT_NONE);
483
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300484 /* CX23415/6 specific */
485 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
486 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300487 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
488 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
489 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300490
491 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
492 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
493 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300494 if (params->video_spatial_filter_mode ==
495 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
496 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300497 return 0;
498
499 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
500 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300501 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
502 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
503 1,
504 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
505 if (params->video_spatial_filter_mode ==
506 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
507 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300508 return 0;
509
510 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
511 cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300512 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
513 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
514 1,
515 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
516 if (params->video_spatial_filter_mode ==
517 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
518 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300519 return 0;
520
521 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
522 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300523 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
524 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
525 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300526
527 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
528 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
529 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300530 if (params->video_temporal_filter_mode ==
531 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
532 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300533 return 0;
534
535 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
536 return cx2341x_ctrl_query_fill(qctrl,
Hans Verkuil737bd412007-11-01 13:38:12 -0300537 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
538 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
539 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300540
541 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
542 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
543 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300544 if (params->video_median_filter_type ==
545 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
546 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300547 return 0;
548
549 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
550 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
551 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300552 if (params->video_median_filter_type ==
553 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
554 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300555 return 0;
556
557 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
558 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
559 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300560 if (params->video_median_filter_type ==
561 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
562 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300563 return 0;
564
565 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
566 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
567 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
Hans Verkuil737bd412007-11-01 13:38:12 -0300568 if (params->video_median_filter_type ==
569 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
570 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300571 return 0;
572
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300573 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
574 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
575
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300576 default:
577 return v4l2_ctrl_query_fill_std(qctrl);
578
579 }
580}
Hans Verkuil737bd412007-11-01 13:38:12 -0300581EXPORT_SYMBOL(cx2341x_ctrl_query);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300582
583const char **cx2341x_ctrl_get_menu(u32 id)
584{
585 static const char *mpeg_stream_type[] = {
586 "MPEG-2 Program Stream",
587 "",
588 "MPEG-1 System Stream",
589 "MPEG-2 DVD-compatible Stream",
590 "MPEG-1 VCD-compatible Stream",
591 "MPEG-2 SVCD-compatible Stream",
592 NULL
593 };
594
595 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
596 "Manual",
597 "Auto",
598 NULL
599 };
600
601 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
602 "Off",
603 "1D Horizontal",
604 "1D Vertical",
605 "2D H/V Separable",
606 "2D Symmetric non-separable",
607 NULL
608 };
609
610 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
611 "Off",
612 "1D Horizontal",
613 NULL
614 };
615
616 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
617 "Manual",
618 "Auto",
619 NULL
620 };
621
622 static const char *cx2341x_video_median_filter_type_menu[] = {
623 "Off",
624 "Horizontal",
625 "Vertical",
626 "Horizontal/Vertical",
627 "Diagonal",
628 NULL
629 };
630
631 switch (id) {
632 case V4L2_CID_MPEG_STREAM_TYPE:
633 return mpeg_stream_type;
634 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
635 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
636 return NULL;
637 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
638 return cx2341x_video_spatial_filter_mode_menu;
639 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
640 return cx2341x_video_luma_spatial_filter_type_menu;
641 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
642 return cx2341x_video_chroma_spatial_filter_type_menu;
643 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
644 return cx2341x_video_temporal_filter_mode_menu;
645 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
646 return cx2341x_video_median_filter_type_menu;
647 default:
648 return v4l2_ctrl_get_menu(id);
649 }
650}
Hans Verkuil737bd412007-11-01 13:38:12 -0300651EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300652
653static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
654{
655 params->audio_properties = (params->audio_sampling_freq << 0) |
656 ((3 - params->audio_encoding) << 2) |
657 ((1 + params->audio_l2_bitrate) << 4) |
658 (params->audio_mode << 8) |
659 (params->audio_mode_extension << 10) |
Hans Verkuil737bd412007-11-01 13:38:12 -0300660 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
661 ? 3 : params->audio_emphasis) << 12) |
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300662 (params->audio_crc << 14);
663}
664
Hans Verkuil01f1e442007-08-21 18:32:42 -0300665int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300666 struct v4l2_ext_controls *ctrls, unsigned int cmd)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300667{
668 int err = 0;
669 int i;
670
671 if (cmd == VIDIOC_G_EXT_CTRLS) {
672 for (i = 0; i < ctrls->count; i++) {
673 struct v4l2_ext_control *ctrl = ctrls->controls + i;
674
675 err = cx2341x_get_ctrl(params, ctrl);
676 if (err) {
677 ctrls->error_idx = i;
678 break;
679 }
680 }
681 return err;
682 }
683 for (i = 0; i < ctrls->count; i++) {
684 struct v4l2_ext_control *ctrl = ctrls->controls + i;
685 struct v4l2_queryctrl qctrl;
686 const char **menu_items = NULL;
687
688 qctrl.id = ctrl->id;
689 err = cx2341x_ctrl_query(params, &qctrl);
690 if (err)
691 break;
692 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
693 menu_items = cx2341x_ctrl_get_menu(qctrl.id);
694 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
695 if (err)
696 break;
Hans Verkuil01f1e442007-08-21 18:32:42 -0300697 err = cx2341x_set_ctrl(params, busy, ctrl);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300698 if (err)
699 break;
700 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300701 if (err == 0 &&
702 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
703 params->video_bitrate_peak < params->video_bitrate) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300704 err = -ERANGE;
705 ctrls->error_idx = ctrls->count;
706 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300707 if (err)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300708 ctrls->error_idx = i;
Hans Verkuil737bd412007-11-01 13:38:12 -0300709 else
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300710 cx2341x_calc_audio_properties(params);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300711 return err;
712}
Hans Verkuil737bd412007-11-01 13:38:12 -0300713EXPORT_SYMBOL(cx2341x_ext_ctrls);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300714
715void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
716{
717 static struct cx2341x_mpeg_params default_params = {
718 /* misc */
Hans Verkuil8cbde942006-06-24 14:36:02 -0300719 .capabilities = 0,
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300720 .port = CX2341X_PORT_MEMORY,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300721 .width = 720,
722 .height = 480,
723 .is_50hz = 0,
724
725 /* stream */
726 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
Hans Verkuil8cbde942006-06-24 14:36:02 -0300727 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300728 .stream_insert_nav_packets = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300729
730 /* audio */
731 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
732 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
733 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
734 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
735 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
736 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
737 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300738 .audio_mute = 0,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300739
740 /* video */
741 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
742 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
743 .video_b_frames = 2,
744 .video_gop_size = 12,
745 .video_gop_closure = 1,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300746 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
747 .video_bitrate = 6000000,
748 .video_bitrate_peak = 8000000,
749 .video_temporal_decimation = 0,
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300750 .video_mute = 0,
751 .video_mute_yuv = 0x008080, /* YCbCr value for black */
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300752
753 /* encoding filters */
Hans Verkuil737bd412007-11-01 13:38:12 -0300754 .video_spatial_filter_mode =
755 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300756 .video_spatial_filter = 0,
Hans Verkuil737bd412007-11-01 13:38:12 -0300757 .video_luma_spatial_filter_type =
758 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
759 .video_chroma_spatial_filter_type =
760 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
761 .video_temporal_filter_mode =
762 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
Hans Verkuil44b579d2006-08-27 19:22:15 -0300763 .video_temporal_filter = 8,
Hans Verkuil737bd412007-11-01 13:38:12 -0300764 .video_median_filter_type =
765 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300766 .video_luma_median_filter_top = 255,
767 .video_luma_median_filter_bottom = 0,
768 .video_chroma_median_filter_top = 255,
769 .video_chroma_median_filter_bottom = 0,
770 };
771
772 *p = default_params;
773 cx2341x_calc_audio_properties(p);
774}
Hans Verkuil737bd412007-11-01 13:38:12 -0300775EXPORT_SYMBOL(cx2341x_fill_defaults);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300776
Hans Verkuil737bd412007-11-01 13:38:12 -0300777static int cx2341x_api(void *priv, cx2341x_mbox_func func,
778 int cmd, int args, ...)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300779{
780 u32 data[CX2341X_MBOX_MAX_DATA];
781 va_list vargs;
782 int i;
783
784 va_start(vargs, args);
785
Hans Verkuil737bd412007-11-01 13:38:12 -0300786 for (i = 0; i < args; i++)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300787 data[i] = va_arg(vargs, int);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300788 va_end(vargs);
789 return func(priv, cmd, args, 0, data);
790}
791
Hans Verkuil737bd412007-11-01 13:38:12 -0300792#define NEQ(field) (old->field != new->field)
793
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300794int cx2341x_update(void *priv, cx2341x_mbox_func func,
Hans Verkuil737bd412007-11-01 13:38:12 -0300795 const struct cx2341x_mpeg_params *old,
796 const struct cx2341x_mpeg_params *new)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300797{
798 static int mpeg_stream_type[] = {
799 0, /* MPEG-2 PS */
800 1, /* MPEG-2 TS */
801 2, /* MPEG-1 SS */
802 14, /* DVD */
803 11, /* VCD */
804 12, /* SVCD */
805 };
806
807 int err = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -0300808 int force = (old == NULL);
Hans Verkuil44b579d2006-08-27 19:22:15 -0300809 u16 temporal = new->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300810
Hans Verkuil45ad9f82006-06-21 17:04:13 -0300811 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300812
Hans Verkuil737bd412007-11-01 13:38:12 -0300813 if (force || NEQ(is_50hz)) {
814 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
815 new->is_50hz);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300816 if (err) return err;
817 }
818
Hans Verkuil737bd412007-11-01 13:38:12 -0300819 if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300820 u16 w = new->width;
821 u16 h = new->height;
822
823 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
824 w /= 2;
825 h /= 2;
826 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300827 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
828 h, w);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300829 if (err) return err;
Hans Verkuil12b896e2006-12-18 13:37:50 -0300830 }
Hans Verkuil44b579d2006-08-27 19:22:15 -0300831
Hans Verkuil12b896e2006-12-18 13:37:50 -0300832 if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
Hans Verkuil737bd412007-11-01 13:38:12 -0300833 /* Adjust temporal filter if necessary. The problem with the
834 temporal filter is that it works well with full resolution
835 capturing, but not when the capture window is scaled (the
836 filter introduces a ghosting effect). So if the capture
837 window is scaled, then force the filter to 0.
Hans Verkuil44b579d2006-08-27 19:22:15 -0300838
Hans Verkuil12b896e2006-12-18 13:37:50 -0300839 For full resolution the filter really improves the video
Hans Verkuil737bd412007-11-01 13:38:12 -0300840 quality, especially if the original video quality is
841 suboptimal. */
Hans Verkuil12b896e2006-12-18 13:37:50 -0300842 temporal = 0;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300843 }
844
Hans Verkuil737bd412007-11-01 13:38:12 -0300845 if (force || NEQ(stream_type)) {
846 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
847 mpeg_stream_type[new->stream_type]);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300848 if (err) return err;
849 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300850 if (force || NEQ(video_aspect)) {
851 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
852 1 + new->video_aspect);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300853 if (err) return err;
854 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300855 if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300856 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
857 new->video_gop_size, new->video_b_frames + 1);
858 if (err) return err;
859 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300860 if (force || NEQ(video_gop_closure)) {
861 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
862 new->video_gop_closure);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300863 if (err) return err;
864 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300865 if (force || NEQ(audio_properties)) {
866 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
867 1, new->audio_properties);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300868 if (err) return err;
869 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300870 if (force || NEQ(audio_mute)) {
871 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
872 new->audio_mute);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300873 if (err) return err;
874 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300875 if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
876 NEQ(video_bitrate_peak)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300877 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
878 new->video_bitrate_mode, new->video_bitrate,
879 new->video_bitrate_peak / 400, 0, 0);
880 if (err) return err;
881 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300882 if (force || NEQ(video_spatial_filter_mode) ||
883 NEQ(video_temporal_filter_mode) ||
884 NEQ(video_median_filter_type)) {
885 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
886 2, new->video_spatial_filter_mode |
887 (new->video_temporal_filter_mode << 1),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300888 new->video_median_filter_type);
889 if (err) return err;
890 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300891 if (force || NEQ(video_luma_median_filter_bottom) ||
892 NEQ(video_luma_median_filter_top) ||
893 NEQ(video_chroma_median_filter_bottom) ||
894 NEQ(video_chroma_median_filter_top)) {
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300895 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
896 new->video_luma_median_filter_bottom,
897 new->video_luma_median_filter_top,
898 new->video_chroma_median_filter_bottom,
899 new->video_chroma_median_filter_top);
900 if (err) return err;
901 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300902 if (force || NEQ(video_luma_spatial_filter_type) ||
903 NEQ(video_chroma_spatial_filter_type)) {
904 err = cx2341x_api(priv, func,
905 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
906 2, new->video_luma_spatial_filter_type,
907 new->video_chroma_spatial_filter_type);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300908 if (err) return err;
909 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300910 if (force || NEQ(video_spatial_filter) ||
911 old->video_temporal_filter != temporal) {
912 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
913 2, new->video_spatial_filter, temporal);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300914 if (err) return err;
915 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300916 if (force || NEQ(video_temporal_decimation)) {
917 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
918 1, new->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300919 if (err) return err;
920 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300921 if (force || NEQ(video_mute) ||
922 (new->video_mute && NEQ(video_mute_yuv))) {
923 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
924 new->video_mute | (new->video_mute_yuv << 8));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300925 if (err) return err;
926 }
Hans Verkuil737bd412007-11-01 13:38:12 -0300927 if (force || NEQ(stream_insert_nav_packets)) {
928 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
929 7, new->stream_insert_nav_packets);
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300930 if (err) return err;
931 }
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300932 return 0;
933}
Hans Verkuil737bd412007-11-01 13:38:12 -0300934EXPORT_SYMBOL(cx2341x_update);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300935
936static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
937{
938 const char **menu = cx2341x_ctrl_get_menu(id);
939 struct v4l2_ext_control ctrl;
940
941 if (menu == NULL)
942 goto invalid;
943 ctrl.id = id;
944 if (cx2341x_get_ctrl(p, &ctrl))
945 goto invalid;
946 while (ctrl.value-- && *menu) menu++;
947 if (*menu == NULL)
948 goto invalid;
949 return *menu;
950
951invalid:
952 return "<invalid>";
953}
954
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300955void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300956{
957 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
Hans Verkuil83aaf132006-12-18 13:40:23 -0300958 int temporal = p->video_temporal_filter;
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300959
960 /* Stream */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300961 printk(KERN_INFO "%s: Stream: %s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300962 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300963 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300964 if (p->stream_insert_nav_packets)
965 printk(" (with navigation packets)");
966 printk("\n");
Hans Verkuil44b579d2006-08-27 19:22:15 -0300967 printk(KERN_INFO "%s: VBI Format: %s\n",
968 prefix,
969 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300970
971 /* Video */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300972 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300973 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300974 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300975 p->is_50hz ? 25 : 30,
976 (p->video_mute) ? " (muted)" : "");
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300977 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",
978 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300979 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
980 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
981 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
982 p->video_bitrate);
Hans Verkuil737bd412007-11-01 13:38:12 -0300983 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300984 printk(", Peak %d", p->video_bitrate_peak);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300985 printk("\n");
Hans Verkuil737bd412007-11-01 13:38:12 -0300986 printk(KERN_INFO
987 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300988 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300989 p->video_gop_size, p->video_b_frames,
Hans Verkuil75558ab2006-12-18 22:52:21 -0300990 p->video_gop_closure ? "" : "No ");
Hans Verkuil737bd412007-11-01 13:38:12 -0300991 if (p->video_temporal_decimation)
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300992 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
993 prefix, p->video_temporal_decimation);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300994
995 /* Audio */
Hans Verkuil5eee72e2007-04-27 12:31:00 -0300996 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",
Hans Verkuil99eb44f2006-06-26 18:24:05 -0300997 prefix,
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -0300998 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
999 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1000 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
Hans Verkuil5eee72e2007-04-27 12:31:00 -03001001 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1002 p->audio_mute ? " (muted)" : "");
Hans Verkuil737bd412007-11-01 13:38:12 -03001003 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1004 printk(", %s", cx2341x_menu_item(p,
1005 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001006 printk(", %s, %s\n",
1007 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1008 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1009
1010 /* Encoding filters */
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001011 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",
1012 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001013 cx2341x_menu_item(p,
1014 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1015 cx2341x_menu_item(p,
1016 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1017 cx2341x_menu_item(p,
1018 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001019 p->video_spatial_filter);
Hans Verkuil737bd412007-11-01 13:38:12 -03001020
1021 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
Hans Verkuil83aaf132006-12-18 13:40:23 -03001022 temporal = 0;
Hans Verkuil737bd412007-11-01 13:38:12 -03001023
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001024 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1025 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001026 cx2341x_menu_item(p,
1027 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
Hans Verkuil83aaf132006-12-18 13:40:23 -03001028 temporal);
Hans Verkuil737bd412007-11-01 13:38:12 -03001029 printk(KERN_INFO
1030 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
Hans Verkuil99eb44f2006-06-26 18:24:05 -03001031 prefix,
Hans Verkuil737bd412007-11-01 13:38:12 -03001032 cx2341x_menu_item(p,
1033 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001034 p->video_luma_median_filter_bottom,
1035 p->video_luma_median_filter_top,
1036 p->video_chroma_median_filter_bottom,
1037 p->video_chroma_median_filter_top);
1038}
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001039EXPORT_SYMBOL(cx2341x_log_status);
Hans Verkuil5d1a9ae2006-06-18 14:40:30 -03001040
1041/*
1042 * Local variables:
1043 * c-basic-offset: 8
1044 * End:
1045 */
1046