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
 934int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
 935                  struct v4l2_ext_controls *ctrls, unsigned int cmd)
 936{
 937        int err = 0;
 938        int i;
 939
 940        if (cmd == VIDIOC_G_EXT_CTRLS) {
 941                for (i = 0; i < ctrls->count; i++) {
 942                        struct v4l2_ext_control *ctrl = ctrls->controls + i;
 943
 944                        err = cx2341x_get_ctrl(params, ctrl);
 945                        if (err) {
 946                                ctrls->error_idx = i;
 947                                break;
 948                        }
 949                }
 950                return err;
 951        }
 952        for (i = 0; i < ctrls->count; i++) {
 953                struct v4l2_ext_control *ctrl = ctrls->controls + i;
 954                struct v4l2_queryctrl qctrl;
 955                const char * const *menu_items = NULL;
 956
 957                qctrl.id = ctrl->id;
 958                err = cx2341x_ctrl_query(params, &qctrl);
 959                if (err)
 960                        break;
 961                if (qctrl.type == V4L2_CTRL_TYPE_MENU)
 962                        menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
 963                err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
 964                if (err)
 965                        break;
 966                err = cx2341x_set_ctrl(params, busy, ctrl);
 967                if (err)
 968                        break;
 969        }
 970        if (err == 0 &&
 971            params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
 972            params->video_bitrate_peak < params->video_bitrate) {
 973                err = -ERANGE;
 974                ctrls->error_idx = ctrls->count;
 975        }
 976        if (err)
 977                ctrls->error_idx = i;
 978        else
 979                cx2341x_calc_audio_properties(params);
 980        return err;
 981}
 982EXPORT_SYMBOL(cx2341x_ext_ctrls);
 983
 984void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
 985{
 986        *p = default_params;
 987        cx2341x_calc_audio_properties(p);
 988}
 989EXPORT_SYMBOL(cx2341x_fill_defaults);
 990
 991static int cx2341x_api(void *priv, cx2341x_mbox_func func,
 992                       u32 cmd, int args, ...)
 993{
 994        u32 data[CX2341X_MBOX_MAX_DATA];
 995        va_list vargs;
 996        int i;
 997
 998        va_start(vargs, args);
 999
1000        for (i = 0; i < args; i++)
1001                data[i] = va_arg(vargs, int);
1002        va_end(vargs);
1003        return func(priv, cmd, args, 0, data);
1004}
1005
1006#define NEQ(field) (old->field != new->field)
1007
1008int cx2341x_update(void *priv, cx2341x_mbox_func func,
1009                   const struct cx2341x_mpeg_params *old,
1010                   const struct cx2341x_mpeg_params *new)
1011{
1012        static int mpeg_stream_type[] = {
1013                0,      /* MPEG-2 PS */
1014                1,      /* MPEG-2 TS */
1015                2,      /* MPEG-1 SS */
1016                14,     /* DVD */
1017                11,     /* VCD */
1018                12,     /* SVCD */
1019        };
1020
1021        int err = 0;
1022        int force = (old == NULL);
1023        u16 temporal = new->video_temporal_filter;
1024
1025        cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
1026
1027        if (force || NEQ(is_50hz)) {
1028                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
1029                                  new->is_50hz);
1030                if (err) return err;
1031        }
1032
1033        if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
1034                u16 w = new->width;
1035                u16 h = new->height;
1036
1037                if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
1038                        w /= 2;
1039                        h /= 2;
1040                }
1041                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
1042                                  h, w);
1043                if (err) return err;
1044        }
1045        if (force || NEQ(stream_type)) {
1046                err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
1047                                  mpeg_stream_type[new->stream_type]);
1048                if (err) return err;
1049        }
1050        if (force || NEQ(video_aspect)) {
1051                err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
1052                                  1 + new->video_aspect);
1053                if (err) return err;
1054        }
1055        if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
1056                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1057                                new->video_gop_size, new->video_b_frames + 1);
1058                if (err) return err;
1059        }
1060        if (force || NEQ(video_gop_closure)) {
1061                err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
1062                                  new->video_gop_closure);
1063                if (err) return err;
1064        }
1065        if (force || NEQ(audio_properties)) {
1066                err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
1067                                  1, new->audio_properties);
1068                if (err) return err;
1069        }
1070        if (force || NEQ(audio_mute)) {
1071                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
1072                                  new->audio_mute);
1073                if (err) return err;
1074        }
1075        if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
1076                                                NEQ(video_bitrate_peak)) {
1077                err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
1078                                new->video_bitrate_mode, new->video_bitrate,
1079                                new->video_bitrate_peak / 400, 0, 0);
1080                if (err) return err;
1081        }
1082        if (force || NEQ(video_spatial_filter_mode) ||
1083                     NEQ(video_temporal_filter_mode) ||
1084                     NEQ(video_median_filter_type)) {
1085                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
1086                                  2, new->video_spatial_filter_mode |
1087                                        (new->video_temporal_filter_mode << 1),
1088                                new->video_median_filter_type);
1089                if (err) return err;
1090        }
1091        if (force || NEQ(video_luma_median_filter_bottom) ||
1092                     NEQ(video_luma_median_filter_top) ||
1093                     NEQ(video_chroma_median_filter_bottom) ||
1094                     NEQ(video_chroma_median_filter_top)) {
1095                err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
1096                                new->video_luma_median_filter_bottom,
1097                                new->video_luma_median_filter_top,
1098                                new->video_chroma_median_filter_bottom,
1099                                new->video_chroma_median_filter_top);
1100                if (err) return err;
1101        }
1102        if (force || NEQ(video_luma_spatial_filter_type) ||
1103                     NEQ(video_chroma_spatial_filter_type)) {
1104                err = cx2341x_api(priv, func,
1105                                  CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
1106                                  2, new->video_luma_spatial_filter_type,
1107                                  new->video_chroma_spatial_filter_type);
1108                if (err) return err;
1109        }
1110        if (force || NEQ(video_spatial_filter) ||
1111                     old->video_temporal_filter != temporal) {
1112                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
1113                                  2, new->video_spatial_filter, temporal);
1114                if (err) return err;
1115        }
1116        if (force || NEQ(video_temporal_decimation)) {
1117                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
1118                                  1, new->video_temporal_decimation);
1119                if (err) return err;
1120        }
1121        if (force || NEQ(video_mute) ||
1122                (new->video_mute && NEQ(video_mute_yuv))) {
1123                err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
1124                                new->video_mute | (new->video_mute_yuv << 8));
1125                if (err) return err;
1126        }
1127        if (force || NEQ(stream_insert_nav_packets)) {
1128                err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
1129                                7, new->stream_insert_nav_packets);
1130                if (err) return err;
1131        }
1132        return 0;
1133}
1134EXPORT_SYMBOL(cx2341x_update);
1135
1136static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
1137{
1138        const char * const *menu = cx2341x_ctrl_get_menu(p, id);
1139        struct v4l2_ext_control ctrl;
1140
1141        if (menu == NULL)
1142                goto invalid;
1143        ctrl.id = id;
1144        if (cx2341x_get_ctrl(p, &ctrl))
1145                goto invalid;
1146        while (ctrl.value-- && *menu) menu++;
1147        if (*menu == NULL)
1148                goto invalid;
1149        return *menu;
1150
1151invalid:
1152        return "<invalid>";
1153}
1154
1155void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1156{
1157        int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1158
1159        /* Stream */
1160        printk(KERN_INFO "%s: Stream: %s",
1161                prefix,
1162                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
1163        if (p->stream_insert_nav_packets)
1164                printk(" (with navigation packets)");
1165        printk("\n");
1166        printk(KERN_INFO "%s: VBI Format: %s\n",
1167                prefix,
1168                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
1169
1170        /* Video */
1171        printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
1172                prefix,
1173                p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
1174                p->is_50hz ? 25 : 30,
1175                (p->video_mute) ? " (muted)" : "");
1176        printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
1177                prefix,
1178                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
1179                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
1180                cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
1181                p->video_bitrate);
1182        if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
1183                printk(", Peak %d", p->video_bitrate_peak);
1184        printk("\n");
1185        printk(KERN_INFO
1186                "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
1187                prefix,
1188                p->video_gop_size, p->video_b_frames,
1189                p->video_gop_closure ? "" : "No ");
1190        if (p->video_temporal_decimation)
1191                printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
1192                        prefix, p->video_temporal_decimation);
1193
1194        /* Audio */
1195        printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
1196                prefix,
1197                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
1198                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
1199                cx2341x_menu_item(p,
1200                           p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
1201                                              ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
1202                                              : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
1203                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
1204                p->audio_mute ? " (muted)" : "");
1205        if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
1206                printk(", %s", cx2341x_menu_item(p,
1207                                V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
1208        printk(", %s, %s\n",
1209                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
1210                cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
1211
1212        /* Encoding filters */
1213        printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
1214                prefix,
1215                cx2341x_menu_item(p,
1216                    V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
1217                cx2341x_menu_item(p,
1218                    V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
1219                cx2341x_menu_item(p,
1220                    V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1221                p->video_spatial_filter);
1222
1223        printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1224                prefix,
1225                cx2341x_menu_item(p,
1226                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1227                p->video_temporal_filter);
1228        printk(KERN_INFO
1229                "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
1230                prefix,
1231                cx2341x_menu_item(p,
1232                        V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
1233                p->video_luma_median_filter_bottom,
1234                p->video_luma_median_filter_top,
1235                p->video_chroma_median_filter_bottom,
1236                p->video_chroma_median_filter_top);
1237}
1238EXPORT_SYMBOL(cx2341x_log_status);
1239
1240
1241
1242/********************** NEW CODE *********************/
1243
1244static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl)
1245{
1246        return container_of(ctrl->handler, struct cx2341x_handler, hdl);
1247}
1248
1249static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
1250                       u32 cmd, int args, ...)
1251{
1252        u32 data[CX2341X_MBOX_MAX_DATA];
1253        va_list vargs;
1254        int i;
1255
1256        va_start(vargs, args);
1257
1258        for (i = 0; i < args; i++)
1259                data[i] = va_arg(vargs, int);
1260        va_end(vargs);
1261        return hdl->func(hdl->priv, cmd, args, 0, data);
1262}
1263
1264/* ctrl->handler->lock is held, so it is safe to access cur.val */
1265static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
1266{
1267        return ctrl && ctrl->val != ctrl->cur.val;
1268}
1269
1270static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
1271{
1272        struct cx2341x_handler *hdl = to_cxhdl(ctrl);
1273        s32 val = ctrl->val;
1274
1275        switch (ctrl->id) {
1276        case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
1277                /* video gop cluster */
1278                int b = val + 1;
1279                int gop = hdl->video_gop_size->val;
1280
1281                gop = b * ((gop + b - 1) / b);
1282
1283                /* Max GOP size = 34 */
1284                while (gop > 34)
1285                        gop -= b;
1286                hdl->video_gop_size->val = gop;
1287                break;
1288        }
1289
1290        case V4L2_CID_MPEG_STREAM_TYPE:
1291                /* stream type cluster */
1292                hdl->video_encoding->val =
1293                    (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
1294                     hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
1295                        V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
1296                        V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
1297                if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
1298                        /* MPEG-1 implies CBR */
1299                        hdl->video_bitrate_mode->val =
1300                                V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
1301                /* peak bitrate shall be >= normal bitrate */
1302                if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
1303                    hdl->video_bitrate_peak->val < hdl->video_bitrate->val)
1304                        hdl->video_bitrate_peak->val = hdl->video_bitrate->val;
1305                break;
1306        }
1307        return 0;
1308}
1309
1310static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl)
1311{
1312        static const int mpeg_stream_type[] = {
1313                0,      /* MPEG-2 PS */
1314                1,      /* MPEG-2 TS */
1315                2,      /* MPEG-1 SS */
1316                14,     /* DVD */
1317                11,     /* VCD */
1318                12,     /* SVCD */
1319        };
1320        struct cx2341x_handler *hdl = to_cxhdl(ctrl);
1321        s32 val = ctrl->val;
1322        u32 props;
1323        int err;
1324
1325        switch (ctrl->id) {
1326        case V4L2_CID_MPEG_STREAM_VBI_FMT:
1327                if (hdl->ops && hdl->ops->s_stream_vbi_fmt)
1328                        return hdl->ops->s_stream_vbi_fmt(hdl, val);
1329                return 0;
1330
1331        case V4L2_CID_MPEG_VIDEO_ASPECT:
1332                return cx2341x_hdl_api(hdl,
1333                        CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1);
1334
1335        case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
1336                return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val);
1337
1338        case V4L2_CID_MPEG_AUDIO_MUTE:
1339                return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val);
1340
1341        case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
1342                return cx2341x_hdl_api(hdl,
1343                        CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val);
1344
1345        case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
1346                return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val);
1347
1348        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
1349                /* audio properties cluster */
1350                props = (hdl->audio_sampling_freq->val << 0) |
1351                        (hdl->audio_mode->val << 8) |
1352                        (hdl->audio_mode_extension->val << 10) |
1353                        (hdl->audio_crc->val << 14);
1354                if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
1355                        props |= 3 << 12;
1356                else
1357                        props |= hdl->audio_emphasis->val << 12;
1358
1359                if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) {
1360                        props |=
1361#if 1
1362                                /* Not sure if this MPEG Layer II setting is required */
1363                                ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
1364#endif
1365                                (hdl->audio_ac3_bitrate->val << 4) |
1366                                (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
1367                } else {
1368                        /* Assuming MPEG Layer II */
1369                        props |=
1370                                ((3 - hdl->audio_encoding->val) << 2) |
1371                                ((1 + hdl->audio_l2_bitrate->val) << 4);
1372                }
1373                err = cx2341x_hdl_api(hdl,
1374                                CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props);
1375                if (err)
1376                        return err;
1377
1378                hdl->audio_properties = props;
1379                if (hdl->audio_ac3_bitrate) {
1380                        int is_ac3 = hdl->audio_encoding->val ==
1381                                                V4L2_MPEG_AUDIO_ENCODING_AC3;
1382
1383                        v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3);
1384                        v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3);
1385                }
1386                v4l2_ctrl_activate(hdl->audio_mode_extension,
1387                        hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO);
1388                if (cx2341x_neq(hdl->audio_sampling_freq) &&
1389                    hdl->ops && hdl->ops->s_audio_sampling_freq)
1390                        return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val);
1391                if (cx2341x_neq(hdl->audio_mode) &&
1392                    hdl->ops && hdl->ops->s_audio_mode)
1393                        return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val);
1394                return 0;
1395
1396        case V4L2_CID_MPEG_VIDEO_B_FRAMES:
1397                /* video gop cluster */
1398                return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1399                                hdl->video_gop_size->val,
1400                                hdl->video_b_frames->val + 1);
1401
1402        case V4L2_CID_MPEG_STREAM_TYPE:
1403                /* stream type cluster */
1404                err = cx2341x_hdl_api(hdl,
1405                        CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]);
1406                if (err)
1407                        return err;
1408
1409                err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5,
1410                                hdl->video_bitrate_mode->val,
1411                                hdl->video_bitrate->val,
1412                                hdl->video_bitrate_peak->val / 400, 0, 0);
1413                if (err)
1414                        return err;
1415
1416                v4l2_ctrl_activate(hdl->video_bitrate_mode,
1417                        hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1);
1418                v4l2_ctrl_activate(hdl->video_bitrate_peak,
1419                        hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
1420                if (cx2341x_neq(hdl->video_encoding) &&
1421                    hdl->ops && hdl->ops->s_video_encoding)
1422                        return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val);
1423                return 0;
1424
1425        case V4L2_CID_MPEG_VIDEO_MUTE:
1426                /* video mute cluster */
1427                return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1,
1428                                hdl->video_mute->val |
1429                                        (hdl->video_mute_yuv->val << 8));
1430
1431        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: {
1432                int active_filter;
1433
1434                /* video filter mode */
1435                err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
1436                                hdl->video_spatial_filter_mode->val |
1437                                        (hdl->video_temporal_filter_mode->val << 1),
1438                                hdl->video_median_filter_type->val);
1439                if (err)
1440                        return err;
1441
1442                active_filter = hdl->video_spatial_filter_mode->val !=
1443                                V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO;
1444                v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter);
1445                v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter);
1446                v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter);
1447                active_filter = hdl->video_temporal_filter_mode->val !=
1448                                V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO;
1449                v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter);
1450                active_filter = hdl->video_median_filter_type->val !=
1451                                V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF;
1452                v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter);
1453                v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter);
1454                v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter);
1455                v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter);
1456                return 0;
1457        }
1458
1459        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
1460                /* video filter type cluster */
1461                return cx2341x_hdl_api(hdl,
1462                                CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
1463                                hdl->video_luma_spatial_filter_type->val,
1464                                hdl->video_chroma_spatial_filter_type->val);
1465
1466        case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
1467                /* video filter cluster */
1468                return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
1469                                hdl->video_spatial_filter->val,
1470                                hdl->video_temporal_filter->val);
1471
1472        case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
1473                /* video median cluster */
1474                return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4,
1475                                hdl->video_luma_median_filter_bottom->val,
1476                                hdl->video_luma_median_filter_top->val,
1477                                hdl->video_chroma_median_filter_bottom->val,
1478                                hdl->video_chroma_median_filter_top->val);
1479        }
1480        return -EINVAL;
1481}
1482
1483static const struct v4l2_ctrl_ops cx2341x_ops = {
1484        .try_ctrl = cx2341x_try_ctrl,
1485        .s_ctrl = cx2341x_s_ctrl,
1486};
1487
1488static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
1489                        u32 id, s32 min, s32 max, s32 step, s32 def)
1490{
1491        struct v4l2_ctrl_config cfg;
1492
1493        cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);
1494        cfg.ops = &cx2341x_ops;
1495        cfg.id = id;
1496        cfg.min = min;
1497        cfg.max = max;
1498        cfg.def = def;
1499        if (cfg.type == V4L2_CTRL_TYPE_MENU) {
1500                cfg.step = 0;
1501                cfg.menu_skip_mask = step;
1502                cfg.qmenu = cx2341x_get_menu(id);
1503        } else {
1504                cfg.step = step;
1505                cfg.menu_skip_mask = 0;
1506        }
1507        return v4l2_ctrl_new_custom(hdl, &cfg, NULL);
1508}
1509
1510static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
1511                        u32 id, s32 min, s32 max, s32 step, s32 def)
1512{
1513        return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def);
1514}
1515
1516static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl,
1517                        u32 id, s32 max, s32 mask, s32 def)
1518{
1519        return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def);
1520}
1521
1522int cx2341x_handler_init(struct cx2341x_handler *cxhdl,
1523                         unsigned nr_of_controls_hint)
1524{
1525        struct v4l2_ctrl_handler *hdl = &cxhdl->hdl;
1526        u32 caps = cxhdl->capabilities;
1527        int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI;
1528        int has_ac3 = caps & CX2341X_CAP_HAS_AC3;
1529        int has_ts = caps & CX2341X_CAP_HAS_TS;
1530
1531        cxhdl->width = 720;
1532        cxhdl->height = 480;
1533
1534        v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);
1535
1536        /* Add controls in ascending control ID order for fastest
1537           insertion time. */
1538        cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl,
1539                        V4L2_CID_MPEG_STREAM_TYPE,
1540                        V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2,
1541                        V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
1542        cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl,
1543                        V4L2_CID_MPEG_STREAM_VBI_FMT,
1544                        V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2,
1545                        V4L2_MPEG_STREAM_VBI_FMT_NONE);
1546        cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl,
1547                        V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
1548                        V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0,
1549                        V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
1550        cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl,
1551                        V4L2_CID_MPEG_AUDIO_ENCODING,
1552                        V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2,
1553                        V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
1554        cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl,
1555                        V4L2_CID_MPEG_AUDIO_L2_BITRATE,
1556                        V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff,
1557                        V4L2_MPEG_AUDIO_L2_BITRATE_224K);
1558        cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl,
1559                        V4L2_CID_MPEG_AUDIO_MODE,
1560                        V4L2_MPEG_AUDIO_MODE_MONO, 0,
1561                        V4L2_MPEG_AUDIO_MODE_STEREO);
1562        cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl,
1563                        V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
1564                        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0,
1565                        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
1566        cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl,
1567                        V4L2_CID_MPEG_AUDIO_EMPHASIS,
1568                        V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0,
1569                        V4L2_MPEG_AUDIO_EMPHASIS_NONE);
1570        cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl,
1571                        V4L2_CID_MPEG_AUDIO_CRC,
1572                        V4L2_MPEG_AUDIO_CRC_CRC16, 0,
1573                        V4L2_MPEG_AUDIO_CRC_NONE);
1574
1575        cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0);
1576        if (has_ac3)
1577                cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl,
1578                                V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
1579                                V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03,
1580                                V4L2_MPEG_AUDIO_AC3_BITRATE_224K);
1581        cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl,
1582                        V4L2_CID_MPEG_VIDEO_ENCODING,
1583                        V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0,
1584                        V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
1585        cx2341x_ctrl_new_menu(hdl,
1586                        V4L2_CID_MPEG_VIDEO_ASPECT,
1587                        V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
1588                        V4L2_MPEG_VIDEO_ASPECT_4x3);
1589        cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl,
1590                        V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2);
1591        cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl,
1592                        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1593                        1, 34, 1, cxhdl->is_50hz ? 12 : 15);
1594        cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
1595        cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl,
1596                        V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1597                        V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
1598                        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1599        cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl,
1600                        V4L2_CID_MPEG_VIDEO_BITRATE,
1601                        0, 27000000, 1, 6000000);
1602        cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl,
1603                        V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1604                        0, 27000000, 1, 8000000);
1605        cx2341x_ctrl_new_std(hdl,
1606                        V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0);
1607        cxhdl->video_mute = cx2341x_ctrl_new_std(hdl,
1608                        V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0);
1609        cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl,
1610                        V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080);
1611
1612        /* CX23415/6 specific */
1613        cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl,
1614                        V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
1615                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
1616                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0,
1617                        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
1618        cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl,
1619                        V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
1620                        0, 15, 1, 0);
1621        cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
1622                        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
1623                        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
1624                        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
1625                        0,
1626                        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR);
1627        cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
1628                        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
1629                        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
1630                        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
1631                        0,
1632                        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR);
1633        cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl,
1634                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
1635                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
1636                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO,
1637                        0,
1638                        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
1639        cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl,
1640                        V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
1641                        0, 31, 1, 8);
1642        cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl,
1643                        V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
1644                        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
1645                        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG,
1646                        0,
1647                        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
1648        cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
1649                        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
1650                        0, 255, 1, 0);
1651        cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
1652                        V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
1653                        0, 255, 1, 255);
1654        cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
1655                        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
1656                        0, 255, 1, 0);
1657        cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
1658                        V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
1659                        0, 255, 1, 255);
1660        cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
1661                        0, 1, 1, 0);
1662
1663        if (hdl->error) {
1664                int err = hdl->error;
1665
1666                v4l2_ctrl_handler_free(hdl);
1667                return err;
1668        }
1669
1670        v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq);
1671        v4l2_ctrl_cluster(2, &cxhdl->video_b_frames);
1672        v4l2_ctrl_cluster(5, &cxhdl->stream_type);
1673        v4l2_ctrl_cluster(2, &cxhdl->video_mute);
1674        v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode);
1675        v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type);
1676        v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter);
1677        v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top);
1678
1679        return 0;
1680}
1681EXPORT_SYMBOL(cx2341x_handler_init);
1682
1683void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz)
1684{
1685        cxhdl->is_50hz = is_50hz;
1686        cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15;
1687}
1688EXPORT_SYMBOL(cx2341x_handler_set_50hz);
1689
1690int cx2341x_handler_setup(struct cx2341x_handler *cxhdl)
1691{
1692        int h = cxhdl->height;
1693        int w = cxhdl->width;
1694        int err;
1695
1696        err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0);
1697        if (err)
1698                return err;
1699        err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz);
1700        if (err)
1701                return err;
1702
1703        if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
1704                w /= 2;
1705                h /= 2;
1706        }
1707        err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
1708        if (err)
1709                return err;
1710        return v4l2_ctrl_handler_setup(&cxhdl->hdl);
1711}
1712EXPORT_SYMBOL(cx2341x_handler_setup);
1713
1714void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy)
1715{
1716        v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy);
1717        v4l2_ctrl_grab(cxhdl->audio_encoding, busy);
1718        v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy);
1719        v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy);
1720        v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy);
1721        v4l2_ctrl_grab(cxhdl->stream_type, busy);
1722        v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy);
1723        v4l2_ctrl_grab(cxhdl->video_bitrate, busy);
1724        v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy);
1725}
1726EXPORT_SYMBOL(cx2341x_handler_set_busy);
1727