1779 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * cx2341x - generic code for cx23415/6/8 based devices4 *5 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>6 */7 8 9#include <linux/module.h>10#include <linux/errno.h>11#include <linux/kernel.h>12#include <linux/init.h>13#include <linux/types.h>14#include <linux/videodev2.h>15 16#include <media/tuner.h>17#include <media/drv-intf/cx2341x.h>18#include <media/v4l2-common.h>19 20MODULE_DESCRIPTION("cx23415/6/8 driver");21MODULE_AUTHOR("Hans Verkuil");22MODULE_LICENSE("GPL");23 24static int debug;25module_param(debug, int, 0644);26MODULE_PARM_DESC(debug, "Debug level (0-1)");27 28/********************** COMMON CODE *********************/29 30/* definitions for audio properties bits 29-28 */31#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 032#define CX2341X_AUDIO_ENCODING_METHOD_AC3 133#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 234 35static const char *cx2341x_get_name(u32 id)36{37 switch (id) {38 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:39 return "Spatial Filter Mode";40 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:41 return "Spatial Filter";42 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:43 return "Spatial Luma Filter Type";44 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:45 return "Spatial Chroma Filter Type";46 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:47 return "Temporal Filter Mode";48 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:49 return "Temporal Filter";50 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:51 return "Median Filter Type";52 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:53 return "Median Luma Filter Maximum";54 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:55 return "Median Luma Filter Minimum";56 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:57 return "Median Chroma Filter Maximum";58 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:59 return "Median Chroma Filter Minimum";60 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:61 return "Insert Navigation Packets";62 }63 return NULL;64}65 66static const char **cx2341x_get_menu(u32 id)67{68 static const char *cx2341x_video_spatial_filter_mode_menu[] = {69 "Manual",70 "Auto",71 NULL72 };73 74 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {75 "Off",76 "1D Horizontal",77 "1D Vertical",78 "2D H/V Separable",79 "2D Symmetric non-separable",80 NULL81 };82 83 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {84 "Off",85 "1D Horizontal",86 NULL87 };88 89 static const char *cx2341x_video_temporal_filter_mode_menu[] = {90 "Manual",91 "Auto",92 NULL93 };94 95 static const char *cx2341x_video_median_filter_type_menu[] = {96 "Off",97 "Horizontal",98 "Vertical",99 "Horizontal/Vertical",100 "Diagonal",101 NULL102 };103 104 switch (id) {105 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:106 return cx2341x_video_spatial_filter_mode_menu;107 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:108 return cx2341x_video_luma_spatial_filter_type_menu;109 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:110 return cx2341x_video_chroma_spatial_filter_type_menu;111 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:112 return cx2341x_video_temporal_filter_mode_menu;113 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:114 return cx2341x_video_median_filter_type_menu;115 }116 return NULL;117}118 119static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,120 s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)121{122 *name = cx2341x_get_name(id);123 *flags = 0;124 125 switch (id) {126 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:127 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:128 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:129 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:130 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:131 *type = V4L2_CTRL_TYPE_MENU;132 *min = 0;133 *step = 0;134 break;135 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:136 *type = V4L2_CTRL_TYPE_BOOLEAN;137 *min = 0;138 *max = *step = 1;139 break;140 default:141 *type = V4L2_CTRL_TYPE_INTEGER;142 break;143 }144 switch (id) {145 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:146 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:147 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:148 *flags |= V4L2_CTRL_FLAG_UPDATE;149 break;150 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:151 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:152 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:153 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:154 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:155 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:156 *flags |= V4L2_CTRL_FLAG_SLIDER;157 break;158 case V4L2_CID_MPEG_VIDEO_ENCODING:159 *flags |= V4L2_CTRL_FLAG_READ_ONLY;160 break;161 }162}163 164 165/********************** OLD CODE *********************/166 167/* Must be sorted from low to high control ID! */168const u32 cx2341x_mpeg_ctrls[] = {169 V4L2_CID_CODEC_CLASS,170 V4L2_CID_MPEG_STREAM_TYPE,171 V4L2_CID_MPEG_STREAM_VBI_FMT,172 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,173 V4L2_CID_MPEG_AUDIO_ENCODING,174 V4L2_CID_MPEG_AUDIO_L2_BITRATE,175 V4L2_CID_MPEG_AUDIO_MODE,176 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,177 V4L2_CID_MPEG_AUDIO_EMPHASIS,178 V4L2_CID_MPEG_AUDIO_CRC,179 V4L2_CID_MPEG_AUDIO_MUTE,180 V4L2_CID_MPEG_AUDIO_AC3_BITRATE,181 V4L2_CID_MPEG_VIDEO_ENCODING,182 V4L2_CID_MPEG_VIDEO_ASPECT,183 V4L2_CID_MPEG_VIDEO_B_FRAMES,184 V4L2_CID_MPEG_VIDEO_GOP_SIZE,185 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,186 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,187 V4L2_CID_MPEG_VIDEO_BITRATE,188 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,189 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,190 V4L2_CID_MPEG_VIDEO_MUTE,191 V4L2_CID_MPEG_VIDEO_MUTE_YUV,192 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,193 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,194 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,195 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,196 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,197 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,198 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,199 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,200 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,201 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,202 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,203 V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,204 0205};206EXPORT_SYMBOL(cx2341x_mpeg_ctrls);207 208static const struct cx2341x_mpeg_params default_params = {209 /* misc */210 .capabilities = 0,211 .port = CX2341X_PORT_MEMORY,212 .width = 720,213 .height = 480,214 .is_50hz = 0,215 216 /* stream */217 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,218 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,219 .stream_insert_nav_packets = 0,220 221 /* audio */222 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,223 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,224 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,225 .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,226 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,227 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,228 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,229 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,230 .audio_mute = 0,231 232 /* video */233 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,234 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,235 .video_b_frames = 2,236 .video_gop_size = 12,237 .video_gop_closure = 1,238 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,239 .video_bitrate = 6000000,240 .video_bitrate_peak = 8000000,241 .video_temporal_decimation = 0,242 .video_mute = 0,243 .video_mute_yuv = 0x008080, /* YCbCr value for black */244 245 /* encoding filters */246 .video_spatial_filter_mode =247 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,248 .video_spatial_filter = 0,249 .video_luma_spatial_filter_type =250 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,251 .video_chroma_spatial_filter_type =252 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,253 .video_temporal_filter_mode =254 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,255 .video_temporal_filter = 8,256 .video_median_filter_type =257 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,258 .video_luma_median_filter_top = 255,259 .video_luma_median_filter_bottom = 0,260 .video_chroma_median_filter_top = 255,261 .video_chroma_median_filter_bottom = 0,262};263/* Map the control ID to the correct field in the cx2341x_mpeg_params264 struct. Return -EINVAL if the ID is unknown, else return 0. */265static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,266 struct v4l2_ext_control *ctrl)267{268 switch (ctrl->id) {269 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:270 ctrl->value = params->audio_sampling_freq;271 break;272 case V4L2_CID_MPEG_AUDIO_ENCODING:273 ctrl->value = params->audio_encoding;274 break;275 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:276 ctrl->value = params->audio_l2_bitrate;277 break;278 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:279 ctrl->value = params->audio_ac3_bitrate;280 break;281 case V4L2_CID_MPEG_AUDIO_MODE:282 ctrl->value = params->audio_mode;283 break;284 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:285 ctrl->value = params->audio_mode_extension;286 break;287 case V4L2_CID_MPEG_AUDIO_EMPHASIS:288 ctrl->value = params->audio_emphasis;289 break;290 case V4L2_CID_MPEG_AUDIO_CRC:291 ctrl->value = params->audio_crc;292 break;293 case V4L2_CID_MPEG_AUDIO_MUTE:294 ctrl->value = params->audio_mute;295 break;296 case V4L2_CID_MPEG_VIDEO_ENCODING:297 ctrl->value = params->video_encoding;298 break;299 case V4L2_CID_MPEG_VIDEO_ASPECT:300 ctrl->value = params->video_aspect;301 break;302 case V4L2_CID_MPEG_VIDEO_B_FRAMES:303 ctrl->value = params->video_b_frames;304 break;305 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:306 ctrl->value = params->video_gop_size;307 break;308 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:309 ctrl->value = params->video_gop_closure;310 break;311 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:312 ctrl->value = params->video_bitrate_mode;313 break;314 case V4L2_CID_MPEG_VIDEO_BITRATE:315 ctrl->value = params->video_bitrate;316 break;317 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:318 ctrl->value = params->video_bitrate_peak;319 break;320 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:321 ctrl->value = params->video_temporal_decimation;322 break;323 case V4L2_CID_MPEG_VIDEO_MUTE:324 ctrl->value = params->video_mute;325 break;326 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:327 ctrl->value = params->video_mute_yuv;328 break;329 case V4L2_CID_MPEG_STREAM_TYPE:330 ctrl->value = params->stream_type;331 break;332 case V4L2_CID_MPEG_STREAM_VBI_FMT:333 ctrl->value = params->stream_vbi_fmt;334 break;335 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:336 ctrl->value = params->video_spatial_filter_mode;337 break;338 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:339 ctrl->value = params->video_spatial_filter;340 break;341 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:342 ctrl->value = params->video_luma_spatial_filter_type;343 break;344 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:345 ctrl->value = params->video_chroma_spatial_filter_type;346 break;347 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:348 ctrl->value = params->video_temporal_filter_mode;349 break;350 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:351 ctrl->value = params->video_temporal_filter;352 break;353 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:354 ctrl->value = params->video_median_filter_type;355 break;356 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:357 ctrl->value = params->video_luma_median_filter_top;358 break;359 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:360 ctrl->value = params->video_luma_median_filter_bottom;361 break;362 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:363 ctrl->value = params->video_chroma_median_filter_top;364 break;365 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:366 ctrl->value = params->video_chroma_median_filter_bottom;367 break;368 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:369 ctrl->value = params->stream_insert_nav_packets;370 break;371 default:372 return -EINVAL;373 }374 return 0;375}376 377/* Map the control ID to the correct field in the cx2341x_mpeg_params378 struct. Return -EINVAL if the ID is unknown, else return 0. */379static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,380 struct v4l2_ext_control *ctrl)381{382 switch (ctrl->id) {383 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:384 if (busy)385 return -EBUSY;386 params->audio_sampling_freq = ctrl->value;387 break;388 case V4L2_CID_MPEG_AUDIO_ENCODING:389 if (busy)390 return -EBUSY;391 if (params->capabilities & CX2341X_CAP_HAS_AC3)392 if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&393 ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)394 return -ERANGE;395 params->audio_encoding = ctrl->value;396 break;397 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:398 if (busy)399 return -EBUSY;400 params->audio_l2_bitrate = ctrl->value;401 break;402 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:403 if (busy)404 return -EBUSY;405 if (!(params->capabilities & CX2341X_CAP_HAS_AC3))406 return -EINVAL;407 params->audio_ac3_bitrate = ctrl->value;408 break;409 case V4L2_CID_MPEG_AUDIO_MODE:410 params->audio_mode = ctrl->value;411 break;412 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:413 params->audio_mode_extension = ctrl->value;414 break;415 case V4L2_CID_MPEG_AUDIO_EMPHASIS:416 params->audio_emphasis = ctrl->value;417 break;418 case V4L2_CID_MPEG_AUDIO_CRC:419 params->audio_crc = ctrl->value;420 break;421 case V4L2_CID_MPEG_AUDIO_MUTE:422 params->audio_mute = ctrl->value;423 break;424 case V4L2_CID_MPEG_VIDEO_ASPECT:425 params->video_aspect = ctrl->value;426 break;427 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {428 int b = ctrl->value + 1;429 int gop = params->video_gop_size;430 params->video_b_frames = ctrl->value;431 params->video_gop_size = b * ((gop + b - 1) / b);432 /* Max GOP size = 34 */433 while (params->video_gop_size > 34)434 params->video_gop_size -= b;435 break;436 }437 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {438 int b = params->video_b_frames + 1;439 int gop = ctrl->value;440 params->video_gop_size = b * ((gop + b - 1) / b);441 /* Max GOP size = 34 */442 while (params->video_gop_size > 34)443 params->video_gop_size -= b;444 ctrl->value = params->video_gop_size;445 break;446 }447 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:448 params->video_gop_closure = ctrl->value;449 break;450 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:451 if (busy)452 return -EBUSY;453 /* MPEG-1 only allows CBR */454 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&455 ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)456 return -EINVAL;457 params->video_bitrate_mode = ctrl->value;458 break;459 case V4L2_CID_MPEG_VIDEO_BITRATE:460 if (busy)461 return -EBUSY;462 params->video_bitrate = ctrl->value;463 break;464 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:465 if (busy)466 return -EBUSY;467 params->video_bitrate_peak = ctrl->value;468 break;469 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:470 params->video_temporal_decimation = ctrl->value;471 break;472 case V4L2_CID_MPEG_VIDEO_MUTE:473 params->video_mute = (ctrl->value != 0);474 break;475 case V4L2_CID_MPEG_VIDEO_MUTE_YUV:476 params->video_mute_yuv = ctrl->value;477 break;478 case V4L2_CID_MPEG_STREAM_TYPE:479 if (busy)480 return -EBUSY;481 params->stream_type = ctrl->value;482 params->video_encoding =483 (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||484 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?485 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :486 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;487 if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)488 /* MPEG-1 implies CBR */489 params->video_bitrate_mode =490 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;491 break;492 case V4L2_CID_MPEG_STREAM_VBI_FMT:493 params->stream_vbi_fmt = ctrl->value;494 break;495 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:496 params->video_spatial_filter_mode = ctrl->value;497 break;498 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:499 params->video_spatial_filter = ctrl->value;500 break;501 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:502 params->video_luma_spatial_filter_type = ctrl->value;503 break;504 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:505 params->video_chroma_spatial_filter_type = ctrl->value;506 break;507 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:508 params->video_temporal_filter_mode = ctrl->value;509 break;510 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:511 params->video_temporal_filter = ctrl->value;512 break;513 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:514 params->video_median_filter_type = ctrl->value;515 break;516 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:517 params->video_luma_median_filter_top = ctrl->value;518 break;519 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:520 params->video_luma_median_filter_bottom = ctrl->value;521 break;522 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:523 params->video_chroma_median_filter_top = ctrl->value;524 break;525 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:526 params->video_chroma_median_filter_bottom = ctrl->value;527 break;528 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:529 params->stream_insert_nav_packets = ctrl->value;530 break;531 default:532 return -EINVAL;533 }534 return 0;535}536 537static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,538 s32 min, s32 max, s32 step, s32 def)539{540 const char *name;541 542 switch (qctrl->id) {543 /* MPEG controls */544 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:545 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:546 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:547 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:548 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:549 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:550 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:551 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:552 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:553 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:554 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:555 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:556 cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type,557 &min, &max, &step, &def, &qctrl->flags);558 qctrl->minimum = min;559 qctrl->maximum = max;560 qctrl->step = step;561 qctrl->default_value = def;562 qctrl->reserved[0] = qctrl->reserved[1] = 0;563 strscpy(qctrl->name, name, sizeof(qctrl->name));564 return 0;565 566 default:567 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);568 }569}570 571int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,572 struct v4l2_queryctrl *qctrl)573{574 int err;575 576 switch (qctrl->id) {577 case V4L2_CID_CODEC_CLASS:578 return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);579 case V4L2_CID_MPEG_STREAM_TYPE:580 return v4l2_ctrl_query_fill(qctrl,581 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,582 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,583 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);584 585 case V4L2_CID_MPEG_STREAM_VBI_FMT:586 if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)587 return v4l2_ctrl_query_fill(qctrl,588 V4L2_MPEG_STREAM_VBI_FMT_NONE,589 V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,590 V4L2_MPEG_STREAM_VBI_FMT_NONE);591 return cx2341x_ctrl_query_fill(qctrl,592 V4L2_MPEG_STREAM_VBI_FMT_NONE,593 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,594 default_params.stream_vbi_fmt);595 596 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:597 return v4l2_ctrl_query_fill(qctrl,598 V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,599 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,600 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);601 602 case V4L2_CID_MPEG_AUDIO_ENCODING:603 if (params->capabilities & CX2341X_CAP_HAS_AC3) {604 /*605 * The state of L2 & AC3 bitrate controls can change606 * when this control changes, but v4l2_ctrl_query_fill()607 * already sets V4L2_CTRL_FLAG_UPDATE for608 * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.609 */610 return v4l2_ctrl_query_fill(qctrl,611 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,612 V4L2_MPEG_AUDIO_ENCODING_AC3, 1,613 default_params.audio_encoding);614 }615 616 return v4l2_ctrl_query_fill(qctrl,617 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,618 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,619 default_params.audio_encoding);620 621 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:622 err = v4l2_ctrl_query_fill(qctrl,623 V4L2_MPEG_AUDIO_L2_BITRATE_192K,624 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,625 default_params.audio_l2_bitrate);626 if (err)627 return err;628 if (params->capabilities & CX2341X_CAP_HAS_AC3 &&629 params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)630 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;631 return 0;632 633 case V4L2_CID_MPEG_AUDIO_MODE:634 return v4l2_ctrl_query_fill(qctrl,635 V4L2_MPEG_AUDIO_MODE_STEREO,636 V4L2_MPEG_AUDIO_MODE_MONO, 1,637 V4L2_MPEG_AUDIO_MODE_STEREO);638 639 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:640 err = v4l2_ctrl_query_fill(qctrl,641 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,642 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,643 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);644 if (err == 0 &&645 params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)646 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;647 return err;648 649 case V4L2_CID_MPEG_AUDIO_EMPHASIS:650 return v4l2_ctrl_query_fill(qctrl,651 V4L2_MPEG_AUDIO_EMPHASIS_NONE,652 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,653 V4L2_MPEG_AUDIO_EMPHASIS_NONE);654 655 case V4L2_CID_MPEG_AUDIO_CRC:656 return v4l2_ctrl_query_fill(qctrl,657 V4L2_MPEG_AUDIO_CRC_NONE,658 V4L2_MPEG_AUDIO_CRC_CRC16, 1,659 V4L2_MPEG_AUDIO_CRC_NONE);660 661 case V4L2_CID_MPEG_AUDIO_MUTE:662 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);663 664 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:665 err = v4l2_ctrl_query_fill(qctrl,666 V4L2_MPEG_AUDIO_AC3_BITRATE_48K,667 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,668 default_params.audio_ac3_bitrate);669 if (err)670 return err;671 if (params->capabilities & CX2341X_CAP_HAS_AC3) {672 if (params->audio_encoding !=673 V4L2_MPEG_AUDIO_ENCODING_AC3)674 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;675 } else676 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;677 return 0;678 679 case V4L2_CID_MPEG_VIDEO_ENCODING:680 /* this setting is read-only for the cx2341x since the681 V4L2_CID_MPEG_STREAM_TYPE really determines the682 MPEG-1/2 setting */683 err = v4l2_ctrl_query_fill(qctrl,684 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,685 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,686 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);687 if (err == 0)688 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;689 return err;690 691 case V4L2_CID_MPEG_VIDEO_ASPECT:692 return v4l2_ctrl_query_fill(qctrl,693 V4L2_MPEG_VIDEO_ASPECT_1x1,694 V4L2_MPEG_VIDEO_ASPECT_221x100, 1,695 V4L2_MPEG_VIDEO_ASPECT_4x3);696 697 case V4L2_CID_MPEG_VIDEO_B_FRAMES:698 return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);699 700 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:701 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,702 params->is_50hz ? 12 : 15);703 704 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:705 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);706 707 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:708 err = v4l2_ctrl_query_fill(qctrl,709 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,710 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,711 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);712 if (err == 0 &&713 params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)714 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;715 return err;716 717 case V4L2_CID_MPEG_VIDEO_BITRATE:718 return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);719 720 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:721 err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);722 if (err == 0 &&723 params->video_bitrate_mode ==724 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)725 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;726 return err;727 728 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:729 return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);730 731 case V4L2_CID_MPEG_VIDEO_MUTE:732 return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);733 734 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */735 return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);736 737 /* CX23415/6 specific */738 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:739 return cx2341x_ctrl_query_fill(qctrl,740 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,741 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,742 default_params.video_spatial_filter_mode);743 744 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:745 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,746 default_params.video_spatial_filter);747 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;748 if (params->video_spatial_filter_mode ==749 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)750 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;751 return 0;752 753 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:754 cx2341x_ctrl_query_fill(qctrl,755 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,756 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,757 1,758 default_params.video_luma_spatial_filter_type);759 if (params->video_spatial_filter_mode ==760 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)761 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;762 return 0;763 764 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:765 cx2341x_ctrl_query_fill(qctrl,766 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,767 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,768 1,769 default_params.video_chroma_spatial_filter_type);770 if (params->video_spatial_filter_mode ==771 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)772 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;773 return 0;774 775 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:776 return cx2341x_ctrl_query_fill(qctrl,777 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,778 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,779 default_params.video_temporal_filter_mode);780 781 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:782 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,783 default_params.video_temporal_filter);784 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;785 if (params->video_temporal_filter_mode ==786 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)787 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;788 return 0;789 790 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:791 return cx2341x_ctrl_query_fill(qctrl,792 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,793 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,794 default_params.video_median_filter_type);795 796 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:797 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,798 default_params.video_luma_median_filter_top);799 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;800 if (params->video_median_filter_type ==801 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)802 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;803 return 0;804 805 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:806 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,807 default_params.video_luma_median_filter_bottom);808 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;809 if (params->video_median_filter_type ==810 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)811 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;812 return 0;813 814 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:815 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,816 default_params.video_chroma_median_filter_top);817 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;818 if (params->video_median_filter_type ==819 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)820 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;821 return 0;822 823 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:824 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,825 default_params.video_chroma_median_filter_bottom);826 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;827 if (params->video_median_filter_type ==828 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)829 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;830 return 0;831 832 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:833 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,834 default_params.stream_insert_nav_packets);835 836 default:837 return -EINVAL;838 839 }840}841EXPORT_SYMBOL(cx2341x_ctrl_query);842 843const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)844{845 static const char * const mpeg_stream_type_without_ts[] = {846 "MPEG-2 Program Stream",847 "",848 "MPEG-1 System Stream",849 "MPEG-2 DVD-compatible Stream",850 "MPEG-1 VCD-compatible Stream",851 "MPEG-2 SVCD-compatible Stream",852 NULL853 };854 855 static const char *mpeg_stream_type_with_ts[] = {856 "MPEG-2 Program Stream",857 "MPEG-2 Transport Stream",858 "MPEG-1 System Stream",859 "MPEG-2 DVD-compatible Stream",860 "MPEG-1 VCD-compatible Stream",861 "MPEG-2 SVCD-compatible Stream",862 NULL863 };864 865 static const char *mpeg_audio_encoding_l2_ac3[] = {866 "",867 "MPEG-1/2 Layer II",868 "",869 "",870 "AC-3",871 NULL872 };873 874 switch (id) {875 case V4L2_CID_MPEG_STREAM_TYPE:876 return (p->capabilities & CX2341X_CAP_HAS_TS) ?877 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;878 case V4L2_CID_MPEG_AUDIO_ENCODING:879 return (p->capabilities & CX2341X_CAP_HAS_AC3) ?880 mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);881 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:882 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:883 return NULL;884 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:885 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:886 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:887 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:888 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:889 return cx2341x_get_menu(id);890 default:891 return v4l2_ctrl_get_menu(id);892 }893}894EXPORT_SYMBOL(cx2341x_ctrl_get_menu);895 896static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)897{898 params->audio_properties =899 (params->audio_sampling_freq << 0) |900 (params->audio_mode << 8) |901 (params->audio_mode_extension << 10) |902 (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)903 ? 3 : params->audio_emphasis) << 12) |904 (params->audio_crc << 14);905 906 if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&907 params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {908 params->audio_properties |=909 /* Not sure if this MPEG Layer II setting is required */910 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |911 (params->audio_ac3_bitrate << 4) |912 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);913 } else {914 /* Assuming MPEG Layer II */915 params->audio_properties |=916 ((3 - params->audio_encoding) << 2) |917 ((1 + params->audio_l2_bitrate) << 4);918 }919}920 921/* Check for correctness of the ctrl's value based on the data from922 struct v4l2_queryctrl and the available menu items. Note that923 menu_items may be NULL, in that case it is ignored. */924static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,925 const char * const *menu_items)926{927 if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)928 return -EINVAL;929 if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)930 return -EBUSY;931 if (qctrl->type == V4L2_CTRL_TYPE_STRING)932 return 0;933 if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||934 qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||935 qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)936 return 0;937 if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)938 return -ERANGE;939 if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {940 if (menu_items[ctrl->value] == NULL ||941 menu_items[ctrl->value][0] == '\0')942 return -EINVAL;943 }944 if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&945 (ctrl->value & ~qctrl->maximum))946 return -ERANGE;947 return 0;948}949 950int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,951 struct v4l2_ext_controls *ctrls, unsigned int cmd)952{953 int err = 0;954 int i;955 956 if (cmd == VIDIOC_G_EXT_CTRLS) {957 for (i = 0; i < ctrls->count; i++) {958 struct v4l2_ext_control *ctrl = ctrls->controls + i;959 960 err = cx2341x_get_ctrl(params, ctrl);961 if (err) {962 ctrls->error_idx = i;963 break;964 }965 }966 return err;967 }968 for (i = 0; i < ctrls->count; i++) {969 struct v4l2_ext_control *ctrl = ctrls->controls + i;970 struct v4l2_queryctrl qctrl;971 const char * const *menu_items = NULL;972 973 qctrl.id = ctrl->id;974 err = cx2341x_ctrl_query(params, &qctrl);975 if (err)976 break;977 if (qctrl.type == V4L2_CTRL_TYPE_MENU)978 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);979 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);980 if (err)981 break;982 err = cx2341x_set_ctrl(params, busy, ctrl);983 if (err)984 break;985 }986 if (err == 0 &&987 params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&988 params->video_bitrate_peak < params->video_bitrate) {989 err = -ERANGE;990 ctrls->error_idx = ctrls->count;991 }992 if (err)993 ctrls->error_idx = i;994 else995 cx2341x_calc_audio_properties(params);996 return err;997}998EXPORT_SYMBOL(cx2341x_ext_ctrls);999 1000void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)1001{1002 *p = default_params;1003 cx2341x_calc_audio_properties(p);1004}1005EXPORT_SYMBOL(cx2341x_fill_defaults);1006 1007static int cx2341x_api(void *priv, cx2341x_mbox_func func,1008 u32 cmd, int args, ...)1009{1010 u32 data[CX2341X_MBOX_MAX_DATA];1011 va_list vargs;1012 int i;1013 1014 va_start(vargs, args);1015 1016 for (i = 0; i < args; i++)1017 data[i] = va_arg(vargs, int);1018 va_end(vargs);1019 return func(priv, cmd, args, 0, data);1020}1021 1022#define CMP_FIELD(__old, __new, __field) (__old->__field != __new->__field)1023 1024int cx2341x_update(void *priv, cx2341x_mbox_func func,1025 const struct cx2341x_mpeg_params *old,1026 const struct cx2341x_mpeg_params *new)1027{1028 static int mpeg_stream_type[] = {1029 0, /* MPEG-2 PS */1030 1, /* MPEG-2 TS */1031 2, /* MPEG-1 SS */1032 14, /* DVD */1033 11, /* VCD */1034 12, /* SVCD */1035 };1036 int err;1037 1038 cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);1039 1040 if (!old ||1041 CMP_FIELD(old, new, is_50hz)) {1042 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,1043 new->is_50hz);1044 if (err)1045 return err;1046 }1047 1048 if (!old ||1049 CMP_FIELD(old, new, width) ||1050 CMP_FIELD(old, new, height) ||1051 CMP_FIELD(old, new, video_encoding)) {1052 u16 w = new->width;1053 u16 h = new->height;1054 1055 if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {1056 w /= 2;1057 h /= 2;1058 }1059 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,1060 h, w);1061 if (err)1062 return err;1063 }1064 if (!old ||1065 CMP_FIELD(old, new, stream_type)) {1066 err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,1067 mpeg_stream_type[new->stream_type]);1068 if (err)1069 return err;1070 }1071 if (!old ||1072 CMP_FIELD(old, new, video_aspect)) {1073 err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,1074 1 + new->video_aspect);1075 if (err)1076 return err;1077 }1078 if (!old ||1079 CMP_FIELD(old, new, video_b_frames) ||1080 CMP_FIELD(old, new, video_gop_size)) {1081 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,1082 new->video_gop_size, new->video_b_frames + 1);1083 if (err)1084 return err;1085 }1086 if (!old ||1087 CMP_FIELD(old, new, video_gop_closure)) {1088 err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,1089 new->video_gop_closure);1090 if (err)1091 return err;1092 }1093 if (!old ||1094 CMP_FIELD(old, new, audio_properties)) {1095 err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,1096 1, new->audio_properties);1097 if (err)1098 return err;1099 }1100 if (!old ||1101 CMP_FIELD(old, new, audio_mute)) {1102 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,1103 new->audio_mute);1104 if (err)1105 return err;1106 }1107 if (!old ||1108 CMP_FIELD(old, new, video_bitrate_mode) ||1109 CMP_FIELD(old, new, video_bitrate) ||1110 CMP_FIELD(old, new, video_bitrate_peak)) {1111 err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,1112 new->video_bitrate_mode, new->video_bitrate,1113 new->video_bitrate_peak / 400, 0, 0);1114 if (err)1115 return err;1116 }1117 if (!old ||1118 CMP_FIELD(old, new, video_spatial_filter_mode) ||1119 CMP_FIELD(old, new, video_temporal_filter_mode) ||1120 CMP_FIELD(old, new, video_median_filter_type)) {1121 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,1122 2,1123 new->video_spatial_filter_mode |1124 (new->video_temporal_filter_mode << 1),1125 new->video_median_filter_type);1126 if (err)1127 return err;1128 }1129 if (!old ||1130 CMP_FIELD(old, new, video_luma_median_filter_bottom) ||1131 CMP_FIELD(old, new, video_luma_median_filter_top) ||1132 CMP_FIELD(old, new, video_chroma_median_filter_bottom) ||1133 CMP_FIELD(old, new, video_chroma_median_filter_top)) {1134 err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,1135 new->video_luma_median_filter_bottom,1136 new->video_luma_median_filter_top,1137 new->video_chroma_median_filter_bottom,1138 new->video_chroma_median_filter_top);1139 if (err)1140 return err;1141 }1142 if (!old ||1143 CMP_FIELD(old, new, video_luma_spatial_filter_type) ||1144 CMP_FIELD(old, new, video_chroma_spatial_filter_type)) {1145 err = cx2341x_api(priv, func,1146 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,1147 2, new->video_luma_spatial_filter_type,1148 new->video_chroma_spatial_filter_type);1149 if (err)1150 return err;1151 }1152 if (!old ||1153 CMP_FIELD(old, new, video_spatial_filter) ||1154 CMP_FIELD(old, new, video_temporal_filter)) {1155 err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,1156 2, new->video_spatial_filter,1157 new->video_temporal_filter);1158 if (err)1159 return err;1160 }1161 if (!old ||1162 CMP_FIELD(old, new, video_temporal_decimation)) {1163 err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,1164 1, new->video_temporal_decimation);1165 if (err)1166 return err;1167 }1168 if (!old ||1169 CMP_FIELD(old, new, video_mute) ||1170 (new->video_mute && CMP_FIELD(old, new, video_mute_yuv))) {1171 err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,1172 new->video_mute | (new->video_mute_yuv << 8));1173 if (err)1174 return err;1175 }1176 if (!old ||1177 CMP_FIELD(old, new, stream_insert_nav_packets)) {1178 err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,1179 7, new->stream_insert_nav_packets);1180 if (err)1181 return err;1182 }1183 return 0;1184}1185EXPORT_SYMBOL(cx2341x_update);1186 1187static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)1188{1189 const char * const *menu = cx2341x_ctrl_get_menu(p, id);1190 struct v4l2_ext_control ctrl;1191 1192 if (menu == NULL)1193 goto invalid;1194 ctrl.id = id;1195 if (cx2341x_get_ctrl(p, &ctrl))1196 goto invalid;1197 while (ctrl.value-- && *menu) menu++;1198 if (*menu == NULL)1199 goto invalid;1200 return *menu;1201 1202invalid:1203 return "<invalid>";1204}1205 1206void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)1207{1208 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;1209 1210 /* Stream */1211 printk(KERN_INFO "%s: Stream: %s",1212 prefix,1213 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));1214 if (p->stream_insert_nav_packets)1215 printk(KERN_CONT " (with navigation packets)");1216 printk(KERN_CONT "\n");1217 printk(KERN_INFO "%s: VBI Format: %s\n",1218 prefix,1219 cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));1220 1221 /* Video */1222 printk(KERN_INFO "%s: Video: %dx%d, %d fps%s\n",1223 prefix,1224 p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),1225 p->is_50hz ? 25 : 30,1226 (p->video_mute) ? " (muted)" : "");1227 printk(KERN_INFO "%s: Video: %s, %s, %s, %d",1228 prefix,1229 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),1230 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),1231 cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),1232 p->video_bitrate);1233 if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)1234 printk(KERN_CONT ", Peak %d", p->video_bitrate_peak);1235 printk(KERN_CONT "\n");1236 printk(KERN_INFO1237 "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure\n",1238 prefix,1239 p->video_gop_size, p->video_b_frames,1240 p->video_gop_closure ? "" : "No ");1241 if (p->video_temporal_decimation)1242 printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",1243 prefix, p->video_temporal_decimation);1244 1245 /* Audio */1246 printk(KERN_INFO "%s: Audio: %s, %s, %s, %s%s",1247 prefix,1248 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),1249 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),1250 cx2341x_menu_item(p,1251 p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC31252 ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE1253 : V4L2_CID_MPEG_AUDIO_L2_BITRATE),1254 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),1255 p->audio_mute ? " (muted)" : "");1256 if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)1257 printk(KERN_CONT ", %s", cx2341x_menu_item(p,1258 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));1259 printk(KERN_CONT ", %s, %s\n",1260 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),1261 cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));1262 1263 /* Encoding filters */1264 printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n",1265 prefix,1266 cx2341x_menu_item(p,1267 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),1268 cx2341x_menu_item(p,1269 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),1270 cx2341x_menu_item(p,1271 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),1272 p->video_spatial_filter);1273 1274 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",1275 prefix,1276 cx2341x_menu_item(p,1277 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),1278 p->video_temporal_filter);1279 printk(KERN_INFO1280 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",1281 prefix,1282 cx2341x_menu_item(p,1283 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),1284 p->video_luma_median_filter_bottom,1285 p->video_luma_median_filter_top,1286 p->video_chroma_median_filter_bottom,1287 p->video_chroma_median_filter_top);1288}1289EXPORT_SYMBOL(cx2341x_log_status);1290 1291 1292 1293/********************** NEW CODE *********************/1294 1295static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl)1296{1297 return container_of(ctrl->handler, struct cx2341x_handler, hdl);1298}1299 1300static int cx2341x_hdl_api(struct cx2341x_handler *hdl,1301 u32 cmd, int args, ...)1302{1303 u32 data[CX2341X_MBOX_MAX_DATA];1304 va_list vargs;1305 int i;1306 1307 va_start(vargs, args);1308 1309 for (i = 0; i < args; i++)1310 data[i] = va_arg(vargs, int);1311 va_end(vargs);1312 return hdl->func(hdl->priv, cmd, args, 0, data);1313}1314 1315/* ctrl->handler->lock is held, so it is safe to access cur.val */1316static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)1317{1318 return ctrl && ctrl->val != ctrl->cur.val;1319}1320 1321static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)1322{1323 struct cx2341x_handler *hdl = to_cxhdl(ctrl);1324 s32 val = ctrl->val;1325 1326 switch (ctrl->id) {1327 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {1328 /* video gop cluster */1329 int b = val + 1;1330 int gop = hdl->video_gop_size->val;1331 1332 gop = b * ((gop + b - 1) / b);1333 1334 /* Max GOP size = 34 */1335 while (gop > 34)1336 gop -= b;1337 hdl->video_gop_size->val = gop;1338 break;1339 }1340 1341 case V4L2_CID_MPEG_STREAM_TYPE:1342 /* stream type cluster */1343 hdl->video_encoding->val =1344 (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||1345 hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?1346 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :1347 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;1348 if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)1349 /* MPEG-1 implies CBR */1350 hdl->video_bitrate_mode->val =1351 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;1352 /* peak bitrate shall be >= normal bitrate */1353 if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&1354 hdl->video_bitrate_peak->val < hdl->video_bitrate->val)1355 hdl->video_bitrate_peak->val = hdl->video_bitrate->val;1356 break;1357 }1358 return 0;1359}1360 1361static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl)1362{1363 static const int mpeg_stream_type[] = {1364 0, /* MPEG-2 PS */1365 1, /* MPEG-2 TS */1366 2, /* MPEG-1 SS */1367 14, /* DVD */1368 11, /* VCD */1369 12, /* SVCD */1370 };1371 struct cx2341x_handler *hdl = to_cxhdl(ctrl);1372 s32 val = ctrl->val;1373 u32 props;1374 int err;1375 1376 switch (ctrl->id) {1377 case V4L2_CID_MPEG_STREAM_VBI_FMT:1378 if (hdl->ops && hdl->ops->s_stream_vbi_fmt)1379 return hdl->ops->s_stream_vbi_fmt(hdl, val);1380 return 0;1381 1382 case V4L2_CID_MPEG_VIDEO_ASPECT:1383 return cx2341x_hdl_api(hdl,1384 CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1);1385 1386 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:1387 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val);1388 1389 case V4L2_CID_MPEG_AUDIO_MUTE:1390 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val);1391 1392 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:1393 return cx2341x_hdl_api(hdl,1394 CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val);1395 1396 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:1397 return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val);1398 1399 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:1400 /* audio properties cluster */1401 props = (hdl->audio_sampling_freq->val << 0) |1402 (hdl->audio_mode->val << 8) |1403 (hdl->audio_mode_extension->val << 10) |1404 (hdl->audio_crc->val << 14);1405 if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)1406 props |= 3 << 12;1407 else1408 props |= hdl->audio_emphasis->val << 12;1409 1410 if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) {1411 props |=1412#if 11413 /* Not sure if this MPEG Layer II setting is required */1414 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |1415#endif1416 (hdl->audio_ac3_bitrate->val << 4) |1417 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);1418 } else {1419 /* Assuming MPEG Layer II */1420 props |=1421 ((3 - hdl->audio_encoding->val) << 2) |1422 ((1 + hdl->audio_l2_bitrate->val) << 4);1423 }1424 err = cx2341x_hdl_api(hdl,1425 CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props);1426 if (err)1427 return err;1428 1429 hdl->audio_properties = props;1430 if (hdl->audio_ac3_bitrate) {1431 int is_ac3 = hdl->audio_encoding->val ==1432 V4L2_MPEG_AUDIO_ENCODING_AC3;1433 1434 v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3);1435 v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3);1436 }1437 v4l2_ctrl_activate(hdl->audio_mode_extension,1438 hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO);1439 if (cx2341x_neq(hdl->audio_sampling_freq) &&1440 hdl->ops && hdl->ops->s_audio_sampling_freq)1441 return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val);1442 if (cx2341x_neq(hdl->audio_mode) &&1443 hdl->ops && hdl->ops->s_audio_mode)1444 return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val);1445 return 0;1446 1447 case V4L2_CID_MPEG_VIDEO_B_FRAMES:1448 /* video gop cluster */1449 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2,1450 hdl->video_gop_size->val,1451 hdl->video_b_frames->val + 1);1452 1453 case V4L2_CID_MPEG_STREAM_TYPE:1454 /* stream type cluster */1455 err = cx2341x_hdl_api(hdl,1456 CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]);1457 if (err)1458 return err;1459 1460 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5,1461 hdl->video_bitrate_mode->val,1462 hdl->video_bitrate->val,1463 hdl->video_bitrate_peak->val / 400, 0, 0);1464 if (err)1465 return err;1466 1467 v4l2_ctrl_activate(hdl->video_bitrate_mode,1468 hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1);1469 v4l2_ctrl_activate(hdl->video_bitrate_peak,1470 hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);1471 if (cx2341x_neq(hdl->video_encoding) &&1472 hdl->ops && hdl->ops->s_video_encoding)1473 return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val);1474 return 0;1475 1476 case V4L2_CID_MPEG_VIDEO_MUTE:1477 /* video mute cluster */1478 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1,1479 hdl->video_mute->val |1480 (hdl->video_mute_yuv->val << 8));1481 1482 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: {1483 int active_filter;1484 1485 /* video filter mode */1486 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,1487 hdl->video_spatial_filter_mode->val |1488 (hdl->video_temporal_filter_mode->val << 1),1489 hdl->video_median_filter_type->val);1490 if (err)1491 return err;1492 1493 active_filter = hdl->video_spatial_filter_mode->val !=1494 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO;1495 v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter);1496 v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter);1497 v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter);1498 active_filter = hdl->video_temporal_filter_mode->val !=1499 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO;1500 v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter);1501 active_filter = hdl->video_median_filter_type->val !=1502 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF;1503 v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter);1504 v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter);1505 v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter);1506 v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter);1507 return 0;1508 }1509 1510 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:1511 /* video filter type cluster */1512 return cx2341x_hdl_api(hdl,1513 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,1514 hdl->video_luma_spatial_filter_type->val,1515 hdl->video_chroma_spatial_filter_type->val);1516 1517 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:1518 /* video filter cluster */1519 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,1520 hdl->video_spatial_filter->val,1521 hdl->video_temporal_filter->val);1522 1523 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:1524 /* video median cluster */1525 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4,1526 hdl->video_luma_median_filter_bottom->val,1527 hdl->video_luma_median_filter_top->val,1528 hdl->video_chroma_median_filter_bottom->val,1529 hdl->video_chroma_median_filter_top->val);1530 }1531 return -EINVAL;1532}1533 1534static const struct v4l2_ctrl_ops cx2341x_ops = {1535 .try_ctrl = cx2341x_try_ctrl,1536 .s_ctrl = cx2341x_s_ctrl,1537};1538 1539static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,1540 u32 id, s32 min, s32 max, s32 step, s32 def)1541{1542 struct v4l2_ctrl_config cfg;1543 1544 memset(&cfg, 0, sizeof(cfg));1545 cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);1546 cfg.ops = &cx2341x_ops;1547 cfg.id = id;1548 cfg.min = min;1549 cfg.max = max;1550 cfg.def = def;1551 if (cfg.type == V4L2_CTRL_TYPE_MENU) {1552 cfg.step = 0;1553 cfg.menu_skip_mask = step;1554 cfg.qmenu = cx2341x_get_menu(id);1555 } else {1556 cfg.step = step;1557 cfg.menu_skip_mask = 0;1558 }1559 return v4l2_ctrl_new_custom(hdl, &cfg, NULL);1560}1561 1562static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl,1563 u32 id, s32 min, s32 max, s32 step, s32 def)1564{1565 return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def);1566}1567 1568static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl,1569 u32 id, s32 max, s32 mask, s32 def)1570{1571 return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def);1572}1573 1574int cx2341x_handler_init(struct cx2341x_handler *cxhdl,1575 unsigned nr_of_controls_hint)1576{1577 struct v4l2_ctrl_handler *hdl = &cxhdl->hdl;1578 u32 caps = cxhdl->capabilities;1579 int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI;1580 int has_ac3 = caps & CX2341X_CAP_HAS_AC3;1581 int has_ts = caps & CX2341X_CAP_HAS_TS;1582 1583 cxhdl->width = 720;1584 cxhdl->height = 480;1585 1586 v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);1587 1588 /* Add controls in ascending control ID order for fastest1589 insertion time. */1590 cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl,1591 V4L2_CID_MPEG_STREAM_TYPE,1592 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2,1593 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);1594 cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl,1595 V4L2_CID_MPEG_STREAM_VBI_FMT,1596 V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2,1597 V4L2_MPEG_STREAM_VBI_FMT_NONE);1598 cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl,1599 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,1600 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0,1601 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);1602 cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl,1603 V4L2_CID_MPEG_AUDIO_ENCODING,1604 V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2,1605 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);1606 cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl,1607 V4L2_CID_MPEG_AUDIO_L2_BITRATE,1608 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff,1609 V4L2_MPEG_AUDIO_L2_BITRATE_224K);1610 cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl,1611 V4L2_CID_MPEG_AUDIO_MODE,1612 V4L2_MPEG_AUDIO_MODE_MONO, 0,1613 V4L2_MPEG_AUDIO_MODE_STEREO);1614 cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl,1615 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,1616 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0,1617 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);1618 cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl,1619 V4L2_CID_MPEG_AUDIO_EMPHASIS,1620 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0,1621 V4L2_MPEG_AUDIO_EMPHASIS_NONE);1622 cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl,1623 V4L2_CID_MPEG_AUDIO_CRC,1624 V4L2_MPEG_AUDIO_CRC_CRC16, 0,1625 V4L2_MPEG_AUDIO_CRC_NONE);1626 1627 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0);1628 if (has_ac3)1629 cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl,1630 V4L2_CID_MPEG_AUDIO_AC3_BITRATE,1631 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03,1632 V4L2_MPEG_AUDIO_AC3_BITRATE_224K);1633 cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl,1634 V4L2_CID_MPEG_VIDEO_ENCODING,1635 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0,1636 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);1637 cx2341x_ctrl_new_menu(hdl,1638 V4L2_CID_MPEG_VIDEO_ASPECT,1639 V4L2_MPEG_VIDEO_ASPECT_221x100, 0,1640 V4L2_MPEG_VIDEO_ASPECT_4x3);1641 cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl,1642 V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2);1643 cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl,1644 V4L2_CID_MPEG_VIDEO_GOP_SIZE,1645 1, 34, 1, cxhdl->is_50hz ? 12 : 15);1646 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);1647 cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl,1648 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,1649 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,1650 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);1651 cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl,1652 V4L2_CID_MPEG_VIDEO_BITRATE,1653 0, 27000000, 1, 6000000);1654 cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl,1655 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,1656 0, 27000000, 1, 8000000);1657 cx2341x_ctrl_new_std(hdl,1658 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0);1659 cxhdl->video_mute = cx2341x_ctrl_new_std(hdl,1660 V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0);1661 cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl,1662 V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080);1663 1664 /* CX23415/6 specific */1665 cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl,1666 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,1667 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,1668 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0,1669 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);1670 cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl,1671 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,1672 0, 15, 1, 0);1673 cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,1674 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,1675 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,1676 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,1677 0,1678 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR);1679 cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,1680 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,1681 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,1682 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,1683 0,1684 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR);1685 cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl,1686 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,1687 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,1688 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO,1689 0,1690 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);1691 cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl,1692 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,1693 0, 31, 1, 8);1694 cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl,1695 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,1696 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,1697 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG,1698 0,1699 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);1700 cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,1701 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,1702 0, 255, 1, 0);1703 cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl,1704 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,1705 0, 255, 1, 255);1706 cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,1707 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,1708 0, 255, 1, 0);1709 cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl,1710 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,1711 0, 255, 1, 255);1712 cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,1713 0, 1, 1, 0);1714 1715 if (hdl->error) {1716 int err = hdl->error;1717 1718 v4l2_ctrl_handler_free(hdl);1719 return err;1720 }1721 1722 v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq);1723 v4l2_ctrl_cluster(2, &cxhdl->video_b_frames);1724 v4l2_ctrl_cluster(5, &cxhdl->stream_type);1725 v4l2_ctrl_cluster(2, &cxhdl->video_mute);1726 v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode);1727 v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type);1728 v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter);1729 v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top);1730 1731 return 0;1732}1733EXPORT_SYMBOL(cx2341x_handler_init);1734 1735void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz)1736{1737 cxhdl->is_50hz = is_50hz;1738 cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15;1739}1740EXPORT_SYMBOL(cx2341x_handler_set_50hz);1741 1742int cx2341x_handler_setup(struct cx2341x_handler *cxhdl)1743{1744 int h = cxhdl->height;1745 int w = cxhdl->width;1746 int err;1747 1748 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0);1749 if (err)1750 return err;1751 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz);1752 if (err)1753 return err;1754 1755 if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {1756 w /= 2;1757 h /= 2;1758 }1759 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);1760 if (err)1761 return err;1762 return v4l2_ctrl_handler_setup(&cxhdl->hdl);1763}1764EXPORT_SYMBOL(cx2341x_handler_setup);1765 1766void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy)1767{1768 v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy);1769 v4l2_ctrl_grab(cxhdl->audio_encoding, busy);1770 v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy);1771 v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy);1772 v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy);1773 v4l2_ctrl_grab(cxhdl->stream_type, busy);1774 v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy);1775 v4l2_ctrl_grab(cxhdl->video_bitrate, busy);1776 v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy);1777}1778EXPORT_SYMBOL(cx2341x_handler_set_busy);1779