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