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