linux/drivers/media/video/cx2341x.c
<<
>>
Prefs
   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 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21
  22#include <linux/module.h>
  23#include <linux/errno.h>
  24#include <linux/kernel.h>
  25#include <linux/init.h>
  26#include <linux/types.h>
  27#include <linux/videodev2.h>
  28
  29#include <media/tuner.h>
  30#include <media/cx2341x.h>
  31#include <media/v4l2-common.h>
  32
  33MODULE_DESCRIPTION("cx23415/6/8 driver");
  34MODULE_AUTHOR("Hans Verkuil");
  35MODULE_LICENSE("GPL");
  36
  37static int debug;
  38module_param(debug, int, 0644);
  39MODULE_PARM_DESC(debug, "Debug level (0-1)");
  40
  41/* Must be sorted from low to high control ID! */
  42const u32 cx2341x_mpeg_ctrls[] = {
  43        V4L2_CID_MPEG_CLASS,
  44        V4L2_CID_MPEG_STREAM_TYPE,
  45        V4L2_CID_MPEG_STREAM_VBI_FMT,
  46        V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
  47        V4L2_CID_MPEG_AUDIO_ENCODING,
  48        V4L2_CID_MPEG_AUDIO_L2_BITRATE,
  49        V4L2_CID_MPEG_AUDIO_MODE,
  50        V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
  51        V4L2_CID_MPEG_AUDIO_EMPHASIS,
  52        V4L2_CID_MPEG_AUDIO_CRC,
  53        V4L2_CID_MPEG_AUDIO_MUTE,
  54        V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
  55        V4L2_CID_MPEG_VIDEO_ENCODING,
  56        V4L2_CID_MPEG_VIDEO_ASPECT,
  57        V4L2_CID_MPEG_VIDEO_B_FRAMES,
  58        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
  59        V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
  60        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
  61        V4L2_CID_MPEG_VIDEO_BITRATE,
  62        V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
  63        V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
  64        V4L2_CID_MPEG_VIDEO_MUTE,
  65        V4L2_CID_MPEG_VIDEO_MUTE_YUV,
  66        V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
  67        V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
  68        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
  69        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
  70        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
  71        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
  72        V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
  73        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
  74        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
  75        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
  76        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
  77        V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
  78        0
  79};
  80EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
  81
  82static const struct cx2341x_mpeg_params default_params = {
  83        /* misc */
  84        .capabilities = 0,
  85        .port = CX2341X_PORT_MEMORY,
  86        .width = 720,
  87        .height = 480,
  88        .is_50hz = 0,
  89
  90        /* stream */
  91        .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
  92        .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
  93        .stream_insert_nav_packets = 0,
  94
  95        /* audio */
  96        .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
  97        .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
  98        .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
  99        .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
 100        .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
 101        .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
 102        .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
 103        .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
 104        .audio_mute = 0,
 105
 106        /* video */
 107        .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
 108        .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
 109        .video_b_frames = 2,
 110        .video_gop_size = 12,
 111        .video_gop_closure = 1,
 112        .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
 113        .video_bitrate = 6000000,
 114        .video_bitrate_peak = 8000000,
 115        .video_temporal_decimation = 0,
 116        .video_mute = 0,
 117        .video_mute_yuv = 0x008080,  /* YCbCr value for black */
 118
 119        /* encoding filters */
 120        .video_spatial_filter_mode =
 121                V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
 122        .video_spatial_filter = 0,
 123        .video_luma_spatial_filter_type =
 124                V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
 125        .video_chroma_spatial_filter_type =
 126                V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
 127        .video_temporal_filter_mode =
 128                V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
 129        .video_temporal_filter = 8,
 130        .video_median_filter_type =
 131                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
 132        .video_luma_median_filter_top = 255,
 133        .video_luma_median_filter_bottom = 0,
 134        .video_chroma_median_filter_top = 255,
 135        .video_chroma_median_filter_bottom = 0,
 136};
 137
 138
 139/* Map the control ID to the correct field in the cx2341x_mpeg_params
 140   struct. Return -EINVAL if the ID is unknown, else return 0. */
 141static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
 142                struct v4l2_ext_control *ctrl)
 143{
 144        switch (ctrl->id) {
 145        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
 146                ctrl->value = params->audio_sampling_freq;
 147                break;
 148        case V4L2_CID_MPEG_AUDIO_ENCODING:
 149                ctrl->value = params->audio_encoding;
 150                break;
 151        case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
 152                ctrl->value = params->audio_l2_bitrate;
 153                break;
 154        case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
 155                ctrl->value = params->audio_ac3_bitrate;
 156                break;
 157        case V4L2_CID_MPEG_AUDIO_MODE:
 158                ctrl->value = params->audio_mode;
 159                break;
 160        case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
 161                ctrl->value = params->audio_mode_extension;
 162                break;
 163        case V4L2_CID_MPEG_AUDIO_EMPHASIS:
 164                ctrl->value = params->audio_emphasis;
 165                break;
 166        case V4L2_CID_MPEG_AUDIO_CRC:
 167                ctrl->value = params->audio_crc;
 168                break;
 169        case V4L2_CID_MPEG_AUDIO_MUTE:
 170                ctrl->value = params->audio_mute;
 171                break;
 172        case V4L2_CID_MPEG_VIDEO_ENCODING:
 173                ctrl->value = params->video_encoding;
 174                break;
 175        case V4L2_CID_MPEG_VIDEO_ASPECT:
 176                ctrl->value = params->video_aspect;
 177                break;
 178        case V4L2_CID_MPEG_VIDEO_B_FRAMES:
 179                ctrl->value = params->video_b_frames;
 180                break;
 181        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
 182                ctrl->value = params->video_gop_size;
 183                break;
 184        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 185                ctrl->value = params->video_gop_closure;
 186                break;
 187        case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 188                ctrl->value = params->video_bitrate_mode;
 189                break;
 190        case V4L2_CID_MPEG_VIDEO_BITRATE:
 191                ctrl->value = params->video_bitrate;
 192                break;
 193        case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
 194                ctrl->value = params->video_bitrate_peak;
 195                break;
 196        case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
 197                ctrl->value = params->video_temporal_decimation;
 198                break;
 199        case V4L2_CID_MPEG_VIDEO_MUTE:
 200                ctrl->value = params->video_mute;
 201                break;
 202        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
 203                ctrl->value = params->video_mute_yuv;
 204                break;
 205        case V4L2_CID_MPEG_STREAM_TYPE:
 206                ctrl->value = params->stream_type;
 207                break;
 208        case V4L2_CID_MPEG_STREAM_VBI_FMT:
 209                ctrl->value = params->stream_vbi_fmt;
 210                break;
 211        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 212                ctrl->value = params->video_spatial_filter_mode;
 213                break;
 214        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
 215                ctrl->value = params->video_spatial_filter;
 216                break;
 217        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 218                ctrl->value = params->video_luma_spatial_filter_type;
 219                break;
 220        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 221                ctrl->value = params->video_chroma_spatial_filter_type;
 222                break;
 223        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 224                ctrl->value = params->video_temporal_filter_mode;
 225                break;
 226        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
 227                ctrl->value = params->video_temporal_filter;
 228                break;
 229        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 230                ctrl->value = params->video_median_filter_type;
 231                break;
 232        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
 233                ctrl->value = params->video_luma_median_filter_top;
 234                break;
 235        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
 236                ctrl->value = params->video_luma_median_filter_bottom;
 237                break;
 238        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
 239                ctrl->value = params->video_chroma_median_filter_top;
 240                break;
 241        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
 242                ctrl->value = params->video_chroma_median_filter_bottom;
 243                break;
 244        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
 245                ctrl->value = params->stream_insert_nav_packets;
 246                break;
 247        default:
 248                return -EINVAL;
 249        }
 250        return 0;
 251}
 252
 253/* Map the control ID to the correct field in the cx2341x_mpeg_params
 254   struct. Return -EINVAL if the ID is unknown, else return 0. */
 255static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
 256                struct v4l2_ext_control *ctrl)
 257{
 258        switch (ctrl->id) {
 259        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
 260                if (busy)
 261                        return -EBUSY;
 262                params->audio_sampling_freq = ctrl->value;
 263                break;
 264        case V4L2_CID_MPEG_AUDIO_ENCODING:
 265                if (busy)
 266                        return -EBUSY;
 267                if (params->capabilities & CX2341X_CAP_HAS_AC3)
 268                        if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
 269                            ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
 270                                return -ERANGE;
 271                params->audio_encoding = ctrl->value;
 272                break;
 273        case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
 274                if (busy)
 275                        return -EBUSY;
 276                params->audio_l2_bitrate = ctrl->value;
 277                break;
 278        case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
 279                if (busy)
 280                        return -EBUSY;
 281                if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
 282                        return -EINVAL;
 283                params->audio_ac3_bitrate = ctrl->value;
 284                break;
 285        case V4L2_CID_MPEG_AUDIO_MODE:
 286                params->audio_mode = ctrl->value;
 287                break;
 288        case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
 289                params->audio_mode_extension = ctrl->value;
 290                break;
 291        case V4L2_CID_MPEG_AUDIO_EMPHASIS:
 292                params->audio_emphasis = ctrl->value;
 293                break;
 294        case V4L2_CID_MPEG_AUDIO_CRC:
 295                params->audio_crc = ctrl->value;
 296                break;
 297        case V4L2_CID_MPEG_AUDIO_MUTE:
 298                params->audio_mute = ctrl->value;
 299                break;
 300        case V4L2_CID_MPEG_VIDEO_ASPECT:
 301                params->video_aspect = ctrl->value;
 302                break;
 303        case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
 304                int b = ctrl->value + 1;
 305                int gop = params->video_gop_size;
 306                params->video_b_frames = ctrl->value;
 307                params->video_gop_size = b * ((gop + b - 1) / b);
 308                /* Max GOP size = 34 */
 309                while (params->video_gop_size > 34)
 310                        params->video_gop_size -= b;
 311                break;
 312        }
 313        case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
 314                int b = params->video_b_frames + 1;
 315                int gop = ctrl->value;
 316                params->video_gop_size = b * ((gop + b - 1) / b);
 317                /* Max GOP size = 34 */
 318                while (params->video_gop_size > 34)
 319                        params->video_gop_size -= b;
 320                ctrl->value = params->video_gop_size;
 321                break;
 322        }
 323        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 324                params->video_gop_closure = ctrl->value;
 325                break;
 326        case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 327                if (busy)
 328                        return -EBUSY;
 329                /* MPEG-1 only allows CBR */
 330                if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
 331                    ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 332                        return -EINVAL;
 333                params->video_bitrate_mode = ctrl->value;
 334                break;
 335        case V4L2_CID_MPEG_VIDEO_BITRATE:
 336                if (busy)
 337                        return -EBUSY;
 338                params->video_bitrate = ctrl->value;
 339                break;
 340        case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
 341                if (busy)
 342                        return -EBUSY;
 343                params->video_bitrate_peak = ctrl->value;
 344                break;
 345        case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
 346                params->video_temporal_decimation = ctrl->value;
 347                break;
 348        case V4L2_CID_MPEG_VIDEO_MUTE:
 349                params->video_mute = (ctrl->value != 0);
 350                break;
 351        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
 352                params->video_mute_yuv = ctrl->value;
 353                break;
 354        case V4L2_CID_MPEG_STREAM_TYPE:
 355                if (busy)
 356                        return -EBUSY;
 357                params->stream_type = ctrl->value;
 358                params->video_encoding =
 359                    (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
 360                     params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
 361                        V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
 362                        V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
 363                if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
 364                        /* MPEG-1 implies CBR */
 365                        params->video_bitrate_mode =
 366                                V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
 367                break;
 368        case V4L2_CID_MPEG_STREAM_VBI_FMT:
 369                params->stream_vbi_fmt = ctrl->value;
 370                break;
 371        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 372                params->video_spatial_filter_mode = ctrl->value;
 373                break;
 374        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
 375                params->video_spatial_filter = ctrl->value;
 376                break;
 377        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 378                params->video_luma_spatial_filter_type = ctrl->value;
 379                break;
 380        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 381                params->video_chroma_spatial_filter_type = ctrl->value;
 382                break;
 383        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 384                params->video_temporal_filter_mode = ctrl->value;
 385                break;
 386        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
 387                params->video_temporal_filter = ctrl->value;
 388                break;
 389        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 390                params->video_median_filter_type = ctrl->value;
 391                break;
 392        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
 393                params->video_luma_median_filter_top = ctrl->value;
 394                break;
 395        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
 396                params->video_luma_median_filter_bottom = ctrl->value;
 397                break;
 398        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
 399                params->video_chroma_median_filter_top = ctrl->value;
 400                break;
 401        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
 402                params->video_chroma_median_filter_bottom = ctrl->value;
 403                break;
 404        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
 405                params->stream_insert_nav_packets = ctrl->value;
 406                break;
 407        default:
 408                return -EINVAL;
 409        }
 410        return 0;
 411}
 412
 413static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
 414                                   s32 min, s32 max, s32 step, s32 def)
 415{
 416        const char *name;
 417
 418        qctrl->flags = 0;
 419        switch (qctrl->id) {
 420        /* MPEG controls */
 421        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 422                name = "Spatial Filter Mode";
 423                break;
 424        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
 425                name = "Spatial Filter";
 426                break;
 427        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 428                name = "Spatial Luma Filter Type";
 429                break;
 430        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 431                name = "Spatial Chroma Filter Type";
 432                break;
 433        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 434                name = "Temporal Filter Mode";
 435                break;
 436        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
 437                name = "Temporal Filter";
 438                break;
 439        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 440                name = "Median Filter Type";
 441                break;
 442        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
 443                name = "Median Luma Filter Maximum";
 444                break;
 445        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
 446                name = "Median Luma Filter Minimum";
 447                break;
 448        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
 449                name = "Median Chroma Filter Maximum";
 450                break;
 451        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
 452                name = "Median Chroma Filter Minimum";
 453                break;
 454        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
 455                name = "Insert Navigation Packets";
 456                break;
 457
 458        default:
 459                return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
 460        }
 461        switch (qctrl->id) {
 462        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 463        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 464        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 465        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 466        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 467                qctrl->type = V4L2_CTRL_TYPE_MENU;
 468                min = 0;
 469                step = 1;
 470                break;
 471        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
 472                qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
 473                min = 0;
 474                max = 1;
 475                step = 1;
 476                break;
 477        default:
 478                qctrl->type = V4L2_CTRL_TYPE_INTEGER;
 479                break;
 480        }
 481        switch (qctrl->id) {
 482        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 483        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 484        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 485                qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
 486                break;
 487        }
 488        qctrl->minimum = min;
 489        qctrl->maximum = max;
 490        qctrl->step = step;
 491        qctrl->default_value = def;
 492        qctrl->reserved[0] = qctrl->reserved[1] = 0;
 493        snprintf(qctrl->name, sizeof(qctrl->name), name);
 494        return 0;
 495}
 496
 497int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
 498                       struct v4l2_queryctrl *qctrl)
 499{
 500        int err;
 501
 502        switch (qctrl->id) {
 503        case V4L2_CID_MPEG_CLASS:
 504                return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
 505        case V4L2_CID_MPEG_STREAM_TYPE:
 506                return v4l2_ctrl_query_fill(qctrl,
 507                                V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
 508                                V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
 509                                V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
 510
 511        case V4L2_CID_MPEG_STREAM_VBI_FMT:
 512                if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
 513                        return v4l2_ctrl_query_fill(qctrl,
 514                                        V4L2_MPEG_STREAM_VBI_FMT_NONE,
 515                                        V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
 516                                        V4L2_MPEG_STREAM_VBI_FMT_NONE);
 517                return cx2341x_ctrl_query_fill(qctrl,
 518                                V4L2_MPEG_STREAM_VBI_FMT_NONE,
 519                                V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
 520                                default_params.stream_vbi_fmt);
 521
 522        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
 523                return v4l2_ctrl_query_fill(qctrl,
 524                                V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
 525                                V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
 526                                V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
 527
 528        case V4L2_CID_MPEG_AUDIO_ENCODING:
 529                if (params->capabilities & CX2341X_CAP_HAS_AC3) {
 530                        /*
 531                         * The state of L2 & AC3 bitrate controls can change
 532                         * when this control changes, but v4l2_ctrl_query_fill()
 533                         * already sets V4L2_CTRL_FLAG_UPDATE for
 534                         * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
 535                         */
 536                        return v4l2_ctrl_query_fill(qctrl,
 537                                        V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
 538                                        V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
 539                                        default_params.audio_encoding);
 540                }
 541
 542                return v4l2_ctrl_query_fill(qctrl,
 543                                V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
 544                                V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
 545                                default_params.audio_encoding);
 546
 547        case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
 548                err = v4l2_ctrl_query_fill(qctrl,
 549                                V4L2_MPEG_AUDIO_L2_BITRATE_192K,
 550                                V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
 551                                default_params.audio_l2_bitrate);
 552                if (err)
 553                        return err;
 554                if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
 555                    params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
 556                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 557                return 0;
 558
 559        case V4L2_CID_MPEG_AUDIO_MODE:
 560                return v4l2_ctrl_query_fill(qctrl,
 561                                V4L2_MPEG_AUDIO_MODE_STEREO,
 562                                V4L2_MPEG_AUDIO_MODE_MONO, 1,
 563                                V4L2_MPEG_AUDIO_MODE_STEREO);
 564
 565        case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
 566                err = v4l2_ctrl_query_fill(qctrl,
 567                                V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
 568                                V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
 569                                V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
 570                if (err == 0 &&
 571                    params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
 572                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 573                return err;
 574
 575        case V4L2_CID_MPEG_AUDIO_EMPHASIS:
 576                return v4l2_ctrl_query_fill(qctrl,
 577                                V4L2_MPEG_AUDIO_EMPHASIS_NONE,
 578                                V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
 579                                V4L2_MPEG_AUDIO_EMPHASIS_NONE);
 580
 581        case V4L2_CID_MPEG_AUDIO_CRC:
 582                return v4l2_ctrl_query_fill(qctrl,
 583                                V4L2_MPEG_AUDIO_CRC_NONE,
 584                                V4L2_MPEG_AUDIO_CRC_CRC16, 1,
 585                                V4L2_MPEG_AUDIO_CRC_NONE);
 586
 587        case V4L2_CID_MPEG_AUDIO_MUTE:
 588                return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
 589
 590        case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
 591                err = v4l2_ctrl_query_fill(qctrl,
 592                                V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
 593                                V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
 594                                default_params.audio_ac3_bitrate);
 595                if (err)
 596                        return err;
 597                if (params->capabilities & CX2341X_CAP_HAS_AC3) {
 598                        if (params->audio_encoding !=
 599                                                   V4L2_MPEG_AUDIO_ENCODING_AC3)
 600                                qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 601                } else
 602                        qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
 603                return 0;
 604
 605        case V4L2_CID_MPEG_VIDEO_ENCODING:
 606                /* this setting is read-only for the cx2341x since the
 607                   V4L2_CID_MPEG_STREAM_TYPE really determines the
 608                   MPEG-1/2 setting */
 609                err = v4l2_ctrl_query_fill(qctrl,
 610                                           V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
 611                                           V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
 612                                           V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
 613                if (err == 0)
 614                        qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 615                return err;
 616
 617        case V4L2_CID_MPEG_VIDEO_ASPECT:
 618                return v4l2_ctrl_query_fill(qctrl,
 619                                V4L2_MPEG_VIDEO_ASPECT_1x1,
 620                                V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
 621                                V4L2_MPEG_VIDEO_ASPECT_4x3);
 622
 623        case V4L2_CID_MPEG_VIDEO_B_FRAMES:
 624                return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
 625
 626        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
 627                return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
 628                                params->is_50hz ? 12 : 15);
 629
 630        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 631                return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
 632
 633        case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 634                err = v4l2_ctrl_query_fill(qctrl,
 635                                V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
 636                                V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
 637                                V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 638                if (err == 0 &&
 639                    params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
 640                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 641                return err;
 642
 643        case V4L2_CID_MPEG_VIDEO_BITRATE:
 644                return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
 645
 646        case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
 647                err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
 648                if (err == 0 &&
 649                    params->video_bitrate_mode ==
 650                                V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 651                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 652                return err;
 653
 654        case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
 655                return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
 656
 657        case V4L2_CID_MPEG_VIDEO_MUTE:
 658                return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
 659
 660        case V4L2_CID_MPEG_VIDEO_MUTE_YUV:  /* Init YUV (really YCbCr) to black */
 661                return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
 662
 663        /* CX23415/6 specific */
 664        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 665                return cx2341x_ctrl_query_fill(qctrl,
 666                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
 667                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
 668                        default_params.video_spatial_filter_mode);
 669
 670        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
 671                cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
 672                                default_params.video_spatial_filter);
 673                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 674                if (params->video_spatial_filter_mode ==
 675                            V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
 676                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 677                return 0;
 678
 679        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 680                cx2341x_ctrl_query_fill(qctrl,
 681                        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
 682                        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
 683                        1,
 684                        default_params.video_luma_spatial_filter_type);
 685                if (params->video_spatial_filter_mode ==
 686                            V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
 687                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 688                return 0;
 689
 690        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 691                cx2341x_ctrl_query_fill(qctrl,
 692                    V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
 693                    V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
 694                    1,
 695                    default_params.video_chroma_spatial_filter_type);
 696                if (params->video_spatial_filter_mode ==
 697                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
 698                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 699                return 0;
 700
 701        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 702                return cx2341x_ctrl_query_fill(qctrl,
 703                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
 704                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
 705                        default_params.video_temporal_filter_mode);
 706
 707        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
 708                cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
 709                                default_params.video_temporal_filter);
 710                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 711                if (params->video_temporal_filter_mode ==
 712                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
 713                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 714                return 0;
 715
 716        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 717                return cx2341x_ctrl_query_fill(qctrl,
 718                        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
 719                        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
 720                        default_params.video_median_filter_type);
 721
 722        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
 723                cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
 724                                default_params.video_luma_median_filter_top);
 725                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 726                if (params->video_median_filter_type ==
 727                                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
 728                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 729                return 0;
 730
 731        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
 732                cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
 733                                default_params.video_luma_median_filter_bottom);
 734                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 735                if (params->video_median_filter_type ==
 736                                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
 737                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 738                return 0;
 739
 740        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
 741                cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
 742                                default_params.video_chroma_median_filter_top);
 743                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 744                if (params->video_median_filter_type ==
 745                                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
 746                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 747                return 0;
 748
 749        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
 750                cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
 751                        default_params.video_chroma_median_filter_bottom);
 752                qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 753                if (params->video_median_filter_type ==
 754                                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
 755                        qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 756                return 0;
 757
 758        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
 759                return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
 760                                default_params.stream_insert_nav_packets);
 761
 762        default:
 763                return -EINVAL;
 764
 765        }
 766}
 767EXPORT_SYMBOL(cx2341x_ctrl_query);
 768
 769const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
 770{
 771        static const char *mpeg_stream_type_without_ts[] = {
 772                "MPEG-2 Program Stream",
 773                "",
 774                "MPEG-1 System Stream",
 775                "MPEG-2 DVD-compatible Stream",
 776                "MPEG-1 VCD-compatible Stream",
 777                "MPEG-2 SVCD-compatible Stream",
 778                NULL
 779        };
 780
 781        static const char *mpeg_stream_type_with_ts[] = {
 782                "MPEG-2 Program Stream",
 783                "MPEG-2 Transport Stream",
 784                "MPEG-1 System Stream",
 785                "MPEG-2 DVD-compatible Stream",
 786                "MPEG-1 VCD-compatible Stream",
 787                "MPEG-2 SVCD-compatible Stream",
 788                NULL
 789        };
 790
 791        static const char *mpeg_audio_encoding_l2_ac3[] = {
 792                "",
 793                "MPEG-1/2 Layer II",
 794                "",
 795                "",
 796                "AC-3",
 797                NULL
 798        };
 799
 800        static const char *cx2341x_video_spatial_filter_mode_menu[] = {
 801                "Manual",
 802                "Auto",
 803                NULL
 804        };
 805
 806        static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
 807                "Off",
 808                "1D Horizontal",
 809                "1D Vertical",
 810                "2D H/V Separable",
 811                "2D Symmetric non-separable",
 812                NULL
 813        };
 814
 815        static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
 816                "Off",
 817                "1D Horizontal",
 818                NULL
 819        };
 820
 821        static const char *cx2341x_video_temporal_filter_mode_menu[] = {
 822                "Manual",
 823                "Auto",
 824                NULL
 825        };
 826
 827        static const char *cx2341x_video_median_filter_type_menu[] = {
 828                "Off",
 829                "Horizontal",
 830                "Vertical",
 831                "Horizontal/Vertical",
 832                "Diagonal",
 833                NULL
 834        };
 835
 836        switch (id) {
 837        case V4L2_CID_MPEG_STREAM_TYPE:
 838                return (p->capabilities & CX2341X_CAP_HAS_TS) ?
 839                        mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
 840        case V4L2_CID_MPEG_AUDIO_ENCODING:
 841                return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
 842                        mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
 843        case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
 844        case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
 845                return NULL;
 846        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
 847                return cx2341x_video_spatial_filter_mode_menu;
 848        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
 849                return cx2341x_video_luma_spatial_filter_type_menu;
 850        case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
 851                return cx2341x_video_chroma_spatial_filter_type_menu;
 852        case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
 853                return cx2341x_video_temporal_filter_mode_menu;
 854        case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
 855                return cx2341x_video_median_filter_type_menu;
 856        default:
 857                return v4l2_ctrl_get_menu(id);
 858        }
 859}
 860EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
 861
 862/* definitions for audio properties bits 29-28 */
 863#define CX2341X_AUDIO_ENCODING_METHOD_MPEG      0
 864#define CX2341X_AUDIO_ENCODING_METHOD_AC3       1
 865#define CX2341X_AUDIO_ENCODING_METHOD_LPCM      2
 866
 867static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
 868{
 869        params->audio_properties =
 870                (params->audio_sampling_freq << 0) |
 871                (params->audio_mode << 8) |
 872                (params->audio_mode_extension << 10) |
 873                (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
 874                  ? 3 : params->audio_emphasis) << 12) |
 875                (params->audio_crc << 14);
 876
 877        if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
 878            params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
 879                params->audio_properties |=
 880                        /* Not sure if this MPEG Layer II setting is required */
 881                        ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
 882                        (params->audio_ac3_bitrate << 4) |
 883                        (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
 884        } else {
 885                /* Assuming MPEG Layer II */
 886                params->audio_properties |=
 887                        ((3 - params->audio_encoding) << 2) |
 888                        ((1 + params->audio_l2_bitrate) << 4);
 889        }
 890}
 891
 892int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
 893                  struct v4l2_ext_controls *ctrls, unsigned int cmd)
 894{
 895        int err = 0;
 896        int i;
 897
 898        if (cmd == VIDIOC_G_EXT_CTRLS) {
 899                for (i = 0; i < ctrls->count; i++) {
 900                        struct v4l2_ext_control *ctrl = ctrls->controls + i;
 901
 902                        err = cx2341x_get_ctrl(params, ctrl);
 903                        if (err) {
 904                                ctrls->error_idx = i;
 905                                break;
 906                        }
 907                }
 908                return err;
 909        }
 910        for (i = 0; i < ctrls->count; i++) {
 911                struct v4l2_ext_control *ctrl = ctrls->controls + i;
 912                struct v4l2_queryctrl qctrl;
 913                const char **menu_items = NULL;
 914
 915                qctrl.id = ctrl->id;
 916                err = cx2341x_ctrl_query(params, &qctrl);
 917                if (err)
 918                        break;
 919                if (qctrl.type == V4L2_CTRL_TYPE_MENU)
 920                        menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
 921                err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
 922                if (err)
 923                        break;
 924                err = cx2341x_set_ctrl(params, busy, ctrl);
 925                if (err)
 926                        break;
 927        }
 928        if (err == 0 &&
 929            params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
 930            params->video_bitrate_peak < params->video_bitrate) {
 931                err = -ERANGE;
 932                ctrls->error_idx = ctrls->count;
 933        }
 934        if (err)
 935                ctrls->error_idx = i;
 936        else
 937                cx2341x_calc_audio_properties(params);
 938        return err;
 939}
 940EXPORT_SYMBOL(cx2341x_ext_ctrls);
 941
 942void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
 943{
 944        *p = default_params;
 945        cx2341x_calc_audio_properties(p);
 946}
 947EXPORT_SYMBOL(cx2341x_fill_defaults);
 948
 949static int cx2341x_api(void *priv, cx2341x_mbox_func func,
 950                       u32 cmd, int args, ...)
 951{
 952        u32 data[CX2341X_MBOX_MAX_DATA];
 953        va_list vargs;
 954        int i;
 955
 956        va_start(vargs, args);
 957
 958        for (i = 0; i < args; i++)
 959                data[i] = va_arg(vargs, int);
 960        va_end(vargs);
 961        return func(priv, cmd, args, 0, data);
 962}
 963
 964#define NEQ(field) (old->field != new->field)
 965
 966int cx2341x_update(void *priv, cx2341x_mbox_func func,
 967                   const struct cx2341x_mpeg_params *old,
 968                   const struct cx2341x_mpeg_params *new)
 969{
 970        static int mpeg_stream_type[] = {
 971                0,      /* MPEG-2 PS */
 972                1,      /* MPEG-2 TS */
 973                2,      /* MPEG-1 SS */
 974                14,     /* DVD */
 975                11,     /* VCD */
 976                12,     /* SVCD */
 977        };
 978
 979        int err = 0;
 980        int force = (old == NULL);
 981        u16 temporal = new->video_temporal_filter;
 982
 983        cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
 984
 985        if (force || NEQ(is_50hz)) {
 986                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
 987                                  new->is_50hz);
 988                if (err) return err;
 989        }
 990
 991        if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
 992                u16 w = new->width;
 993                u16 h = new->height;
 994
 995                if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
 996                        w /= 2;
 997                        h /= 2;
 998                }
 999                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
1000                                  h, w);
1001                if (err) return err;
1002        }
1003
1004        if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
1005                /* Adjust temporal filter if necessary. The problem with the
1006                   temporal filter is that it works well with full resolution
1007                   capturing, but not when the capture window is scaled (the
1008                   filter introduces a ghosting effect). So if the capture
1009                   window is scaled, then force the filter to 0.
1010
1011                   For full resolution the filter really improves the video
1012                   quality, especially if the original video quality is
1013                   suboptimal. */
1014                temporal = 0;
1015        }
1016
1017        if (force || NEQ(stream_type)) {
1018                err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1019                                  mpeg_stream_type[new->stream_type]);
1020                if (err) return err;
1021        }
1022        if (force || NEQ(video_aspect)) {
1023                err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1024                                  1 + new->video_aspect);
1025                if (err) return err;
1026        }
1027        if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1028                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1029                                new->video_gop_size, new->video_b_frames + 1);
1030                if (err) return err;
1031        }
1032        if (force || NEQ(video_gop_closure)) {
1033                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1034                                  new->video_gop_closure);
1035                if (err) return err;
1036        }
1037        if (force || NEQ(audio_properties)) {
1038                err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1039                                  1, new->audio_properties);
1040                if (err) return err;
1041        }
1042        if (force || NEQ(audio_mute)) {
1043                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1044                                  new->audio_mute);
1045                if (err) return err;
1046        }
1047        if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1048                                                NEQ(video_bitrate_peak)) {
1049                err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1050                                new->video_bitrate_mode, new->video_bitrate,
1051                                new->video_bitrate_peak / 400, 0, 0);
1052                if (err) return err;
1053        }
1054        if (force || NEQ(video_spatial_filter_mode) ||
1055                     NEQ(video_temporal_filter_mode) ||
1056                     NEQ(video_median_filter_type)) {
1057                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1058                                  2, new->video_spatial_filter_mode |
1059                                        (new->video_temporal_filter_mode << 1),
1060                                new->video_median_filter_type);
1061                if (err) return err;
1062        }
1063        if (force || NEQ(video_luma_median_filter_bottom) ||
1064                     NEQ(video_luma_median_filter_top) ||
1065                     NEQ(video_chroma_median_filter_bottom) ||
1066                     NEQ(video_chroma_median_filter_top)) {
1067                err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1068                                new->video_luma_median_filter_bottom,
1069                                new->video_luma_median_filter_top,
1070                                new->video_chroma_median_filter_bottom,
1071                                new->video_chroma_median_filter_top);
1072                if (err) return err;
1073        }
1074        if (force || NEQ(video_luma_spatial_filter_type) ||
1075                     NEQ(video_chroma_spatial_filter_type)) {
1076                err = cx2341x_api(priv, func,
1077                                  CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1078                                  2, new->video_luma_spatial_filter_type,
1079                                  new->video_chroma_spatial_filter_type);
1080                if (err) return err;
1081        }
1082        if (force || NEQ(video_spatial_filter) ||
1083                     old->video_temporal_filter != temporal) {
1084                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1085                                  2, new->video_spatial_filter, temporal);
1086                if (err) return err;
1087        }
1088        if (force || NEQ(video_temporal_decimation)) {
1089                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1090                                  1, new->video_temporal_decimation);
1091                if (err) return err;
1092        }
1093        if (force || NEQ(video_mute) ||
1094                (new->video_mute && NEQ(video_mute_yuv))) {
1095                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1096                                new->video_mute | (new->video_mute_yuv << 8));
1097                if (err) return err;
1098        }
1099        if (force || NEQ(stream_insert_nav_packets)) {
1100                err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1101                                7, new->stream_insert_nav_packets);
1102                if (err) return err;
1103        }
1104        return 0;
1105}
1106EXPORT_SYMBOL(cx2341x_update);
1107
1108static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1109{
1110        const char **menu = cx2341x_ctrl_get_menu(p, id);
1111        struct v4l2_ext_control ctrl;
1112
1113        if (menu == NULL)
1114                goto invalid;
1115        ctrl.id = id;
1116        if (cx2341x_get_ctrl(p, &ctrl))
1117                goto invalid;
1118        while (ctrl.value-- && *menu) menu++;
1119        if (*menu == NULL)
1120                goto invalid;
1121        return *menu;
1122
1123invalid:
1124        return "<invalid>";
1125}
1126
1127void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1128{
1129        int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1130        int temporal = p->video_temporal_filter;
1131
1132        /* Stream */
1133        printk(KERN_INFO "%s: Stream: %s",
1134                prefix,
1135                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1136        if (p->stream_insert_nav_packets)
1137                printk(" (with navigation packets)");
1138        printk("\n");
1139        printk(KERN_INFO "%s: VBI Format: %s\n",
1140                prefix,
1141                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1142
1143        /* Video */
1144        printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1145                prefix,
1146                p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1147                p->is_50hz ? 25 : 30,
1148                (p->video_mute) ? " (muted)" : "");
1149        printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1150                prefix,
1151                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1152                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1153                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1154                p->video_bitrate);
1155        if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1156                printk(", Peak %d", p->video_bitrate_peak);
1157        printk("\n");
1158        printk(KERN_INFO
1159                "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1160                prefix,
1161                p->video_gop_size, p->video_b_frames,
1162                p->video_gop_closure ? "" : "No ");
1163        if (p->video_temporal_decimation)
1164                printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1165                        prefix, p->video_temporal_decimation);
1166
1167        /* Audio */
1168        printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1169                prefix,
1170                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1171                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1172                cx2341x_menu_item(p,
1173                           p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1174                                              ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1175                                              : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1176                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1177                p->audio_mute ? " (muted)" : "");
1178        if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1179                printk(", %s", cx2341x_menu_item(p,
1180                                V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1181        printk(", %s, %s\n",
1182                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1183                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1184
1185        /* Encoding filters */
1186        printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1187                prefix,
1188                cx2341x_menu_item(p,
1189                    V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1190                cx2341x_menu_item(p,
1191                    V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1192                cx2341x_menu_item(p,
1193                    V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1194                p->video_spatial_filter);
1195
1196        if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1197                temporal = 0;
1198
1199        printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1200                prefix,
1201                cx2341x_menu_item(p,
1202                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1203                temporal);
1204        printk(KERN_INFO
1205                "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1206                prefix,
1207                cx2341x_menu_item(p,
1208                        V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1209                p->video_luma_median_filter_bottom,
1210                p->video_luma_median_filter_top,
1211                p->video_chroma_median_filter_bottom,
1212                p->video_chroma_median_filter_top);
1213}
1214EXPORT_SYMBOL(cx2341x_log_status);
1215
1216/*
1217 * Local variables:
1218 * c-basic-offset: 8
1219 * End:
1220 */
1221
1222