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