linux/drivers/media/i2c/saa717x.c
<<
>>
Prefs
   1/*
   2 * saa717x - Philips SAA717xHL video decoder driver
   3 *
   4 * Based on the saa7115 driver
   5 *
   6 * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
   7 *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
   8 *
   9 * Changes by T.Adachi (tadachi@tadachi-net.com)
  10 *    - support audio, video scaler etc, and checked the initialize sequence.
  11 *
  12 * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
  13 *
  14 * Note: this is a reversed engineered driver based on captures from
  15 * the I2C bus under Windows. This chip is very similar to the saa7134,
  16 * though. Unfortunately, this driver is currently only working for NTSC.
  17 *
  18 * This program is free software; you can redistribute it and/or modify
  19 * it under the terms of the GNU General Public License as published by
  20 * the Free Software Foundation; either version 2 of the License, or
  21 * (at your option) any later version.
  22 *
  23 * This program is distributed in the hope that it will be useful,
  24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 * GNU General Public License for more details.
  27 *
  28 * You should have received a copy of the GNU General Public License
  29 * along with this program; if not, write to the Free Software
  30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  31 */
  32
  33#include <linux/module.h>
  34#include <linux/kernel.h>
  35#include <linux/slab.h>
  36#include <linux/sched.h>
  37
  38#include <linux/videodev2.h>
  39#include <linux/i2c.h>
  40#include <media/v4l2-device.h>
  41#include <media/v4l2-ctrls.h>
  42
  43MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
  44MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
  45MODULE_LICENSE("GPL");
  46
  47static int debug;
  48module_param(debug, int, 0644);
  49MODULE_PARM_DESC(debug, "Debug level (0-1)");
  50
  51/*
  52 * Generic i2c probe
  53 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  54 */
  55
  56struct saa717x_state {
  57        struct v4l2_subdev sd;
  58        struct v4l2_ctrl_handler hdl;
  59        v4l2_std_id std;
  60        int input;
  61        int enable;
  62        int radio;
  63        int playback;
  64        int audio;
  65        int tuner_audio_mode;
  66        int audio_main_mute;
  67        int audio_main_vol_r;
  68        int audio_main_vol_l;
  69        u16 audio_main_bass;
  70        u16 audio_main_treble;
  71        u16 audio_main_volume;
  72        u16 audio_main_balance;
  73        int audio_input;
  74};
  75
  76static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
  77{
  78        return container_of(sd, struct saa717x_state, sd);
  79}
  80
  81static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  82{
  83        return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
  84}
  85
  86/* ----------------------------------------------------------------------- */
  87
  88/* for audio mode */
  89#define TUNER_AUDIO_MONO        0  /* LL */
  90#define TUNER_AUDIO_STEREO      1  /* LR */
  91#define TUNER_AUDIO_LANG1       2  /* LL */
  92#define TUNER_AUDIO_LANG2       3  /* RR */
  93
  94#define SAA717X_NTSC_WIDTH      (704)
  95#define SAA717X_NTSC_HEIGHT     (480)
  96
  97/* ----------------------------------------------------------------------- */
  98
  99static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
 100{
 101        struct i2c_client *client = v4l2_get_subdevdata(sd);
 102        struct i2c_adapter *adap = client->adapter;
 103        int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
 104        unsigned char mm1[6];
 105        struct i2c_msg msg;
 106
 107        msg.flags = 0;
 108        msg.addr = client->addr;
 109        mm1[0] = (reg >> 8) & 0xff;
 110        mm1[1] = reg & 0xff;
 111
 112        if (fw_addr) {
 113                mm1[4] = (value >> 16) & 0xff;
 114                mm1[3] = (value >> 8) & 0xff;
 115                mm1[2] = value & 0xff;
 116        } else {
 117                mm1[2] = value & 0xff;
 118        }
 119        msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
 120        msg.buf = mm1;
 121        v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
 122        return i2c_transfer(adap, &msg, 1) == 1;
 123}
 124
 125static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
 126{
 127        while (data[0] || data[1]) {
 128                saa717x_write(sd, data[0], data[1]);
 129                data += 2;
 130        }
 131}
 132
 133static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
 134{
 135        struct i2c_client *client = v4l2_get_subdevdata(sd);
 136        struct i2c_adapter *adap = client->adapter;
 137        int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
 138        unsigned char mm1[2];
 139        unsigned char mm2[4] = { 0, 0, 0, 0 };
 140        struct i2c_msg msgs[2];
 141        u32 value;
 142
 143        msgs[0].flags = 0;
 144        msgs[1].flags = I2C_M_RD;
 145        msgs[0].addr = msgs[1].addr = client->addr;
 146        mm1[0] = (reg >> 8) & 0xff;
 147        mm1[1] = reg & 0xff;
 148        msgs[0].len = 2;
 149        msgs[0].buf = mm1;
 150        msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
 151        msgs[1].buf = mm2;
 152        i2c_transfer(adap, msgs, 2);
 153
 154        if (fw_addr)
 155                value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
 156        else
 157                value = mm2[0] & 0xff;
 158
 159        v4l2_dbg(2, debug, sd, "read:  reg 0x%03x=0x%08x\n", reg, value);
 160        return value;
 161}
 162
 163/* ----------------------------------------------------------------------- */
 164
 165static u32 reg_init_initialize[] =
 166{
 167        /* from linux driver */
 168        0x101, 0x008, /* Increment delay */
 169
 170        0x103, 0x000, /* Analog input control 2 */
 171        0x104, 0x090, /* Analog input control 3 */
 172        0x105, 0x090, /* Analog input control 4 */
 173        0x106, 0x0eb, /* Horizontal sync start */
 174        0x107, 0x0e0, /* Horizontal sync stop */
 175        0x109, 0x055, /* Luminance control */
 176
 177        0x10f, 0x02a, /* Chroma gain control */
 178        0x110, 0x000, /* Chroma control 2 */
 179
 180        0x114, 0x045, /* analog/ADC */
 181
 182        0x118, 0x040, /* RAW data gain */
 183        0x119, 0x080, /* RAW data offset */
 184
 185        0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
 186        0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
 187        0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
 188        0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
 189
 190        0x049, 0x000, /* VBI vertical input window start (H) TASK A */
 191
 192        0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
 193        0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
 194
 195        0x064, 0x080, /* Lumina brightness TASK A */
 196        0x065, 0x040, /* Luminance contrast TASK A */
 197        0x066, 0x040, /* Chroma saturation TASK A */
 198        /* 067H: Reserved */
 199        0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
 200        0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
 201        0x06a, 0x000, /* VBI phase offset TASK A */
 202
 203        0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
 204        0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
 205
 206        0x072, 0x000, /* Vertical filter mode TASK A */
 207
 208        0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
 209        0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
 210        0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
 211        0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
 212
 213        0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
 214
 215        0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
 216        0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
 217
 218        0x0a4, 0x080, /* Lumina brightness TASK B */
 219        0x0a5, 0x040, /* Luminance contrast TASK B */
 220        0x0a6, 0x040, /* Chroma saturation TASK B */
 221        /* 0A7H reserved */
 222        0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
 223        0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
 224        0x0aa, 0x000, /* VBI phase offset TASK B */
 225
 226        0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
 227        0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
 228
 229        0x0b2, 0x000, /* Vertical filter mode TASK B */
 230
 231        0x00c, 0x000, /* Start point GREEN path */
 232        0x00d, 0x000, /* Start point BLUE path */
 233        0x00e, 0x000, /* Start point RED path */
 234
 235        0x010, 0x010, /* GREEN path gamma curve --- */
 236        0x011, 0x020,
 237        0x012, 0x030,
 238        0x013, 0x040,
 239        0x014, 0x050,
 240        0x015, 0x060,
 241        0x016, 0x070,
 242        0x017, 0x080,
 243        0x018, 0x090,
 244        0x019, 0x0a0,
 245        0x01a, 0x0b0,
 246        0x01b, 0x0c0,
 247        0x01c, 0x0d0,
 248        0x01d, 0x0e0,
 249        0x01e, 0x0f0,
 250        0x01f, 0x0ff, /* --- GREEN path gamma curve */
 251
 252        0x020, 0x010, /* BLUE path gamma curve --- */
 253        0x021, 0x020,
 254        0x022, 0x030,
 255        0x023, 0x040,
 256        0x024, 0x050,
 257        0x025, 0x060,
 258        0x026, 0x070,
 259        0x027, 0x080,
 260        0x028, 0x090,
 261        0x029, 0x0a0,
 262        0x02a, 0x0b0,
 263        0x02b, 0x0c0,
 264        0x02c, 0x0d0,
 265        0x02d, 0x0e0,
 266        0x02e, 0x0f0,
 267        0x02f, 0x0ff, /* --- BLUE path gamma curve */
 268
 269        0x030, 0x010, /* RED path gamma curve --- */
 270        0x031, 0x020,
 271        0x032, 0x030,
 272        0x033, 0x040,
 273        0x034, 0x050,
 274        0x035, 0x060,
 275        0x036, 0x070,
 276        0x037, 0x080,
 277        0x038, 0x090,
 278        0x039, 0x0a0,
 279        0x03a, 0x0b0,
 280        0x03b, 0x0c0,
 281        0x03c, 0x0d0,
 282        0x03d, 0x0e0,
 283        0x03e, 0x0f0,
 284        0x03f, 0x0ff, /* --- RED path gamma curve */
 285
 286        0x109, 0x085, /* Luminance control  */
 287
 288        /**** from app start ****/
 289        0x584, 0x000, /* AGC gain control */
 290        0x585, 0x000, /* Program count */
 291        0x586, 0x003, /* Status reset */
 292        0x588, 0x0ff, /* Number of audio samples (L) */
 293        0x589, 0x00f, /* Number of audio samples (M) */
 294        0x58a, 0x000, /* Number of audio samples (H) */
 295        0x58b, 0x000, /* Audio select */
 296        0x58c, 0x010, /* Audio channel assign1 */
 297        0x58d, 0x032, /* Audio channel assign2 */
 298        0x58e, 0x054, /* Audio channel assign3 */
 299        0x58f, 0x023, /* Audio format */
 300        0x590, 0x000, /* SIF control */
 301
 302        0x595, 0x000, /* ?? */
 303        0x596, 0x000, /* ?? */
 304        0x597, 0x000, /* ?? */
 305
 306        0x464, 0x00, /* Digital input crossbar1 */
 307
 308        0x46c, 0xbbbb10, /* Digital output selection1-3 */
 309        0x470, 0x101010, /* Digital output selection4-6 */
 310
 311        0x478, 0x00, /* Sound feature control */
 312
 313        0x474, 0x18, /* Softmute control */
 314
 315        0x454, 0x0425b9, /* Sound Easy programming(reset) */
 316        0x454, 0x042539, /* Sound Easy programming(reset) */
 317
 318
 319        /**** common setting( of DVD play, including scaler commands) ****/
 320        0x042, 0x003, /* Data path configuration for VBI (TASK A) */
 321
 322        0x082, 0x003, /* Data path configuration for VBI (TASK B) */
 323
 324        0x108, 0x0f8, /* Sync control */
 325        0x2a9, 0x0fd, /* ??? */
 326        0x102, 0x089, /* select video input "mode 9" */
 327        0x111, 0x000, /* Mode/delay control */
 328
 329        0x10e, 0x00a, /* Chroma control 1 */
 330
 331        0x594, 0x002, /* SIF, analog I/O select */
 332
 333        0x454, 0x0425b9, /* Sound  */
 334        0x454, 0x042539,
 335
 336        0x111, 0x000,
 337        0x10e, 0x00a,
 338        0x464, 0x000,
 339        0x300, 0x000,
 340        0x301, 0x006,
 341        0x302, 0x000,
 342        0x303, 0x006,
 343        0x308, 0x040,
 344        0x309, 0x000,
 345        0x30a, 0x000,
 346        0x30b, 0x000,
 347        0x000, 0x002,
 348        0x001, 0x000,
 349        0x002, 0x000,
 350        0x003, 0x000,
 351        0x004, 0x033,
 352        0x040, 0x01d,
 353        0x041, 0x001,
 354        0x042, 0x004,
 355        0x043, 0x000,
 356        0x080, 0x01e,
 357        0x081, 0x001,
 358        0x082, 0x004,
 359        0x083, 0x000,
 360        0x190, 0x018,
 361        0x115, 0x000,
 362        0x116, 0x012,
 363        0x117, 0x018,
 364        0x04a, 0x011,
 365        0x08a, 0x011,
 366        0x04b, 0x000,
 367        0x08b, 0x000,
 368        0x048, 0x000,
 369        0x088, 0x000,
 370        0x04e, 0x012,
 371        0x08e, 0x012,
 372        0x058, 0x012,
 373        0x098, 0x012,
 374        0x059, 0x000,
 375        0x099, 0x000,
 376        0x05a, 0x003,
 377        0x09a, 0x003,
 378        0x05b, 0x001,
 379        0x09b, 0x001,
 380        0x054, 0x008,
 381        0x094, 0x008,
 382        0x055, 0x000,
 383        0x095, 0x000,
 384        0x056, 0x0c7,
 385        0x096, 0x0c7,
 386        0x057, 0x002,
 387        0x097, 0x002,
 388        0x0ff, 0x0ff,
 389        0x060, 0x001,
 390        0x0a0, 0x001,
 391        0x061, 0x000,
 392        0x0a1, 0x000,
 393        0x062, 0x000,
 394        0x0a2, 0x000,
 395        0x063, 0x000,
 396        0x0a3, 0x000,
 397        0x070, 0x000,
 398        0x0b0, 0x000,
 399        0x071, 0x004,
 400        0x0b1, 0x004,
 401        0x06c, 0x0e9,
 402        0x0ac, 0x0e9,
 403        0x06d, 0x003,
 404        0x0ad, 0x003,
 405        0x05c, 0x0d0,
 406        0x09c, 0x0d0,
 407        0x05d, 0x002,
 408        0x09d, 0x002,
 409        0x05e, 0x0f2,
 410        0x09e, 0x0f2,
 411        0x05f, 0x000,
 412        0x09f, 0x000,
 413        0x074, 0x000,
 414        0x0b4, 0x000,
 415        0x075, 0x000,
 416        0x0b5, 0x000,
 417        0x076, 0x000,
 418        0x0b6, 0x000,
 419        0x077, 0x000,
 420        0x0b7, 0x000,
 421        0x195, 0x008,
 422        0x0ff, 0x0ff,
 423        0x108, 0x0f8,
 424        0x111, 0x000,
 425        0x10e, 0x00a,
 426        0x2a9, 0x0fd,
 427        0x464, 0x001,
 428        0x454, 0x042135,
 429        0x598, 0x0e7,
 430        0x599, 0x07d,
 431        0x59a, 0x018,
 432        0x59c, 0x066,
 433        0x59d, 0x090,
 434        0x59e, 0x001,
 435        0x584, 0x000,
 436        0x585, 0x000,
 437        0x586, 0x003,
 438        0x588, 0x0ff,
 439        0x589, 0x00f,
 440        0x58a, 0x000,
 441        0x58b, 0x000,
 442        0x58c, 0x010,
 443        0x58d, 0x032,
 444        0x58e, 0x054,
 445        0x58f, 0x023,
 446        0x590, 0x000,
 447        0x595, 0x000,
 448        0x596, 0x000,
 449        0x597, 0x000,
 450        0x464, 0x000,
 451        0x46c, 0xbbbb10,
 452        0x470, 0x101010,
 453
 454
 455        0x478, 0x000,
 456        0x474, 0x018,
 457        0x454, 0x042135,
 458        0x598, 0x0e7,
 459        0x599, 0x07d,
 460        0x59a, 0x018,
 461        0x59c, 0x066,
 462        0x59d, 0x090,
 463        0x59e, 0x001,
 464        0x584, 0x000,
 465        0x585, 0x000,
 466        0x586, 0x003,
 467        0x588, 0x0ff,
 468        0x589, 0x00f,
 469        0x58a, 0x000,
 470        0x58b, 0x000,
 471        0x58c, 0x010,
 472        0x58d, 0x032,
 473        0x58e, 0x054,
 474        0x58f, 0x023,
 475        0x590, 0x000,
 476        0x595, 0x000,
 477        0x596, 0x000,
 478        0x597, 0x000,
 479        0x464, 0x000,
 480        0x46c, 0xbbbb10,
 481        0x470, 0x101010,
 482
 483        0x478, 0x000,
 484        0x474, 0x018,
 485        0x454, 0x042135,
 486        0x598, 0x0e7,
 487        0x599, 0x07d,
 488        0x59a, 0x018,
 489        0x59c, 0x066,
 490        0x59d, 0x090,
 491        0x59e, 0x001,
 492        0x584, 0x000,
 493        0x585, 0x000,
 494        0x586, 0x003,
 495        0x588, 0x0ff,
 496        0x589, 0x00f,
 497        0x58a, 0x000,
 498        0x58b, 0x000,
 499        0x58c, 0x010,
 500        0x58d, 0x032,
 501        0x58e, 0x054,
 502        0x58f, 0x023,
 503        0x590, 0x000,
 504        0x595, 0x000,
 505        0x596, 0x000,
 506        0x597, 0x000,
 507        0x464, 0x000,
 508        0x46c, 0xbbbb10,
 509        0x470, 0x101010,
 510        0x478, 0x000,
 511        0x474, 0x018,
 512        0x454, 0x042135,
 513        0x193, 0x000,
 514        0x300, 0x000,
 515        0x301, 0x006,
 516        0x302, 0x000,
 517        0x303, 0x006,
 518        0x308, 0x040,
 519        0x309, 0x000,
 520        0x30a, 0x000,
 521        0x30b, 0x000,
 522        0x000, 0x002,
 523        0x001, 0x000,
 524        0x002, 0x000,
 525        0x003, 0x000,
 526        0x004, 0x033,
 527        0x040, 0x01d,
 528        0x041, 0x001,
 529        0x042, 0x004,
 530        0x043, 0x000,
 531        0x080, 0x01e,
 532        0x081, 0x001,
 533        0x082, 0x004,
 534        0x083, 0x000,
 535        0x190, 0x018,
 536        0x115, 0x000,
 537        0x116, 0x012,
 538        0x117, 0x018,
 539        0x04a, 0x011,
 540        0x08a, 0x011,
 541        0x04b, 0x000,
 542        0x08b, 0x000,
 543        0x048, 0x000,
 544        0x088, 0x000,
 545        0x04e, 0x012,
 546        0x08e, 0x012,
 547        0x058, 0x012,
 548        0x098, 0x012,
 549        0x059, 0x000,
 550        0x099, 0x000,
 551        0x05a, 0x003,
 552        0x09a, 0x003,
 553        0x05b, 0x001,
 554        0x09b, 0x001,
 555        0x054, 0x008,
 556        0x094, 0x008,
 557        0x055, 0x000,
 558        0x095, 0x000,
 559        0x056, 0x0c7,
 560        0x096, 0x0c7,
 561        0x057, 0x002,
 562        0x097, 0x002,
 563        0x060, 0x001,
 564        0x0a0, 0x001,
 565        0x061, 0x000,
 566        0x0a1, 0x000,
 567        0x062, 0x000,
 568        0x0a2, 0x000,
 569        0x063, 0x000,
 570        0x0a3, 0x000,
 571        0x070, 0x000,
 572        0x0b0, 0x000,
 573        0x071, 0x004,
 574        0x0b1, 0x004,
 575        0x06c, 0x0e9,
 576        0x0ac, 0x0e9,
 577        0x06d, 0x003,
 578        0x0ad, 0x003,
 579        0x05c, 0x0d0,
 580        0x09c, 0x0d0,
 581        0x05d, 0x002,
 582        0x09d, 0x002,
 583        0x05e, 0x0f2,
 584        0x09e, 0x0f2,
 585        0x05f, 0x000,
 586        0x09f, 0x000,
 587        0x074, 0x000,
 588        0x0b4, 0x000,
 589        0x075, 0x000,
 590        0x0b5, 0x000,
 591        0x076, 0x000,
 592        0x0b6, 0x000,
 593        0x077, 0x000,
 594        0x0b7, 0x000,
 595        0x195, 0x008,
 596        0x598, 0x0e7,
 597        0x599, 0x07d,
 598        0x59a, 0x018,
 599        0x59c, 0x066,
 600        0x59d, 0x090,
 601        0x59e, 0x001,
 602        0x584, 0x000,
 603        0x585, 0x000,
 604        0x586, 0x003,
 605        0x588, 0x0ff,
 606        0x589, 0x00f,
 607        0x58a, 0x000,
 608        0x58b, 0x000,
 609        0x58c, 0x010,
 610        0x58d, 0x032,
 611        0x58e, 0x054,
 612        0x58f, 0x023,
 613        0x590, 0x000,
 614        0x595, 0x000,
 615        0x596, 0x000,
 616        0x597, 0x000,
 617        0x464, 0x000,
 618        0x46c, 0xbbbb10,
 619        0x470, 0x101010,
 620        0x478, 0x000,
 621        0x474, 0x018,
 622        0x454, 0x042135,
 623        0x193, 0x0a6,
 624        0x108, 0x0f8,
 625        0x042, 0x003,
 626        0x082, 0x003,
 627        0x454, 0x0425b9,
 628        0x454, 0x042539,
 629        0x193, 0x000,
 630        0x193, 0x0a6,
 631        0x464, 0x000,
 632
 633        0, 0
 634};
 635
 636/* Tuner */
 637static u32 reg_init_tuner_input[] = {
 638        0x108, 0x0f8, /* Sync control */
 639        0x111, 0x000, /* Mode/delay control */
 640        0x10e, 0x00a, /* Chroma control 1 */
 641        0, 0
 642};
 643
 644/* Composite */
 645static u32 reg_init_composite_input[] = {
 646        0x108, 0x0e8, /* Sync control */
 647        0x111, 0x000, /* Mode/delay control */
 648        0x10e, 0x04a, /* Chroma control 1 */
 649        0, 0
 650};
 651
 652/* S-Video */
 653static u32 reg_init_svideo_input[] = {
 654        0x108, 0x0e8, /* Sync control */
 655        0x111, 0x000, /* Mode/delay control */
 656        0x10e, 0x04a, /* Chroma control 1 */
 657        0, 0
 658};
 659
 660static u32 reg_set_audio_template[4][2] =
 661{
 662        { /* for MONO
 663                tadachi 6/29 DMA audio output select?
 664                Register 0x46c
 665                7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
 666                0: MAIN left,  1: MAIN right
 667                2: AUX1 left,  3: AUX1 right
 668                4: AUX2 left,  5: AUX2 right
 669                6: DPL left,   7: DPL  right
 670                8: DPL center, 9: DPL surround
 671                A: monitor output, B: digital sense */
 672                0xbbbb00,
 673
 674                /* tadachi 6/29 DAC and I2S output select?
 675                   Register 0x470
 676                   7-4:DAC right ch. 3-0:DAC left ch.
 677                   I2S1 right,left  I2S2 right,left */
 678                0x00,
 679        },
 680        { /* for STEREO */
 681                0xbbbb10, 0x101010,
 682        },
 683        { /* for LANG1 */
 684                0xbbbb00, 0x00,
 685        },
 686        { /* for LANG2/SAP */
 687                0xbbbb11, 0x111111,
 688        }
 689};
 690
 691
 692/* Get detected audio flags (from saa7134 driver) */
 693static void get_inf_dev_status(struct v4l2_subdev *sd,
 694                int *dual_flag, int *stereo_flag)
 695{
 696        u32 reg_data3;
 697
 698        static char *stdres[0x20] = {
 699                [0x00] = "no standard detected",
 700                [0x01] = "B/G (in progress)",
 701                [0x02] = "D/K (in progress)",
 702                [0x03] = "M (in progress)",
 703
 704                [0x04] = "B/G A2",
 705                [0x05] = "B/G NICAM",
 706                [0x06] = "D/K A2 (1)",
 707                [0x07] = "D/K A2 (2)",
 708                [0x08] = "D/K A2 (3)",
 709                [0x09] = "D/K NICAM",
 710                [0x0a] = "L NICAM",
 711                [0x0b] = "I NICAM",
 712
 713                [0x0c] = "M Korea",
 714                [0x0d] = "M BTSC ",
 715                [0x0e] = "M EIAJ",
 716
 717                [0x0f] = "FM radio / IF 10.7 / 50 deemp",
 718                [0x10] = "FM radio / IF 10.7 / 75 deemp",
 719                [0x11] = "FM radio / IF sel / 50 deemp",
 720                [0x12] = "FM radio / IF sel / 75 deemp",
 721
 722                [0x13 ... 0x1e] = "unknown",
 723                [0x1f] = "??? [in progress]",
 724        };
 725
 726
 727        *dual_flag = *stereo_flag = 0;
 728
 729        /* (demdec status: 0x528) */
 730
 731        /* read current status */
 732        reg_data3 = saa717x_read(sd, 0x0528);
 733
 734        v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
 735                reg_data3, stdres[reg_data3 & 0x1f],
 736                (reg_data3 & 0x000020) ? ",stereo" : "",
 737                (reg_data3 & 0x000040) ? ",dual"   : "");
 738        v4l2_dbg(1, debug, sd, "detailed status: "
 739                "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
 740                (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
 741                (reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
 742                (reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
 743                (reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
 744
 745                (reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
 746                (reg_data3 & 0x001000) ? " SAP carrier "            : "",
 747                (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
 748                (reg_data3 & 0x004000) ? " SAP noise mute "         : "",
 749                (reg_data3 & 0x008000) ? " VDSP "                   : "",
 750
 751                (reg_data3 & 0x010000) ? " NICST "                  : "",
 752                (reg_data3 & 0x020000) ? " NICDU "                  : "",
 753                (reg_data3 & 0x040000) ? " NICAM muted "            : "",
 754                (reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
 755
 756                (reg_data3 & 0x100000) ? " init done "              : "");
 757
 758        if (reg_data3 & 0x000220) {
 759                v4l2_dbg(1, debug, sd, "ST!!!\n");
 760                *stereo_flag = 1;
 761        }
 762
 763        if (reg_data3 & 0x000140) {
 764                v4l2_dbg(1, debug, sd, "DUAL!!!\n");
 765                *dual_flag = 1;
 766        }
 767}
 768
 769/* regs write to set audio mode */
 770static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
 771{
 772        v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
 773                        audio_mode);
 774
 775        saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
 776        saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
 777}
 778
 779/* write regs to set audio volume, bass and treble */
 780static int set_audio_regs(struct v4l2_subdev *sd,
 781                struct saa717x_state *decoder)
 782{
 783        u8 mute = 0xac; /* -84 dB */
 784        u32 val;
 785        unsigned int work_l, work_r;
 786
 787        /* set SIF analog I/O select */
 788        saa717x_write(sd, 0x0594, decoder->audio_input);
 789        v4l2_dbg(1, debug, sd, "set audio input %d\n",
 790                        decoder->audio_input);
 791
 792        /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
 793        work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
 794        work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
 795        decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
 796        decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
 797
 798        /* set main volume */
 799        /* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
 800        /*    def:0dB->6dB(MPG600GR) */
 801        /* if mute is on, set mute */
 802        if (decoder->audio_main_mute) {
 803                val = mute | (mute << 8);
 804        } else {
 805                val = (u8)decoder->audio_main_vol_l |
 806                        ((u8)decoder->audio_main_vol_r << 8);
 807        }
 808
 809        saa717x_write(sd, 0x480, val);
 810
 811        /* set bass and treble */
 812        val = decoder->audio_main_bass & 0x1f;
 813        val |= (decoder->audio_main_treble & 0x1f) << 5;
 814        saa717x_write(sd, 0x488, val);
 815        return 0;
 816}
 817
 818/********** scaling staff ***********/
 819static void set_h_prescale(struct v4l2_subdev *sd,
 820                int task, int prescale)
 821{
 822        static const struct {
 823                int xpsc;
 824                int xacl;
 825                int xc2_1;
 826                int xdcg;
 827                int vpfy;
 828        } vals[] = {
 829                /* XPSC XACL XC2_1 XDCG VPFY */
 830                {    1,   0,    0,    0,   0 },
 831                {    2,   2,    1,    2,   2 },
 832                {    3,   4,    1,    3,   2 },
 833                {    4,   8,    1,    4,   2 },
 834                {    5,   8,    1,    4,   2 },
 835                {    6,   8,    1,    4,   3 },
 836                {    7,   8,    1,    4,   3 },
 837                {    8,  15,    0,    4,   3 },
 838                {    9,  15,    0,    4,   3 },
 839                {   10,  16,    1,    5,   3 },
 840        };
 841        static const int count = ARRAY_SIZE(vals);
 842        int i, task_shift;
 843
 844        task_shift = task * 0x40;
 845        for (i = 0; i < count; i++)
 846                if (vals[i].xpsc == prescale)
 847                        break;
 848        if (i == count)
 849                return;
 850
 851        /* horizonal prescaling */
 852        saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
 853        /* accumulation length */
 854        saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
 855        /* level control */
 856        saa717x_write(sd, 0x62 + task_shift,
 857                        (vals[i].xc2_1 << 3) | vals[i].xdcg);
 858        /*FIR prefilter control */
 859        saa717x_write(sd, 0x63 + task_shift,
 860                        (vals[i].vpfy << 2) | vals[i].vpfy);
 861}
 862
 863/********** scaling staff ***********/
 864static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
 865{
 866        int task_shift;
 867
 868        task_shift = task * 0x40;
 869        /* Vertical scaling ratio (LOW) */
 870        saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
 871        /* Vertical scaling ratio (HI) */
 872        saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
 873}
 874
 875static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
 876{
 877        struct v4l2_subdev *sd = to_sd(ctrl);
 878        struct saa717x_state *state = to_state(sd);
 879
 880        switch (ctrl->id) {
 881        case V4L2_CID_BRIGHTNESS:
 882                saa717x_write(sd, 0x10a, ctrl->val);
 883                return 0;
 884
 885        case V4L2_CID_CONTRAST:
 886                saa717x_write(sd, 0x10b, ctrl->val);
 887                return 0;
 888
 889        case V4L2_CID_SATURATION:
 890                saa717x_write(sd, 0x10c, ctrl->val);
 891                return 0;
 892
 893        case V4L2_CID_HUE:
 894                saa717x_write(sd, 0x10d, ctrl->val);
 895                return 0;
 896
 897        case V4L2_CID_AUDIO_MUTE:
 898                state->audio_main_mute = ctrl->val;
 899                break;
 900
 901        case V4L2_CID_AUDIO_VOLUME:
 902                state->audio_main_volume = ctrl->val;
 903                break;
 904
 905        case V4L2_CID_AUDIO_BALANCE:
 906                state->audio_main_balance = ctrl->val;
 907                break;
 908
 909        case V4L2_CID_AUDIO_TREBLE:
 910                state->audio_main_treble = ctrl->val;
 911                break;
 912
 913        case V4L2_CID_AUDIO_BASS:
 914                state->audio_main_bass = ctrl->val;
 915                break;
 916
 917        default:
 918                return 0;
 919        }
 920        set_audio_regs(sd, state);
 921        return 0;
 922}
 923
 924static int saa717x_s_video_routing(struct v4l2_subdev *sd,
 925                                   u32 input, u32 output, u32 config)
 926{
 927        struct saa717x_state *decoder = to_state(sd);
 928        int is_tuner = input & 0x80;  /* tuner input flag */
 929
 930        input &= 0x7f;
 931
 932        v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
 933        /* inputs from 0-9 are available*/
 934        /* saa717x have mode0-mode9 but mode5 is reserved. */
 935        if (input > 9 || input == 5)
 936                return -EINVAL;
 937
 938        if (decoder->input != input) {
 939                int input_line = input;
 940
 941                decoder->input = input_line;
 942                v4l2_dbg(1, debug, sd,  "now setting %s input %d\n",
 943                                input_line >= 6 ? "S-Video" : "Composite",
 944                                input_line);
 945
 946                /* select mode */
 947                saa717x_write(sd, 0x102,
 948                                (saa717x_read(sd, 0x102) & 0xf0) |
 949                                input_line);
 950
 951                /* bypass chrominance trap for modes 6..9 */
 952                saa717x_write(sd, 0x109,
 953                                (saa717x_read(sd, 0x109) & 0x7f) |
 954                                (input_line < 6 ? 0x0 : 0x80));
 955
 956                /* change audio_mode */
 957                if (is_tuner) {
 958                        /* tuner */
 959                        set_audio_mode(sd, decoder->tuner_audio_mode);
 960                } else {
 961                        /* Force to STEREO mode if Composite or
 962                         * S-Video were chosen */
 963                        set_audio_mode(sd, TUNER_AUDIO_STEREO);
 964                }
 965                /* change initialize procedure (Composite/S-Video) */
 966                if (is_tuner)
 967                        saa717x_write_regs(sd, reg_init_tuner_input);
 968                else if (input_line >= 6)
 969                        saa717x_write_regs(sd, reg_init_svideo_input);
 970                else
 971                        saa717x_write_regs(sd, reg_init_composite_input);
 972        }
 973
 974        return 0;
 975}
 976
 977#ifdef CONFIG_VIDEO_ADV_DEBUG
 978static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 979{
 980        reg->val = saa717x_read(sd, reg->reg);
 981        reg->size = 1;
 982        return 0;
 983}
 984
 985static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 986{
 987        u16 addr = reg->reg & 0xffff;
 988        u8 val = reg->val & 0xff;
 989
 990        saa717x_write(sd, addr, val);
 991        return 0;
 992}
 993#endif
 994
 995static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 996{
 997        int prescale, h_scale, v_scale;
 998
 999        v4l2_dbg(1, debug, sd, "decoder set size\n");
1000
1001        if (fmt->code != V4L2_MBUS_FMT_FIXED)
1002                return -EINVAL;
1003
1004        /* FIXME need better bounds checking here */
1005        if (fmt->width < 1 || fmt->width > 1440)
1006                return -EINVAL;
1007        if (fmt->height < 1 || fmt->height > 960)
1008                return -EINVAL;
1009
1010        fmt->field = V4L2_FIELD_INTERLACED;
1011        fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1012
1013        /* scaling setting */
1014        /* NTSC and interlace only */
1015        prescale = SAA717X_NTSC_WIDTH / fmt->width;
1016        if (prescale == 0)
1017                prescale = 1;
1018        h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
1019        /* interlace */
1020        v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1021
1022        /* Horizontal prescaling etc */
1023        set_h_prescale(sd, 0, prescale);
1024        set_h_prescale(sd, 1, prescale);
1025
1026        /* Horizontal scaling increment */
1027        /* TASK A */
1028        saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
1029        saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1030        /* TASK B */
1031        saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
1032        saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1033
1034        /* Vertical prescaling etc */
1035        set_v_scale(sd, 0, v_scale);
1036        set_v_scale(sd, 1, v_scale);
1037
1038        /* set video output size */
1039        /* video number of pixels at output */
1040        /* TASK A */
1041        saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1042        saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1043        /* TASK B */
1044        saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1045        saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1046
1047        /* video number of lines at output */
1048        /* TASK A */
1049        saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1050        saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1051        /* TASK B */
1052        saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
1053        saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
1054        return 0;
1055}
1056
1057static int saa717x_s_radio(struct v4l2_subdev *sd)
1058{
1059        struct saa717x_state *decoder = to_state(sd);
1060
1061        decoder->radio = 1;
1062        return 0;
1063}
1064
1065static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1066{
1067        struct saa717x_state *decoder = to_state(sd);
1068
1069        v4l2_dbg(1, debug, sd, "decoder set norm ");
1070        v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
1071
1072        decoder->radio = 0;
1073        decoder->std = std;
1074        return 0;
1075}
1076
1077static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1078                                   u32 input, u32 output, u32 config)
1079{
1080        struct saa717x_state *decoder = to_state(sd);
1081
1082        if (input < 3) { /* FIXME! --tadachi */
1083                decoder->audio_input = input;
1084                v4l2_dbg(1, debug, sd,
1085                                "set decoder audio input to %d\n",
1086                                decoder->audio_input);
1087                set_audio_regs(sd, decoder);
1088                return 0;
1089        }
1090        return -ERANGE;
1091}
1092
1093static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1094{
1095        struct saa717x_state *decoder = to_state(sd);
1096
1097        v4l2_dbg(1, debug, sd, "decoder %s output\n",
1098                        enable ? "enable" : "disable");
1099        decoder->enable = enable;
1100        saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1101        return 0;
1102}
1103
1104/* change audio mode */
1105static int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
1106{
1107        struct saa717x_state *decoder = to_state(sd);
1108        int audio_mode;
1109        char *mes[4] = {
1110                "MONO", "STEREO", "LANG1", "LANG2/SAP"
1111        };
1112
1113        audio_mode = TUNER_AUDIO_STEREO;
1114
1115        switch (vt->audmode) {
1116                case V4L2_TUNER_MODE_MONO:
1117                        audio_mode = TUNER_AUDIO_MONO;
1118                        break;
1119                case V4L2_TUNER_MODE_STEREO:
1120                        audio_mode = TUNER_AUDIO_STEREO;
1121                        break;
1122                case V4L2_TUNER_MODE_LANG2:
1123                        audio_mode = TUNER_AUDIO_LANG2;
1124                        break;
1125                case V4L2_TUNER_MODE_LANG1:
1126                        audio_mode = TUNER_AUDIO_LANG1;
1127                        break;
1128        }
1129
1130        v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1131                        mes[audio_mode]);
1132        decoder->tuner_audio_mode = audio_mode;
1133        /* The registers are not changed here. */
1134        /* See DECODER_ENABLE_OUTPUT section. */
1135        set_audio_mode(sd, decoder->tuner_audio_mode);
1136        return 0;
1137}
1138
1139static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1140{
1141        struct saa717x_state *decoder = to_state(sd);
1142        int dual_f, stereo_f;
1143
1144        if (decoder->radio)
1145                return 0;
1146        get_inf_dev_status(sd, &dual_f, &stereo_f);
1147
1148        v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1149                        stereo_f, dual_f);
1150
1151        /* mono */
1152        if ((dual_f == 0) && (stereo_f == 0)) {
1153                vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1154                v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1155        }
1156
1157        /* stereo */
1158        if (stereo_f == 1) {
1159                if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1160                                vt->audmode == V4L2_TUNER_MODE_LANG1) {
1161                        vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1162                        v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1163                } else {
1164                        vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1165                        v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
1166                }
1167        }
1168
1169        /* dual */
1170        if (dual_f == 1) {
1171                if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1172                        vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1173                        v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1174                } else {
1175                        vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1176                        v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1177                }
1178        }
1179        return 0;
1180}
1181
1182static int saa717x_log_status(struct v4l2_subdev *sd)
1183{
1184        struct saa717x_state *state = to_state(sd);
1185
1186        v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1187        return 0;
1188}
1189
1190/* ----------------------------------------------------------------------- */
1191
1192static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1193        .s_ctrl = saa717x_s_ctrl,
1194};
1195
1196static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1197#ifdef CONFIG_VIDEO_ADV_DEBUG
1198        .g_register = saa717x_g_register,
1199        .s_register = saa717x_s_register,
1200#endif
1201        .s_std = saa717x_s_std,
1202        .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1203        .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1204        .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1205        .g_ctrl = v4l2_subdev_g_ctrl,
1206        .s_ctrl = v4l2_subdev_s_ctrl,
1207        .queryctrl = v4l2_subdev_queryctrl,
1208        .querymenu = v4l2_subdev_querymenu,
1209        .log_status = saa717x_log_status,
1210};
1211
1212static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1213        .g_tuner = saa717x_g_tuner,
1214        .s_tuner = saa717x_s_tuner,
1215        .s_radio = saa717x_s_radio,
1216};
1217
1218static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1219        .s_routing = saa717x_s_video_routing,
1220        .s_mbus_fmt = saa717x_s_mbus_fmt,
1221        .s_stream = saa717x_s_stream,
1222};
1223
1224static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1225        .s_routing = saa717x_s_audio_routing,
1226};
1227
1228static const struct v4l2_subdev_ops saa717x_ops = {
1229        .core = &saa717x_core_ops,
1230        .tuner = &saa717x_tuner_ops,
1231        .audio = &saa717x_audio_ops,
1232        .video = &saa717x_video_ops,
1233};
1234
1235/* ----------------------------------------------------------------------- */
1236
1237
1238/* i2c implementation */
1239
1240/* ----------------------------------------------------------------------- */
1241static int saa717x_probe(struct i2c_client *client,
1242                         const struct i2c_device_id *did)
1243{
1244        struct saa717x_state *decoder;
1245        struct v4l2_ctrl_handler *hdl;
1246        struct v4l2_subdev *sd;
1247        u8 id = 0;
1248        char *p = "";
1249
1250        /* Check if the adapter supports the needed features */
1251        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1252                return -EIO;
1253
1254        decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
1255        if (decoder == NULL)
1256                return -ENOMEM;
1257
1258        sd = &decoder->sd;
1259        v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1260
1261        if (saa717x_write(sd, 0x5a4, 0xfe) &&
1262                        saa717x_write(sd, 0x5a5, 0x0f) &&
1263                        saa717x_write(sd, 0x5a6, 0x00) &&
1264                        saa717x_write(sd, 0x5a7, 0x01))
1265                id = saa717x_read(sd, 0x5a0);
1266        if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1267                v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1268                return -ENODEV;
1269        }
1270        if (id == 0xc2)
1271                p = "saa7173";
1272        else if (id == 0x32)
1273                p = "saa7174A";
1274        else if (id == 0x6c)
1275                p = "saa7174HL";
1276        else
1277                p = "saa7171";
1278        v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1279                        client->addr << 1, client->adapter->name);
1280
1281        hdl = &decoder->hdl;
1282        v4l2_ctrl_handler_init(hdl, 9);
1283        /* add in ascending ID order */
1284        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1285                        V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1286        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1287                        V4L2_CID_CONTRAST, 0, 255, 1, 68);
1288        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1289                        V4L2_CID_SATURATION, 0, 255, 1, 64);
1290        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1291                        V4L2_CID_HUE, -128, 127, 1, 0);
1292        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1293                        V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
1294        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1295                        V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
1296        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1297                        V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
1298        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1299                        V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
1300        v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1301                        V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1302        sd->ctrl_handler = hdl;
1303        if (hdl->error) {
1304                int err = hdl->error;
1305
1306                v4l2_ctrl_handler_free(hdl);
1307                return err;
1308        }
1309
1310        decoder->std = V4L2_STD_NTSC;
1311        decoder->input = -1;
1312        decoder->enable = 1;
1313
1314        /* FIXME!! */
1315        decoder->playback = 0;  /* initially capture mode used */
1316        decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1317
1318        decoder->audio_input = 2; /* FIXME!! */
1319
1320        decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1321        /* set volume, bass and treble */
1322        decoder->audio_main_vol_l = 6;
1323        decoder->audio_main_vol_r = 6;
1324
1325        v4l2_dbg(1, debug, sd, "writing init values\n");
1326
1327        /* FIXME!! */
1328        saa717x_write_regs(sd, reg_init_initialize);
1329
1330        v4l2_ctrl_handler_setup(hdl);
1331
1332        set_current_state(TASK_INTERRUPTIBLE);
1333        schedule_timeout(2*HZ);
1334        return 0;
1335}
1336
1337static int saa717x_remove(struct i2c_client *client)
1338{
1339        struct v4l2_subdev *sd = i2c_get_clientdata(client);
1340
1341        v4l2_device_unregister_subdev(sd);
1342        v4l2_ctrl_handler_free(sd->ctrl_handler);
1343        return 0;
1344}
1345
1346/* ----------------------------------------------------------------------- */
1347
1348static const struct i2c_device_id saa717x_id[] = {
1349        { "saa717x", 0 },
1350        { }
1351};
1352MODULE_DEVICE_TABLE(i2c, saa717x_id);
1353
1354static struct i2c_driver saa717x_driver = {
1355        .driver = {
1356                .owner  = THIS_MODULE,
1357                .name   = "saa717x",
1358        },
1359        .probe          = saa717x_probe,
1360        .remove         = saa717x_remove,
1361        .id_table       = saa717x_id,
1362};
1363
1364module_i2c_driver(saa717x_driver);
1365