root/drivers/media/i2c/saa717x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_state
  2. to_sd
  3. saa717x_write
  4. saa717x_write_regs
  5. saa717x_read
  6. get_inf_dev_status
  7. set_audio_mode
  8. set_audio_regs
  9. set_h_prescale
  10. set_v_scale
  11. saa717x_s_ctrl
  12. saa717x_s_video_routing
  13. saa717x_g_register
  14. saa717x_s_register
  15. saa717x_set_fmt
  16. saa717x_s_radio
  17. saa717x_s_std
  18. saa717x_s_audio_routing
  19. saa717x_s_stream
  20. saa717x_s_tuner
  21. saa717x_g_tuner
  22. saa717x_log_status
  23. saa717x_probe
  24. saa717x_remove

   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 
  30 MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
  31 MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
  32 MODULE_LICENSE("GPL");
  33 
  34 static int debug;
  35 module_param(debug, int, 0644);
  36 MODULE_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 
  43 struct 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 
  63 static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
  64 {
  65         return container_of(sd, struct saa717x_state, sd);
  66 }
  67 
  68 static 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 
  86 static 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 
 112 static 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 
 120 static 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 
 152 static 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 */
 624 static 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 */
 632 static 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 */
 640 static 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 
 647 static 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) */
 680 static 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 */
 757 static 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 */
 767 static 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 ***********/
 806 static 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 ***********/
 851 static 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 
 862 static 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 
 911 static 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
 965 static 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 
 972 static 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 
 982 static int saa717x_set_fmt(struct v4l2_subdev *sd,
 983                 struct v4l2_subdev_pad_config *cfg,
 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 
1050 static 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 
1058 static 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 
1070 static 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 
1086 static 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 */
1098 static 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 
1132 static 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 
1175 static 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 
1185 static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1186         .s_ctrl = saa717x_s_ctrl,
1187 };
1188 
1189 static 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 
1197 static 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 
1203 static 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 
1209 static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1210         .s_routing = saa717x_s_audio_routing,
1211 };
1212 
1213 static const struct v4l2_subdev_pad_ops saa717x_pad_ops = {
1214         .set_fmt = saa717x_set_fmt,
1215 };
1216 
1217 static 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 /* ----------------------------------------------------------------------- */
1231 static 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 
1327 static 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 
1338 static const struct i2c_device_id saa717x_id[] = {
1339         { "saa717x", 0 },
1340         { }
1341 };
1342 MODULE_DEVICE_TABLE(i2c, saa717x_id);
1343 
1344 static 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 
1353 module_i2c_driver(saa717x_driver);

/* [<][>][^][v][top][bottom][index][help] */