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