linux/drivers/media/video/tw9910.c
<<
>>
Prefs
   1/*
   2 * tw9910 Video Driver
   3 *
   4 * Copyright (C) 2008 Renesas Solutions Corp.
   5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
   6 *
   7 * Based on ov772x driver,
   8 *
   9 * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
  10 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
  11 * Copyright (C) 2008 Magnus Damm
  12 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License version 2 as
  16 * published by the Free Software Foundation.
  17 */
  18
  19#include <linux/init.h>
  20#include <linux/module.h>
  21#include <linux/i2c.h>
  22#include <linux/slab.h>
  23#include <linux/kernel.h>
  24#include <linux/delay.h>
  25#include <linux/videodev2.h>
  26#include <media/v4l2-chip-ident.h>
  27#include <media/v4l2-subdev.h>
  28#include <media/soc_camera.h>
  29#include <media/tw9910.h>
  30
  31#define GET_ID(val)  ((val & 0xF8) >> 3)
  32#define GET_ReV(val) (val & 0x07)
  33
  34/*
  35 * register offset
  36 */
  37#define ID              0x00 /* Product ID Code Register */
  38#define STATUS1         0x01 /* Chip Status Register I */
  39#define INFORM          0x02 /* Input Format */
  40#define OPFORM          0x03 /* Output Format Control Register */
  41#define DLYCTR          0x04 /* Hysteresis and HSYNC Delay Control */
  42#define OUTCTR1         0x05 /* Output Control I */
  43#define ACNTL1          0x06 /* Analog Control Register 1 */
  44#define CROP_HI         0x07 /* Cropping Register, High */
  45#define VDELAY_LO       0x08 /* Vertical Delay Register, Low */
  46#define VACTIVE_LO      0x09 /* Vertical Active Register, Low */
  47#define HDELAY_LO       0x0A /* Horizontal Delay Register, Low */
  48#define HACTIVE_LO      0x0B /* Horizontal Active Register, Low */
  49#define CNTRL1          0x0C /* Control Register I */
  50#define VSCALE_LO       0x0D /* Vertical Scaling Register, Low */
  51#define SCALE_HI        0x0E /* Scaling Register, High */
  52#define HSCALE_LO       0x0F /* Horizontal Scaling Register, Low */
  53#define BRIGHT          0x10 /* BRIGHTNESS Control Register */
  54#define CONTRAST        0x11 /* CONTRAST Control Register */
  55#define SHARPNESS       0x12 /* SHARPNESS Control Register I */
  56#define SAT_U           0x13 /* Chroma (U) Gain Register */
  57#define SAT_V           0x14 /* Chroma (V) Gain Register */
  58#define HUE             0x15 /* Hue Control Register */
  59#define CORING1         0x17
  60#define CORING2         0x18 /* Coring and IF compensation */
  61#define VBICNTL         0x19 /* VBI Control Register */
  62#define ACNTL2          0x1A /* Analog Control 2 */
  63#define OUTCTR2         0x1B /* Output Control 2 */
  64#define SDT             0x1C /* Standard Selection */
  65#define SDTR            0x1D /* Standard Recognition */
  66#define TEST            0x1F /* Test Control Register */
  67#define CLMPG           0x20 /* Clamping Gain */
  68#define IAGC            0x21 /* Individual AGC Gain */
  69#define AGCGAIN         0x22 /* AGC Gain */
  70#define PEAKWT          0x23 /* White Peak Threshold */
  71#define CLMPL           0x24 /* Clamp level */
  72#define SYNCT           0x25 /* Sync Amplitude */
  73#define MISSCNT         0x26 /* Sync Miss Count Register */
  74#define PCLAMP          0x27 /* Clamp Position Register */
  75#define VCNTL1          0x28 /* Vertical Control I */
  76#define VCNTL2          0x29 /* Vertical Control II */
  77#define CKILL           0x2A /* Color Killer Level Control */
  78#define COMB            0x2B /* Comb Filter Control */
  79#define LDLY            0x2C /* Luma Delay and H Filter Control */
  80#define MISC1           0x2D /* Miscellaneous Control I */
  81#define LOOP            0x2E /* LOOP Control Register */
  82#define MISC2           0x2F /* Miscellaneous Control II */
  83#define MVSN            0x30 /* Macrovision Detection */
  84#define STATUS2         0x31 /* Chip STATUS II */
  85#define HFREF           0x32 /* H monitor */
  86#define CLMD            0x33 /* CLAMP MODE */
  87#define IDCNTL          0x34 /* ID Detection Control */
  88#define CLCNTL1         0x35 /* Clamp Control I */
  89#define ANAPLLCTL       0x4C
  90#define VBIMIN          0x4D
  91#define HSLOWCTL        0x4E
  92#define WSS3            0x4F
  93#define FILLDATA        0x50
  94#define SDID            0x51
  95#define DID             0x52
  96#define WSS1            0x53
  97#define WSS2            0x54
  98#define VVBI            0x55
  99#define LCTL6           0x56
 100#define LCTL7           0x57
 101#define LCTL8           0x58
 102#define LCTL9           0x59
 103#define LCTL10          0x5A
 104#define LCTL11          0x5B
 105#define LCTL12          0x5C
 106#define LCTL13          0x5D
 107#define LCTL14          0x5E
 108#define LCTL15          0x5F
 109#define LCTL16          0x60
 110#define LCTL17          0x61
 111#define LCTL18          0x62
 112#define LCTL19          0x63
 113#define LCTL20          0x64
 114#define LCTL21          0x65
 115#define LCTL22          0x66
 116#define LCTL23          0x67
 117#define LCTL24          0x68
 118#define LCTL25          0x69
 119#define LCTL26          0x6A
 120#define HSGEGIN         0x6B
 121#define HSEND           0x6C
 122#define OVSDLY          0x6D
 123#define OVSEND          0x6E
 124#define VBIDELAY        0x6F
 125
 126/*
 127 * register detail
 128 */
 129
 130/* INFORM */
 131#define FC27_ON     0x40 /* 1 : Input crystal clock frequency is 27MHz */
 132#define FC27_FF     0x00 /* 0 : Square pixel mode. */
 133                         /*     Must use 24.54MHz for 60Hz field rate */
 134                         /*     source or 29.5MHz for 50Hz field rate */
 135#define IFSEL_S     0x10 /* 01 : S-video decoding */
 136#define IFSEL_C     0x00 /* 00 : Composite video decoding */
 137                         /* Y input video selection */
 138#define YSEL_M0     0x00 /*  00 : Mux0 selected */
 139#define YSEL_M1     0x04 /*  01 : Mux1 selected */
 140#define YSEL_M2     0x08 /*  10 : Mux2 selected */
 141#define YSEL_M3     0x10 /*  11 : Mux3 selected */
 142
 143/* OPFORM */
 144#define MODE        0x80 /* 0 : CCIR601 compatible YCrCb 4:2:2 format */
 145                         /* 1 : ITU-R-656 compatible data sequence format */
 146#define LEN         0x40 /* 0 : 8-bit YCrCb 4:2:2 output format */
 147                         /* 1 : 16-bit YCrCb 4:2:2 output format.*/
 148#define LLCMODE     0x20 /* 1 : LLC output mode. */
 149                         /* 0 : free-run output mode */
 150#define AINC        0x10 /* Serial interface auto-indexing control */
 151                         /* 0 : auto-increment */
 152                         /* 1 : non-auto */
 153#define VSCTL       0x08 /* 1 : Vertical out ctrl by DVALID */
 154                         /* 0 : Vertical out ctrl by HACTIVE and DVALID */
 155#define OEN         0x04 /* Output Enable together with TRI_SEL. */
 156
 157/* OUTCTR1 */
 158#define VSP_LO      0x00 /* 0 : VS pin output polarity is active low */
 159#define VSP_HI      0x80 /* 1 : VS pin output polarity is active high. */
 160                         /* VS pin output control */
 161#define VSSL_VSYNC  0x00 /*   0 : VSYNC  */
 162#define VSSL_VACT   0x10 /*   1 : VACT   */
 163#define VSSL_FIELD  0x20 /*   2 : FIELD  */
 164#define VSSL_VVALID 0x30 /*   3 : VVALID */
 165#define VSSL_ZERO   0x70 /*   7 : 0      */
 166#define HSP_LOW     0x00 /* 0 : HS pin output polarity is active low */
 167#define HSP_HI      0x08 /* 1 : HS pin output polarity is active high.*/
 168                         /* HS pin output control */
 169#define HSSL_HACT   0x00 /*   0 : HACT   */
 170#define HSSL_HSYNC  0x01 /*   1 : HSYNC  */
 171#define HSSL_DVALID 0x02 /*   2 : DVALID */
 172#define HSSL_HLOCK  0x03 /*   3 : HLOCK  */
 173#define HSSL_ASYNCW 0x04 /*   4 : ASYNCW */
 174#define HSSL_ZERO   0x07 /*   7 : 0      */
 175
 176/* ACNTL1 */
 177#define SRESET      0x80 /* resets the device to its default state
 178                          * but all register content remain unchanged.
 179                          * This bit is self-resetting.
 180                          */
 181
 182/* VBICNTL */
 183/* RTSEL : control the real time signal
 184*          output from the MPOUT pin
 185*/
 186#define RTSEL_MASK  0x07
 187#define RTSEL_VLOSS 0x00 /* 0000 = Video loss */
 188#define RTSEL_HLOCK 0x01 /* 0001 = H-lock */
 189#define RTSEL_SLOCK 0x02 /* 0010 = S-lock */
 190#define RTSEL_VLOCK 0x03 /* 0011 = V-lock */
 191#define RTSEL_MONO  0x04 /* 0100 = MONO */
 192#define RTSEL_DET50 0x05 /* 0101 = DET50 */
 193#define RTSEL_FIELD 0x06 /* 0110 = FIELD */
 194#define RTSEL_RTCO  0x07 /* 0111 = RTCO ( Real Time Control ) */
 195
 196/*
 197 * structure
 198 */
 199
 200struct regval_list {
 201        unsigned char reg_num;
 202        unsigned char value;
 203};
 204
 205struct tw9910_scale_ctrl {
 206        char           *name;
 207        unsigned short  width;
 208        unsigned short  height;
 209        u16             hscale;
 210        u16             vscale;
 211};
 212
 213struct tw9910_cropping_ctrl {
 214        u16 vdelay;
 215        u16 vactive;
 216        u16 hdelay;
 217        u16 hactive;
 218};
 219
 220struct tw9910_hsync_ctrl {
 221        u16 start;
 222        u16 end;
 223};
 224
 225struct tw9910_priv {
 226        struct v4l2_subdev                subdev;
 227        struct tw9910_video_info       *info;
 228        const struct tw9910_scale_ctrl *scale;
 229};
 230
 231/*
 232 * register settings
 233 */
 234
 235#define ENDMARKER { 0xff, 0xff }
 236
 237static const struct regval_list tw9910_default_regs[] =
 238{
 239        { OPFORM,  0x00 },
 240        { OUTCTR1, VSP_LO | VSSL_VVALID | HSP_HI | HSSL_HSYNC },
 241        ENDMARKER,
 242};
 243
 244static const struct soc_camera_data_format tw9910_color_fmt[] = {
 245        {
 246                .name       = "VYUY",
 247                .fourcc     = V4L2_PIX_FMT_VYUY,
 248                .depth      = 16,
 249                .colorspace = V4L2_COLORSPACE_SMPTE170M,
 250        }
 251};
 252
 253static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = {
 254        {
 255                .name   = "NTSC SQ",
 256                .width  = 640,
 257                .height = 480,
 258                .hscale = 0x0100,
 259                .vscale = 0x0100,
 260        },
 261        {
 262                .name   = "NTSC CCIR601",
 263                .width  = 720,
 264                .height = 480,
 265                .hscale = 0x0100,
 266                .vscale = 0x0100,
 267        },
 268        {
 269                .name   = "NTSC SQ (CIF)",
 270                .width  = 320,
 271                .height = 240,
 272                .hscale = 0x0200,
 273                .vscale = 0x0200,
 274        },
 275        {
 276                .name   = "NTSC CCIR601 (CIF)",
 277                .width  = 360,
 278                .height = 240,
 279                .hscale = 0x0200,
 280                .vscale = 0x0200,
 281        },
 282        {
 283                .name   = "NTSC SQ (QCIF)",
 284                .width  = 160,
 285                .height = 120,
 286                .hscale = 0x0400,
 287                .vscale = 0x0400,
 288        },
 289        {
 290                .name   = "NTSC CCIR601 (QCIF)",
 291                .width  = 180,
 292                .height = 120,
 293                .hscale = 0x0400,
 294                .vscale = 0x0400,
 295        },
 296};
 297
 298static const struct tw9910_scale_ctrl tw9910_pal_scales[] = {
 299        {
 300                .name   = "PAL SQ",
 301                .width  = 768,
 302                .height = 576,
 303                .hscale = 0x0100,
 304                .vscale = 0x0100,
 305        },
 306        {
 307                .name   = "PAL CCIR601",
 308                .width  = 720,
 309                .height = 576,
 310                .hscale = 0x0100,
 311                .vscale = 0x0100,
 312        },
 313        {
 314                .name   = "PAL SQ (CIF)",
 315                .width  = 384,
 316                .height = 288,
 317                .hscale = 0x0200,
 318                .vscale = 0x0200,
 319        },
 320        {
 321                .name   = "PAL CCIR601 (CIF)",
 322                .width  = 360,
 323                .height = 288,
 324                .hscale = 0x0200,
 325                .vscale = 0x0200,
 326        },
 327        {
 328                .name   = "PAL SQ (QCIF)",
 329                .width  = 192,
 330                .height = 144,
 331                .hscale = 0x0400,
 332                .vscale = 0x0400,
 333        },
 334        {
 335                .name   = "PAL CCIR601 (QCIF)",
 336                .width  = 180,
 337                .height = 144,
 338                .hscale = 0x0400,
 339                .vscale = 0x0400,
 340        },
 341};
 342
 343static const struct tw9910_cropping_ctrl tw9910_cropping_ctrl = {
 344        .vdelay  = 0x0012,
 345        .vactive = 0x00F0,
 346        .hdelay  = 0x0010,
 347        .hactive = 0x02D0,
 348};
 349
 350static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
 351        .start = 0x0260,
 352        .end   = 0x0300,
 353};
 354
 355/*
 356 * general function
 357 */
 358static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
 359{
 360        return container_of(i2c_get_clientdata(client), struct tw9910_priv,
 361                            subdev);
 362}
 363
 364static int tw9910_set_scale(struct i2c_client *client,
 365                            const struct tw9910_scale_ctrl *scale)
 366{
 367        int ret;
 368
 369        ret = i2c_smbus_write_byte_data(client, SCALE_HI,
 370                                        (scale->vscale & 0x0F00) >> 4 |
 371                                        (scale->hscale & 0x0F00) >> 8);
 372        if (ret < 0)
 373                return ret;
 374
 375        ret = i2c_smbus_write_byte_data(client, HSCALE_LO,
 376                                        scale->hscale & 0x00FF);
 377        if (ret < 0)
 378                return ret;
 379
 380        ret = i2c_smbus_write_byte_data(client, VSCALE_LO,
 381                                        scale->vscale & 0x00FF);
 382
 383        return ret;
 384}
 385
 386static int tw9910_set_cropping(struct i2c_client *client,
 387                               const struct tw9910_cropping_ctrl *cropping)
 388{
 389        int ret;
 390
 391        ret = i2c_smbus_write_byte_data(client, CROP_HI,
 392                                        (cropping->vdelay  & 0x0300) >> 2 |
 393                                        (cropping->vactive & 0x0300) >> 4 |
 394                                        (cropping->hdelay  & 0x0300) >> 6 |
 395                                        (cropping->hactive & 0x0300) >> 8);
 396        if (ret < 0)
 397                return ret;
 398
 399        ret = i2c_smbus_write_byte_data(client, VDELAY_LO,
 400                                        cropping->vdelay & 0x00FF);
 401        if (ret < 0)
 402                return ret;
 403
 404        ret = i2c_smbus_write_byte_data(client, VACTIVE_LO,
 405                                        cropping->vactive & 0x00FF);
 406        if (ret < 0)
 407                return ret;
 408
 409        ret = i2c_smbus_write_byte_data(client, HDELAY_LO,
 410                                        cropping->hdelay & 0x00FF);
 411        if (ret < 0)
 412                return ret;
 413
 414        ret = i2c_smbus_write_byte_data(client, HACTIVE_LO,
 415                                        cropping->hactive & 0x00FF);
 416
 417        return ret;
 418}
 419
 420static int tw9910_set_hsync(struct i2c_client *client,
 421                            const struct tw9910_hsync_ctrl *hsync)
 422{
 423        int ret;
 424
 425        /* bit 10 - 3 */
 426        ret = i2c_smbus_write_byte_data(client, HSGEGIN,
 427                                        (hsync->start & 0x07F8) >> 3);
 428        if (ret < 0)
 429                return ret;
 430
 431        /* bit 10 - 3 */
 432        ret = i2c_smbus_write_byte_data(client, HSEND,
 433                                        (hsync->end & 0x07F8) >> 3);
 434        if (ret < 0)
 435                return ret;
 436
 437        /* bit 2 - 0 */
 438        ret = i2c_smbus_read_byte_data(client, HSLOWCTL);
 439        if (ret < 0)
 440                return ret;
 441
 442        ret = i2c_smbus_write_byte_data(client, HSLOWCTL,
 443                                        (ret & 0x88)                 |
 444                                        (hsync->start & 0x0007) << 4 |
 445                                        (hsync->end   & 0x0007));
 446
 447        return ret;
 448}
 449
 450static int tw9910_write_array(struct i2c_client *client,
 451                              const struct regval_list *vals)
 452{
 453        while (vals->reg_num != 0xff) {
 454                int ret = i2c_smbus_write_byte_data(client,
 455                                                    vals->reg_num,
 456                                                    vals->value);
 457                if (ret < 0)
 458                        return ret;
 459                vals++;
 460        }
 461        return 0;
 462}
 463
 464static int tw9910_mask_set(struct i2c_client *client, u8 command,
 465                           u8 mask, u8 set)
 466{
 467        s32 val = i2c_smbus_read_byte_data(client, command);
 468        if (val < 0)
 469                return val;
 470
 471        val &= ~mask;
 472        val |= set & mask;
 473
 474        return i2c_smbus_write_byte_data(client, command, val);
 475}
 476
 477static void tw9910_reset(struct i2c_client *client)
 478{
 479        i2c_smbus_write_byte_data(client, ACNTL1, SRESET);
 480        msleep(1);
 481}
 482
 483static const struct tw9910_scale_ctrl*
 484tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
 485{
 486        const struct tw9910_scale_ctrl *scale;
 487        const struct tw9910_scale_ctrl *ret = NULL;
 488        v4l2_std_id norm = icd->vdev->current_norm;
 489        __u32 diff = 0xffffffff, tmp;
 490        int size, i;
 491
 492        if (norm & V4L2_STD_NTSC) {
 493                scale = tw9910_ntsc_scales;
 494                size = ARRAY_SIZE(tw9910_ntsc_scales);
 495        } else if (norm & V4L2_STD_PAL) {
 496                scale = tw9910_pal_scales;
 497                size = ARRAY_SIZE(tw9910_pal_scales);
 498        } else {
 499                return NULL;
 500        }
 501
 502        for (i = 0; i < size; i++) {
 503                tmp = abs(width - scale[i].width) +
 504                        abs(height - scale[i].height);
 505                if (tmp < diff) {
 506                        diff = tmp;
 507                        ret = scale + i;
 508                }
 509        }
 510
 511        return ret;
 512}
 513
 514/*
 515 * soc_camera_ops function
 516 */
 517static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
 518{
 519        struct i2c_client *client = sd->priv;
 520        struct tw9910_priv *priv = to_tw9910(client);
 521
 522        if (!enable)
 523                return 0;
 524
 525        if (!priv->scale) {
 526                dev_err(&client->dev, "norm select error\n");
 527                return -EPERM;
 528        }
 529
 530        dev_dbg(&client->dev, "%s %dx%d\n",
 531                 priv->scale->name,
 532                 priv->scale->width,
 533                 priv->scale->height);
 534
 535        return 0;
 536}
 537
 538static int tw9910_set_bus_param(struct soc_camera_device *icd,
 539                                unsigned long flags)
 540{
 541        return 0;
 542}
 543
 544static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
 545{
 546        struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
 547        struct tw9910_priv *priv = to_tw9910(client);
 548        struct soc_camera_link *icl = to_soc_camera_link(icd);
 549        unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
 550                SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
 551                SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
 552
 553        return soc_camera_apply_sensor_flags(icl, flags);
 554}
 555
 556static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 557{
 558        int ret = -EINVAL;
 559
 560        if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL))
 561                ret = 0;
 562
 563        return ret;
 564}
 565
 566static int tw9910_enum_input(struct soc_camera_device *icd,
 567                             struct v4l2_input *inp)
 568{
 569        inp->type = V4L2_INPUT_TYPE_TUNER;
 570        inp->std  = V4L2_STD_UNKNOWN;
 571        strcpy(inp->name, "Video");
 572
 573        return 0;
 574}
 575
 576static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
 577                               struct v4l2_dbg_chip_ident *id)
 578{
 579        id->ident = V4L2_IDENT_TW9910;
 580        id->revision = 0;
 581
 582        return 0;
 583}
 584
 585#ifdef CONFIG_VIDEO_ADV_DEBUG
 586static int tw9910_g_register(struct v4l2_subdev *sd,
 587                             struct v4l2_dbg_register *reg)
 588{
 589        struct i2c_client *client = sd->priv;
 590        int ret;
 591
 592        if (reg->reg > 0xff)
 593                return -EINVAL;
 594
 595        ret = i2c_smbus_read_byte_data(client, reg->reg);
 596        if (ret < 0)
 597                return ret;
 598
 599        /* ret      = int
 600         * reg->val = __u64
 601         */
 602        reg->val = (__u64)ret;
 603
 604        return 0;
 605}
 606
 607static int tw9910_s_register(struct v4l2_subdev *sd,
 608                             struct v4l2_dbg_register *reg)
 609{
 610        struct i2c_client *client = sd->priv;
 611
 612        if (reg->reg > 0xff ||
 613            reg->val > 0xff)
 614                return -EINVAL;
 615
 616        return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
 617}
 618#endif
 619
 620static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 621{
 622        struct v4l2_rect *rect = &a->c;
 623        struct i2c_client *client = sd->priv;
 624        struct tw9910_priv *priv = to_tw9910(client);
 625        struct soc_camera_device *icd = client->dev.platform_data;
 626        int                 ret  = -EINVAL;
 627        u8                  val;
 628
 629        /*
 630         * select suitable norm
 631         */
 632        priv->scale = tw9910_select_norm(icd, rect->width, rect->height);
 633        if (!priv->scale)
 634                goto tw9910_set_fmt_error;
 635
 636        /*
 637         * reset hardware
 638         */
 639        tw9910_reset(client);
 640        ret = tw9910_write_array(client, tw9910_default_regs);
 641        if (ret < 0)
 642                goto tw9910_set_fmt_error;
 643
 644        /*
 645         * set bus width
 646         */
 647        val = 0x00;
 648        if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
 649                val = LEN;
 650
 651        ret = tw9910_mask_set(client, OPFORM, LEN, val);
 652        if (ret < 0)
 653                goto tw9910_set_fmt_error;
 654
 655        /*
 656         * select MPOUT behavior
 657         */
 658        switch (priv->info->mpout) {
 659        case TW9910_MPO_VLOSS:
 660                val = RTSEL_VLOSS; break;
 661        case TW9910_MPO_HLOCK:
 662                val = RTSEL_HLOCK; break;
 663        case TW9910_MPO_SLOCK:
 664                val = RTSEL_SLOCK; break;
 665        case TW9910_MPO_VLOCK:
 666                val = RTSEL_VLOCK; break;
 667        case TW9910_MPO_MONO:
 668                val = RTSEL_MONO;  break;
 669        case TW9910_MPO_DET50:
 670                val = RTSEL_DET50; break;
 671        case TW9910_MPO_FIELD:
 672                val = RTSEL_FIELD; break;
 673        case TW9910_MPO_RTCO:
 674                val = RTSEL_RTCO;  break;
 675        default:
 676                val = 0;
 677        }
 678
 679        ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
 680        if (ret < 0)
 681                goto tw9910_set_fmt_error;
 682
 683        /*
 684         * set scale
 685         */
 686        ret = tw9910_set_scale(client, priv->scale);
 687        if (ret < 0)
 688                goto tw9910_set_fmt_error;
 689
 690        /*
 691         * set cropping
 692         */
 693        ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
 694        if (ret < 0)
 695                goto tw9910_set_fmt_error;
 696
 697        /*
 698         * set hsync
 699         */
 700        ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
 701        if (ret < 0)
 702                goto tw9910_set_fmt_error;
 703
 704        rect->width = priv->scale->width;
 705        rect->height = priv->scale->height;
 706        rect->left = 0;
 707        rect->top = 0;
 708
 709        return ret;
 710
 711tw9910_set_fmt_error:
 712
 713        tw9910_reset(client);
 714        priv->scale = NULL;
 715
 716        return ret;
 717}
 718
 719static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 720{
 721        struct i2c_client *client = sd->priv;
 722        struct tw9910_priv *priv = to_tw9910(client);
 723
 724        if (!priv->scale) {
 725                int ret;
 726                struct v4l2_crop crop = {
 727                        .c = {
 728                                .left   = 0,
 729                                .top    = 0,
 730                                .width  = 640,
 731                                .height = 480,
 732                        },
 733                };
 734                ret = tw9910_s_crop(sd, &crop);
 735                if (ret < 0)
 736                        return ret;
 737        }
 738
 739        a->c.left       = 0;
 740        a->c.top        = 0;
 741        a->c.width      = priv->scale->width;
 742        a->c.height     = priv->scale->height;
 743        a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 744
 745        return 0;
 746}
 747
 748static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 749{
 750        a->bounds.left                  = 0;
 751        a->bounds.top                   = 0;
 752        a->bounds.width                 = 768;
 753        a->bounds.height                = 576;
 754        a->defrect.left                 = 0;
 755        a->defrect.top                  = 0;
 756        a->defrect.width                = 640;
 757        a->defrect.height               = 480;
 758        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 759        a->pixelaspect.numerator        = 1;
 760        a->pixelaspect.denominator      = 1;
 761
 762        return 0;
 763}
 764
 765static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
 766{
 767        struct i2c_client *client = sd->priv;
 768        struct tw9910_priv *priv = to_tw9910(client);
 769        struct v4l2_pix_format *pix = &f->fmt.pix;
 770
 771        if (!priv->scale) {
 772                int ret;
 773                struct v4l2_crop crop = {
 774                        .c = {
 775                                .left   = 0,
 776                                .top    = 0,
 777                                .width  = 640,
 778                                .height = 480,
 779                        },
 780                };
 781                ret = tw9910_s_crop(sd, &crop);
 782                if (ret < 0)
 783                        return ret;
 784        }
 785
 786        f->type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 787
 788        pix->width              = priv->scale->width;
 789        pix->height             = priv->scale->height;
 790        pix->pixelformat        = V4L2_PIX_FMT_VYUY;
 791        pix->colorspace         = V4L2_COLORSPACE_SMPTE170M;
 792        pix->field              = V4L2_FIELD_INTERLACED;
 793
 794        return 0;
 795}
 796
 797static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
 798{
 799        struct i2c_client *client = sd->priv;
 800        struct tw9910_priv *priv = to_tw9910(client);
 801        struct v4l2_pix_format *pix = &f->fmt.pix;
 802        /* See tw9910_s_crop() - no proper cropping support */
 803        struct v4l2_crop a = {
 804                .c = {
 805                        .left   = 0,
 806                        .top    = 0,
 807                        .width  = pix->width,
 808                        .height = pix->height,
 809                },
 810        };
 811        int i, ret;
 812
 813        /*
 814         * check color format
 815         */
 816        for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++)
 817                if (pix->pixelformat == tw9910_color_fmt[i].fourcc)
 818                        break;
 819
 820        if (i == ARRAY_SIZE(tw9910_color_fmt))
 821                return -EINVAL;
 822
 823        ret = tw9910_s_crop(sd, &a);
 824        if (!ret) {
 825                pix->width = priv->scale->width;
 826                pix->height = priv->scale->height;
 827        }
 828        return ret;
 829}
 830
 831static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
 832{
 833        struct i2c_client *client = sd->priv;
 834        struct soc_camera_device *icd = client->dev.platform_data;
 835        struct v4l2_pix_format *pix = &f->fmt.pix;
 836        const struct tw9910_scale_ctrl *scale;
 837
 838        if (V4L2_FIELD_ANY == pix->field) {
 839                pix->field = V4L2_FIELD_INTERLACED;
 840        } else if (V4L2_FIELD_INTERLACED != pix->field) {
 841                dev_err(&client->dev, "Field type invalid.\n");
 842                return -EINVAL;
 843        }
 844
 845        /*
 846         * select suitable norm
 847         */
 848        scale = tw9910_select_norm(icd, pix->width, pix->height);
 849        if (!scale)
 850                return -EINVAL;
 851
 852        pix->width  = scale->width;
 853        pix->height = scale->height;
 854
 855        return 0;
 856}
 857
 858static int tw9910_video_probe(struct soc_camera_device *icd,
 859                              struct i2c_client *client)
 860{
 861        struct tw9910_priv *priv = to_tw9910(client);
 862        s32 val;
 863
 864        /*
 865         * We must have a parent by now. And it cannot be a wrong one.
 866         * So this entire test is completely redundant.
 867         */
 868        if (!icd->dev.parent ||
 869            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
 870                return -ENODEV;
 871
 872        /*
 873         * tw9910 only use 8 or 16 bit bus width
 874         */
 875        if (SOCAM_DATAWIDTH_16 != priv->info->buswidth &&
 876            SOCAM_DATAWIDTH_8  != priv->info->buswidth) {
 877                dev_err(&client->dev, "bus width error\n");
 878                return -ENODEV;
 879        }
 880
 881        icd->formats     = tw9910_color_fmt;
 882        icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
 883
 884        /*
 885         * check and show Product ID
 886         */
 887        val = i2c_smbus_read_byte_data(client, ID);
 888
 889        if (0x0B != GET_ID(val) ||
 890            0x00 != GET_ReV(val)) {
 891                dev_err(&client->dev,
 892                        "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val));
 893                return -ENODEV;
 894        }
 895
 896        dev_info(&client->dev,
 897                 "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
 898
 899        icd->vdev->tvnorms      = V4L2_STD_NTSC | V4L2_STD_PAL;
 900        icd->vdev->current_norm = V4L2_STD_NTSC;
 901
 902        return 0;
 903}
 904
 905static struct soc_camera_ops tw9910_ops = {
 906        .set_bus_param          = tw9910_set_bus_param,
 907        .query_bus_param        = tw9910_query_bus_param,
 908        .enum_input             = tw9910_enum_input,
 909};
 910
 911static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
 912        .g_chip_ident   = tw9910_g_chip_ident,
 913        .s_std          = tw9910_s_std,
 914#ifdef CONFIG_VIDEO_ADV_DEBUG
 915        .g_register     = tw9910_g_register,
 916        .s_register     = tw9910_s_register,
 917#endif
 918};
 919
 920static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
 921        .s_stream       = tw9910_s_stream,
 922        .g_fmt          = tw9910_g_fmt,
 923        .s_fmt          = tw9910_s_fmt,
 924        .try_fmt        = tw9910_try_fmt,
 925        .cropcap        = tw9910_cropcap,
 926        .g_crop         = tw9910_g_crop,
 927        .s_crop         = tw9910_s_crop,
 928};
 929
 930static struct v4l2_subdev_ops tw9910_subdev_ops = {
 931        .core   = &tw9910_subdev_core_ops,
 932        .video  = &tw9910_subdev_video_ops,
 933};
 934
 935/*
 936 * i2c_driver function
 937 */
 938
 939static int tw9910_probe(struct i2c_client *client,
 940                        const struct i2c_device_id *did)
 941
 942{
 943        struct tw9910_priv             *priv;
 944        struct tw9910_video_info       *info;
 945        struct soc_camera_device       *icd = client->dev.platform_data;
 946        struct i2c_adapter             *adapter =
 947                to_i2c_adapter(client->dev.parent);
 948        struct soc_camera_link         *icl;
 949        int                             ret;
 950
 951        if (!icd) {
 952                dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
 953                return -EINVAL;
 954        }
 955
 956        icl = to_soc_camera_link(icd);
 957        if (!icl)
 958                return -EINVAL;
 959
 960        info = container_of(icl, struct tw9910_video_info, link);
 961
 962        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 963                dev_err(&client->dev,
 964                        "I2C-Adapter doesn't support "
 965                        "I2C_FUNC_SMBUS_BYTE_DATA\n");
 966                return -EIO;
 967        }
 968
 969        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 970        if (!priv)
 971                return -ENOMEM;
 972
 973        priv->info   = info;
 974
 975        v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
 976
 977        icd->ops     = &tw9910_ops;
 978        icd->iface   = info->link.bus_id;
 979
 980        ret = tw9910_video_probe(icd, client);
 981        if (ret) {
 982                icd->ops = NULL;
 983                i2c_set_clientdata(client, NULL);
 984                kfree(priv);
 985        }
 986
 987        return ret;
 988}
 989
 990static int tw9910_remove(struct i2c_client *client)
 991{
 992        struct tw9910_priv *priv = to_tw9910(client);
 993        struct soc_camera_device *icd = client->dev.platform_data;
 994
 995        icd->ops = NULL;
 996        i2c_set_clientdata(client, NULL);
 997        kfree(priv);
 998        return 0;
 999}
1000
1001static const struct i2c_device_id tw9910_id[] = {
1002        { "tw9910", 0 },
1003        { }
1004};
1005MODULE_DEVICE_TABLE(i2c, tw9910_id);
1006
1007static struct i2c_driver tw9910_i2c_driver = {
1008        .driver = {
1009                .name = "tw9910",
1010        },
1011        .probe    = tw9910_probe,
1012        .remove   = tw9910_remove,
1013        .id_table = tw9910_id,
1014};
1015
1016/*
1017 * module function
1018 */
1019static int __init tw9910_module_init(void)
1020{
1021        return i2c_add_driver(&tw9910_i2c_driver);
1022}
1023
1024static void __exit tw9910_module_exit(void)
1025{
1026        i2c_del_driver(&tw9910_i2c_driver);
1027}
1028
1029module_init(tw9910_module_init);
1030module_exit(tw9910_module_exit);
1031
1032MODULE_DESCRIPTION("SoC Camera driver for tw9910");
1033MODULE_AUTHOR("Kuninori Morimoto");
1034MODULE_LICENSE("GPL v2");
1035