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        if (force || NEQ(stream_type)) {
1004                err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1005                                  mpeg_stream_type[new->stream_type]);
1006                if (err) return err;
1007        }
1008        if (force || NEQ(video_aspect)) {
1009                err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1010                                  1 + new->video_aspect);
1011                if (err) return err;
1012        }
1013        if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1014                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1015                                new->video_gop_size, new->video_b_frames + 1);
1016                if (err) return err;
1017        }
1018        if (force || NEQ(video_gop_closure)) {
1019                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1020                                  new->video_gop_closure);
1021                if (err) return err;
1022        }
1023        if (force || NEQ(audio_properties)) {
1024                err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1025                                  1, new->audio_properties);
1026                if (err) return err;
1027        }
1028        if (force || NEQ(audio_mute)) {
1029                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1030                                  new->audio_mute);
1031                if (err) return err;
1032        }
1033        if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1034                                                NEQ(video_bitrate_peak)) {
1035                err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1036                                new->video_bitrate_mode, new->video_bitrate,
1037                                new->video_bitrate_peak / 400, 0, 0);
1038                if (err) return err;
1039        }
1040        if (force || NEQ(video_spatial_filter_mode) ||
1041                     NEQ(video_temporal_filter_mode) ||
1042                     NEQ(video_median_filter_type)) {
1043                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1044                                  2, new->video_spatial_filter_mode |
1045                                        (new->video_temporal_filter_mode << 1),
1046                                new->video_median_filter_type);
1047                if (err) return err;
1048        }
1049        if (force || NEQ(video_luma_median_filter_bottom) ||
1050                     NEQ(video_luma_median_filter_top) ||
1051                     NEQ(video_chroma_median_filter_bottom) ||
1052                     NEQ(video_chroma_median_filter_top)) {
1053                err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1054                                new->video_luma_median_filter_bottom,
1055                                new->video_luma_median_filter_top,
1056                                new->video_chroma_median_filter_bottom,
1057                                new->video_chroma_median_filter_top);
1058                if (err) return err;
1059        }
1060        if (force || NEQ(video_luma_spatial_filter_type) ||
1061                     NEQ(video_chroma_spatial_filter_type)) {
1062                err = cx2341x_api(priv, func,
1063                                  CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1064                                  2, new->video_luma_spatial_filter_type,
1065                                  new->video_chroma_spatial_filter_type);
1066                if (err) return err;
1067        }
1068        if (force || NEQ(video_spatial_filter) ||
1069                     old->video_temporal_filter != temporal) {
1070                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1071                                  2, new->video_spatial_filter, temporal);
1072                if (err) return err;
1073        }
1074        if (force || NEQ(video_temporal_decimation)) {
1075                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1076                                  1, new->video_temporal_decimation);
1077                if (err) return err;
1078        }
1079        if (force || NEQ(video_mute) ||
1080                (new->video_mute && NEQ(video_mute_yuv))) {
1081                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1082                                new->video_mute | (new->video_mute_yuv << 8));
1083                if (err) return err;
1084        }
1085        if (force || NEQ(stream_insert_nav_packets)) {
1086                err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1087                                7, new->stream_insert_nav_packets);
1088                if (err) return err;
1089        }
1090        return 0;
1091}
1092EXPORT_SYMBOL(cx2341x_update);
1093
1094static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1095{
1096        const char **menu = cx2341x_ctrl_get_menu(p, id);
1097        struct v4l2_ext_control ctrl;
1098
1099        if (menu == NULL)
1100                goto invalid;
1101        ctrl.id = id;
1102        if (cx2341x_get_ctrl(p, &ctrl))
1103                goto invalid;
1104        while (ctrl.value-- && *menu) menu++;
1105        if (*menu == NULL)
1106                goto invalid;
1107        return *menu;
1108
1109invalid:
1110        return "<invalid>";
1111}
1112
1113void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1114{
1115        int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1116
1117        /* Stream */
1118        printk(KERN_INFO "%s: Stream: %s",
1119                prefix,
1120                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1121        if (p->stream_insert_nav_packets)
1122                printk(" (with navigation packets)");
1123        printk("\n");
1124        printk(KERN_INFO "%s: VBI Format: %s\n",
1125                prefix,
1126                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1127
1128        /* Video */
1129        printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1130                prefix,
1131                p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1132                p->is_50hz ? 25 : 30,
1133                (p->video_mute) ? " (muted)" : "");
1134        printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1135                prefix,
1136                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1137                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1138                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1139                p->video_bitrate);
1140        if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1141                printk(", Peak %d", p->video_bitrate_peak);
1142        printk("\n");
1143        printk(KERN_INFO
1144                "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1145                prefix,
1146                p->video_gop_size, p->video_b_frames,
1147                p->video_gop_closure ? "" : "No ");
1148        if (p->video_temporal_decimation)
1149                printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1150                        prefix, p->video_temporal_decimation);
1151
1152        /* Audio */
1153        printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1154                prefix,
1155                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1156                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1157                cx2341x_menu_item(p,
1158                           p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1159                                              ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1160                                              : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1161                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1162                p->audio_mute ? " (muted)" : "");
1163        if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1164                printk(", %s", cx2341x_menu_item(p,
1165                                V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1166        printk(", %s, %s\n",
1167                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1168                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1169
1170        /* Encoding filters */
1171        printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1172                prefix,
1173                cx2341x_menu_item(p,
1174                    V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1175                cx2341x_menu_item(p,
1176                    V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1177                cx2341x_menu_item(p,
1178                    V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1179                p->video_spatial_filter);
1180
1181        printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1182                prefix,
1183                cx2341x_menu_item(p,
1184                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1185                p->video_temporal_filter);
1186        printk(KERN_INFO
1187                "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1188                prefix,
1189                cx2341x_menu_item(p,
1190                        V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1191                p->video_luma_median_filter_bottom,
1192                p->video_luma_median_filter_top,
1193                p->video_chroma_median_filter_bottom,
1194                p->video_chroma_median_filter_top);
1195}
1196EXPORT_SYMBOL(cx2341x_log_status);
1197
1198/*
1199 * Local variables:
1200 * c-basic-offset: 8
1201 * End:
1202 */
1203
1204