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