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