Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * saa717x - Philips SAA717xHL video decoder driver
0004  *
0005  * Based on the saa7115 driver
0006  *
0007  * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
0008  *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
0009  *
0010  * Changes by T.Adachi (tadachi@tadachi-net.com)
0011  *    - support audio, video scaler etc, and checked the initialize sequence.
0012  *
0013  * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
0014  *
0015  * Note: this is a reversed engineered driver based on captures from
0016  * the I2C bus under Windows. This chip is very similar to the saa7134,
0017  * though. Unfortunately, this driver is currently only working for NTSC.
0018  */
0019 
0020 #include <linux/module.h>
0021 #include <linux/kernel.h>
0022 #include <linux/slab.h>
0023 #include <linux/sched.h>
0024 
0025 #include <linux/videodev2.h>
0026 #include <linux/i2c.h>
0027 #include <media/v4l2-device.h>
0028 #include <media/v4l2-ctrls.h>
0029 
0030 MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
0031 MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
0032 MODULE_LICENSE("GPL");
0033 
0034 static int debug;
0035 module_param(debug, int, 0644);
0036 MODULE_PARM_DESC(debug, "Debug level (0-1)");
0037 
0038 /*
0039  * Generic i2c probe
0040  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
0041  */
0042 
0043 struct saa717x_state {
0044     struct v4l2_subdev sd;
0045     struct v4l2_ctrl_handler hdl;
0046     v4l2_std_id std;
0047     int input;
0048     int enable;
0049     int radio;
0050     int playback;
0051     int audio;
0052     int tuner_audio_mode;
0053     int audio_main_mute;
0054     int audio_main_vol_r;
0055     int audio_main_vol_l;
0056     u16 audio_main_bass;
0057     u16 audio_main_treble;
0058     u16 audio_main_volume;
0059     u16 audio_main_balance;
0060     int audio_input;
0061 };
0062 
0063 static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
0064 {
0065     return container_of(sd, struct saa717x_state, sd);
0066 }
0067 
0068 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
0069 {
0070     return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
0071 }
0072 
0073 /* ----------------------------------------------------------------------- */
0074 
0075 /* for audio mode */
0076 #define TUNER_AUDIO_MONO    0  /* LL */
0077 #define TUNER_AUDIO_STEREO  1  /* LR */
0078 #define TUNER_AUDIO_LANG1   2  /* LL */
0079 #define TUNER_AUDIO_LANG2   3  /* RR */
0080 
0081 #define SAA717X_NTSC_WIDTH  (704)
0082 #define SAA717X_NTSC_HEIGHT (480)
0083 
0084 /* ----------------------------------------------------------------------- */
0085 
0086 static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
0087 {
0088     struct i2c_client *client = v4l2_get_subdevdata(sd);
0089     struct i2c_adapter *adap = client->adapter;
0090     int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
0091     unsigned char mm1[6];
0092     struct i2c_msg msg;
0093 
0094     msg.flags = 0;
0095     msg.addr = client->addr;
0096     mm1[0] = (reg >> 8) & 0xff;
0097     mm1[1] = reg & 0xff;
0098 
0099     if (fw_addr) {
0100         mm1[4] = (value >> 16) & 0xff;
0101         mm1[3] = (value >> 8) & 0xff;
0102         mm1[2] = value & 0xff;
0103     } else {
0104         mm1[2] = value & 0xff;
0105     }
0106     msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
0107     msg.buf = mm1;
0108     v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
0109     return i2c_transfer(adap, &msg, 1) == 1;
0110 }
0111 
0112 static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
0113 {
0114     while (data[0] || data[1]) {
0115         saa717x_write(sd, data[0], data[1]);
0116         data += 2;
0117     }
0118 }
0119 
0120 static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
0121 {
0122     struct i2c_client *client = v4l2_get_subdevdata(sd);
0123     struct i2c_adapter *adap = client->adapter;
0124     int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
0125     unsigned char mm1[2];
0126     unsigned char mm2[4] = { 0, 0, 0, 0 };
0127     struct i2c_msg msgs[2];
0128     u32 value;
0129 
0130     msgs[0].flags = 0;
0131     msgs[1].flags = I2C_M_RD;
0132     msgs[0].addr = msgs[1].addr = client->addr;
0133     mm1[0] = (reg >> 8) & 0xff;
0134     mm1[1] = reg & 0xff;
0135     msgs[0].len = 2;
0136     msgs[0].buf = mm1;
0137     msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
0138     msgs[1].buf = mm2;
0139     i2c_transfer(adap, msgs, 2);
0140 
0141     if (fw_addr)
0142         value = (mm2[2] << 16)  | (mm2[1] << 8) | mm2[0];
0143     else
0144         value = mm2[0];
0145 
0146     v4l2_dbg(2, debug, sd, "read:  reg 0x%03x=0x%08x\n", reg, value);
0147     return value;
0148 }
0149 
0150 /* ----------------------------------------------------------------------- */
0151 
0152 static u32 reg_init_initialize[] =
0153 {
0154     /* from linux driver */
0155     0x101, 0x008, /* Increment delay */
0156 
0157     0x103, 0x000, /* Analog input control 2 */
0158     0x104, 0x090, /* Analog input control 3 */
0159     0x105, 0x090, /* Analog input control 4 */
0160     0x106, 0x0eb, /* Horizontal sync start */
0161     0x107, 0x0e0, /* Horizontal sync stop */
0162     0x109, 0x055, /* Luminance control */
0163 
0164     0x10f, 0x02a, /* Chroma gain control */
0165     0x110, 0x000, /* Chroma control 2 */
0166 
0167     0x114, 0x045, /* analog/ADC */
0168 
0169     0x118, 0x040, /* RAW data gain */
0170     0x119, 0x080, /* RAW data offset */
0171 
0172     0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
0173     0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
0174     0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
0175     0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
0176 
0177     0x049, 0x000, /* VBI vertical input window start (H) TASK A */
0178 
0179     0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
0180     0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
0181 
0182     0x064, 0x080, /* Lumina brightness TASK A */
0183     0x065, 0x040, /* Luminance contrast TASK A */
0184     0x066, 0x040, /* Chroma saturation TASK A */
0185     /* 067H: Reserved */
0186     0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
0187     0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
0188     0x06a, 0x000, /* VBI phase offset TASK A */
0189 
0190     0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
0191     0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
0192 
0193     0x072, 0x000, /* Vertical filter mode TASK A */
0194 
0195     0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
0196     0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
0197     0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
0198     0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
0199 
0200     0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
0201 
0202     0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
0203     0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
0204 
0205     0x0a4, 0x080, /* Lumina brightness TASK B */
0206     0x0a5, 0x040, /* Luminance contrast TASK B */
0207     0x0a6, 0x040, /* Chroma saturation TASK B */
0208     /* 0A7H reserved */
0209     0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
0210     0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
0211     0x0aa, 0x000, /* VBI phase offset TASK B */
0212 
0213     0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
0214     0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
0215 
0216     0x0b2, 0x000, /* Vertical filter mode TASK B */
0217 
0218     0x00c, 0x000, /* Start point GREEN path */
0219     0x00d, 0x000, /* Start point BLUE path */
0220     0x00e, 0x000, /* Start point RED path */
0221 
0222     0x010, 0x010, /* GREEN path gamma curve --- */
0223     0x011, 0x020,
0224     0x012, 0x030,
0225     0x013, 0x040,
0226     0x014, 0x050,
0227     0x015, 0x060,
0228     0x016, 0x070,
0229     0x017, 0x080,
0230     0x018, 0x090,
0231     0x019, 0x0a0,
0232     0x01a, 0x0b0,
0233     0x01b, 0x0c0,
0234     0x01c, 0x0d0,
0235     0x01d, 0x0e0,
0236     0x01e, 0x0f0,
0237     0x01f, 0x0ff, /* --- GREEN path gamma curve */
0238 
0239     0x020, 0x010, /* BLUE path gamma curve --- */
0240     0x021, 0x020,
0241     0x022, 0x030,
0242     0x023, 0x040,
0243     0x024, 0x050,
0244     0x025, 0x060,
0245     0x026, 0x070,
0246     0x027, 0x080,
0247     0x028, 0x090,
0248     0x029, 0x0a0,
0249     0x02a, 0x0b0,
0250     0x02b, 0x0c0,
0251     0x02c, 0x0d0,
0252     0x02d, 0x0e0,
0253     0x02e, 0x0f0,
0254     0x02f, 0x0ff, /* --- BLUE path gamma curve */
0255 
0256     0x030, 0x010, /* RED path gamma curve --- */
0257     0x031, 0x020,
0258     0x032, 0x030,
0259     0x033, 0x040,
0260     0x034, 0x050,
0261     0x035, 0x060,
0262     0x036, 0x070,
0263     0x037, 0x080,
0264     0x038, 0x090,
0265     0x039, 0x0a0,
0266     0x03a, 0x0b0,
0267     0x03b, 0x0c0,
0268     0x03c, 0x0d0,
0269     0x03d, 0x0e0,
0270     0x03e, 0x0f0,
0271     0x03f, 0x0ff, /* --- RED path gamma curve */
0272 
0273     0x109, 0x085, /* Luminance control  */
0274 
0275     /**** from app start ****/
0276     0x584, 0x000, /* AGC gain control */
0277     0x585, 0x000, /* Program count */
0278     0x586, 0x003, /* Status reset */
0279     0x588, 0x0ff, /* Number of audio samples (L) */
0280     0x589, 0x00f, /* Number of audio samples (M) */
0281     0x58a, 0x000, /* Number of audio samples (H) */
0282     0x58b, 0x000, /* Audio select */
0283     0x58c, 0x010, /* Audio channel assign1 */
0284     0x58d, 0x032, /* Audio channel assign2 */
0285     0x58e, 0x054, /* Audio channel assign3 */
0286     0x58f, 0x023, /* Audio format */
0287     0x590, 0x000, /* SIF control */
0288 
0289     0x595, 0x000, /* ?? */
0290     0x596, 0x000, /* ?? */
0291     0x597, 0x000, /* ?? */
0292 
0293     0x464, 0x00, /* Digital input crossbar1 */
0294 
0295     0x46c, 0xbbbb10, /* Digital output selection1-3 */
0296     0x470, 0x101010, /* Digital output selection4-6 */
0297 
0298     0x478, 0x00, /* Sound feature control */
0299 
0300     0x474, 0x18, /* Softmute control */
0301 
0302     0x454, 0x0425b9, /* Sound Easy programming(reset) */
0303     0x454, 0x042539, /* Sound Easy programming(reset) */
0304 
0305 
0306     /**** common setting( of DVD play, including scaler commands) ****/
0307     0x042, 0x003, /* Data path configuration for VBI (TASK A) */
0308 
0309     0x082, 0x003, /* Data path configuration for VBI (TASK B) */
0310 
0311     0x108, 0x0f8, /* Sync control */
0312     0x2a9, 0x0fd, /* ??? */
0313     0x102, 0x089, /* select video input "mode 9" */
0314     0x111, 0x000, /* Mode/delay control */
0315 
0316     0x10e, 0x00a, /* Chroma control 1 */
0317 
0318     0x594, 0x002, /* SIF, analog I/O select */
0319 
0320     0x454, 0x0425b9, /* Sound  */
0321     0x454, 0x042539,
0322 
0323     0x111, 0x000,
0324     0x10e, 0x00a,
0325     0x464, 0x000,
0326     0x300, 0x000,
0327     0x301, 0x006,
0328     0x302, 0x000,
0329     0x303, 0x006,
0330     0x308, 0x040,
0331     0x309, 0x000,
0332     0x30a, 0x000,
0333     0x30b, 0x000,
0334     0x000, 0x002,
0335     0x001, 0x000,
0336     0x002, 0x000,
0337     0x003, 0x000,
0338     0x004, 0x033,
0339     0x040, 0x01d,
0340     0x041, 0x001,
0341     0x042, 0x004,
0342     0x043, 0x000,
0343     0x080, 0x01e,
0344     0x081, 0x001,
0345     0x082, 0x004,
0346     0x083, 0x000,
0347     0x190, 0x018,
0348     0x115, 0x000,
0349     0x116, 0x012,
0350     0x117, 0x018,
0351     0x04a, 0x011,
0352     0x08a, 0x011,
0353     0x04b, 0x000,
0354     0x08b, 0x000,
0355     0x048, 0x000,
0356     0x088, 0x000,
0357     0x04e, 0x012,
0358     0x08e, 0x012,
0359     0x058, 0x012,
0360     0x098, 0x012,
0361     0x059, 0x000,
0362     0x099, 0x000,
0363     0x05a, 0x003,
0364     0x09a, 0x003,
0365     0x05b, 0x001,
0366     0x09b, 0x001,
0367     0x054, 0x008,
0368     0x094, 0x008,
0369     0x055, 0x000,
0370     0x095, 0x000,
0371     0x056, 0x0c7,
0372     0x096, 0x0c7,
0373     0x057, 0x002,
0374     0x097, 0x002,
0375     0x0ff, 0x0ff,
0376     0x060, 0x001,
0377     0x0a0, 0x001,
0378     0x061, 0x000,
0379     0x0a1, 0x000,
0380     0x062, 0x000,
0381     0x0a2, 0x000,
0382     0x063, 0x000,
0383     0x0a3, 0x000,
0384     0x070, 0x000,
0385     0x0b0, 0x000,
0386     0x071, 0x004,
0387     0x0b1, 0x004,
0388     0x06c, 0x0e9,
0389     0x0ac, 0x0e9,
0390     0x06d, 0x003,
0391     0x0ad, 0x003,
0392     0x05c, 0x0d0,
0393     0x09c, 0x0d0,
0394     0x05d, 0x002,
0395     0x09d, 0x002,
0396     0x05e, 0x0f2,
0397     0x09e, 0x0f2,
0398     0x05f, 0x000,
0399     0x09f, 0x000,
0400     0x074, 0x000,
0401     0x0b4, 0x000,
0402     0x075, 0x000,
0403     0x0b5, 0x000,
0404     0x076, 0x000,
0405     0x0b6, 0x000,
0406     0x077, 0x000,
0407     0x0b7, 0x000,
0408     0x195, 0x008,
0409     0x0ff, 0x0ff,
0410     0x108, 0x0f8,
0411     0x111, 0x000,
0412     0x10e, 0x00a,
0413     0x2a9, 0x0fd,
0414     0x464, 0x001,
0415     0x454, 0x042135,
0416     0x598, 0x0e7,
0417     0x599, 0x07d,
0418     0x59a, 0x018,
0419     0x59c, 0x066,
0420     0x59d, 0x090,
0421     0x59e, 0x001,
0422     0x584, 0x000,
0423     0x585, 0x000,
0424     0x586, 0x003,
0425     0x588, 0x0ff,
0426     0x589, 0x00f,
0427     0x58a, 0x000,
0428     0x58b, 0x000,
0429     0x58c, 0x010,
0430     0x58d, 0x032,
0431     0x58e, 0x054,
0432     0x58f, 0x023,
0433     0x590, 0x000,
0434     0x595, 0x000,
0435     0x596, 0x000,
0436     0x597, 0x000,
0437     0x464, 0x000,
0438     0x46c, 0xbbbb10,
0439     0x470, 0x101010,
0440 
0441 
0442     0x478, 0x000,
0443     0x474, 0x018,
0444     0x454, 0x042135,
0445     0x598, 0x0e7,
0446     0x599, 0x07d,
0447     0x59a, 0x018,
0448     0x59c, 0x066,
0449     0x59d, 0x090,
0450     0x59e, 0x001,
0451     0x584, 0x000,
0452     0x585, 0x000,
0453     0x586, 0x003,
0454     0x588, 0x0ff,
0455     0x589, 0x00f,
0456     0x58a, 0x000,
0457     0x58b, 0x000,
0458     0x58c, 0x010,
0459     0x58d, 0x032,
0460     0x58e, 0x054,
0461     0x58f, 0x023,
0462     0x590, 0x000,
0463     0x595, 0x000,
0464     0x596, 0x000,
0465     0x597, 0x000,
0466     0x464, 0x000,
0467     0x46c, 0xbbbb10,
0468     0x470, 0x101010,
0469 
0470     0x478, 0x000,
0471     0x474, 0x018,
0472     0x454, 0x042135,
0473     0x598, 0x0e7,
0474     0x599, 0x07d,
0475     0x59a, 0x018,
0476     0x59c, 0x066,
0477     0x59d, 0x090,
0478     0x59e, 0x001,
0479     0x584, 0x000,
0480     0x585, 0x000,
0481     0x586, 0x003,
0482     0x588, 0x0ff,
0483     0x589, 0x00f,
0484     0x58a, 0x000,
0485     0x58b, 0x000,
0486     0x58c, 0x010,
0487     0x58d, 0x032,
0488     0x58e, 0x054,
0489     0x58f, 0x023,
0490     0x590, 0x000,
0491     0x595, 0x000,
0492     0x596, 0x000,
0493     0x597, 0x000,
0494     0x464, 0x000,
0495     0x46c, 0xbbbb10,
0496     0x470, 0x101010,
0497     0x478, 0x000,
0498     0x474, 0x018,
0499     0x454, 0x042135,
0500     0x193, 0x000,
0501     0x300, 0x000,
0502     0x301, 0x006,
0503     0x302, 0x000,
0504     0x303, 0x006,
0505     0x308, 0x040,
0506     0x309, 0x000,
0507     0x30a, 0x000,
0508     0x30b, 0x000,
0509     0x000, 0x002,
0510     0x001, 0x000,
0511     0x002, 0x000,
0512     0x003, 0x000,
0513     0x004, 0x033,
0514     0x040, 0x01d,
0515     0x041, 0x001,
0516     0x042, 0x004,
0517     0x043, 0x000,
0518     0x080, 0x01e,
0519     0x081, 0x001,
0520     0x082, 0x004,
0521     0x083, 0x000,
0522     0x190, 0x018,
0523     0x115, 0x000,
0524     0x116, 0x012,
0525     0x117, 0x018,
0526     0x04a, 0x011,
0527     0x08a, 0x011,
0528     0x04b, 0x000,
0529     0x08b, 0x000,
0530     0x048, 0x000,
0531     0x088, 0x000,
0532     0x04e, 0x012,
0533     0x08e, 0x012,
0534     0x058, 0x012,
0535     0x098, 0x012,
0536     0x059, 0x000,
0537     0x099, 0x000,
0538     0x05a, 0x003,
0539     0x09a, 0x003,
0540     0x05b, 0x001,
0541     0x09b, 0x001,
0542     0x054, 0x008,
0543     0x094, 0x008,
0544     0x055, 0x000,
0545     0x095, 0x000,
0546     0x056, 0x0c7,
0547     0x096, 0x0c7,
0548     0x057, 0x002,
0549     0x097, 0x002,
0550     0x060, 0x001,
0551     0x0a0, 0x001,
0552     0x061, 0x000,
0553     0x0a1, 0x000,
0554     0x062, 0x000,
0555     0x0a2, 0x000,
0556     0x063, 0x000,
0557     0x0a3, 0x000,
0558     0x070, 0x000,
0559     0x0b0, 0x000,
0560     0x071, 0x004,
0561     0x0b1, 0x004,
0562     0x06c, 0x0e9,
0563     0x0ac, 0x0e9,
0564     0x06d, 0x003,
0565     0x0ad, 0x003,
0566     0x05c, 0x0d0,
0567     0x09c, 0x0d0,
0568     0x05d, 0x002,
0569     0x09d, 0x002,
0570     0x05e, 0x0f2,
0571     0x09e, 0x0f2,
0572     0x05f, 0x000,
0573     0x09f, 0x000,
0574     0x074, 0x000,
0575     0x0b4, 0x000,
0576     0x075, 0x000,
0577     0x0b5, 0x000,
0578     0x076, 0x000,
0579     0x0b6, 0x000,
0580     0x077, 0x000,
0581     0x0b7, 0x000,
0582     0x195, 0x008,
0583     0x598, 0x0e7,
0584     0x599, 0x07d,
0585     0x59a, 0x018,
0586     0x59c, 0x066,
0587     0x59d, 0x090,
0588     0x59e, 0x001,
0589     0x584, 0x000,
0590     0x585, 0x000,
0591     0x586, 0x003,
0592     0x588, 0x0ff,
0593     0x589, 0x00f,
0594     0x58a, 0x000,
0595     0x58b, 0x000,
0596     0x58c, 0x010,
0597     0x58d, 0x032,
0598     0x58e, 0x054,
0599     0x58f, 0x023,
0600     0x590, 0x000,
0601     0x595, 0x000,
0602     0x596, 0x000,
0603     0x597, 0x000,
0604     0x464, 0x000,
0605     0x46c, 0xbbbb10,
0606     0x470, 0x101010,
0607     0x478, 0x000,
0608     0x474, 0x018,
0609     0x454, 0x042135,
0610     0x193, 0x0a6,
0611     0x108, 0x0f8,
0612     0x042, 0x003,
0613     0x082, 0x003,
0614     0x454, 0x0425b9,
0615     0x454, 0x042539,
0616     0x193, 0x000,
0617     0x193, 0x0a6,
0618     0x464, 0x000,
0619 
0620     0, 0
0621 };
0622 
0623 /* Tuner */
0624 static u32 reg_init_tuner_input[] = {
0625     0x108, 0x0f8, /* Sync control */
0626     0x111, 0x000, /* Mode/delay control */
0627     0x10e, 0x00a, /* Chroma control 1 */
0628     0, 0
0629 };
0630 
0631 /* Composite */
0632 static u32 reg_init_composite_input[] = {
0633     0x108, 0x0e8, /* Sync control */
0634     0x111, 0x000, /* Mode/delay control */
0635     0x10e, 0x04a, /* Chroma control 1 */
0636     0, 0
0637 };
0638 
0639 /* S-Video */
0640 static u32 reg_init_svideo_input[] = {
0641     0x108, 0x0e8, /* Sync control */
0642     0x111, 0x000, /* Mode/delay control */
0643     0x10e, 0x04a, /* Chroma control 1 */
0644     0, 0
0645 };
0646 
0647 static u32 reg_set_audio_template[4][2] =
0648 {
0649     { /* for MONO
0650         tadachi 6/29 DMA audio output select?
0651         Register 0x46c
0652         7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
0653         0: MAIN left,  1: MAIN right
0654         2: AUX1 left,  3: AUX1 right
0655         4: AUX2 left,  5: AUX2 right
0656         6: DPL left,   7: DPL  right
0657         8: DPL center, 9: DPL surround
0658         A: monitor output, B: digital sense */
0659         0xbbbb00,
0660 
0661         /* tadachi 6/29 DAC and I2S output select?
0662            Register 0x470
0663            7-4:DAC right ch. 3-0:DAC left ch.
0664            I2S1 right,left  I2S2 right,left */
0665         0x00,
0666     },
0667     { /* for STEREO */
0668         0xbbbb10, 0x101010,
0669     },
0670     { /* for LANG1 */
0671         0xbbbb00, 0x00,
0672     },
0673     { /* for LANG2/SAP */
0674         0xbbbb11, 0x111111,
0675     }
0676 };
0677 
0678 
0679 /* Get detected audio flags (from saa7134 driver) */
0680 static void get_inf_dev_status(struct v4l2_subdev *sd,
0681         int *dual_flag, int *stereo_flag)
0682 {
0683     u32 reg_data3;
0684 
0685     static char *stdres[0x20] = {
0686         [0x00] = "no standard detected",
0687         [0x01] = "B/G (in progress)",
0688         [0x02] = "D/K (in progress)",
0689         [0x03] = "M (in progress)",
0690 
0691         [0x04] = "B/G A2",
0692         [0x05] = "B/G NICAM",
0693         [0x06] = "D/K A2 (1)",
0694         [0x07] = "D/K A2 (2)",
0695         [0x08] = "D/K A2 (3)",
0696         [0x09] = "D/K NICAM",
0697         [0x0a] = "L NICAM",
0698         [0x0b] = "I NICAM",
0699 
0700         [0x0c] = "M Korea",
0701         [0x0d] = "M BTSC ",
0702         [0x0e] = "M EIAJ",
0703 
0704         [0x0f] = "FM radio / IF 10.7 / 50 deemp",
0705         [0x10] = "FM radio / IF 10.7 / 75 deemp",
0706         [0x11] = "FM radio / IF sel / 50 deemp",
0707         [0x12] = "FM radio / IF sel / 75 deemp",
0708 
0709         [0x13 ... 0x1e] = "unknown",
0710         [0x1f] = "??? [in progress]",
0711     };
0712 
0713 
0714     *dual_flag = *stereo_flag = 0;
0715 
0716     /* (demdec status: 0x528) */
0717 
0718     /* read current status */
0719     reg_data3 = saa717x_read(sd, 0x0528);
0720 
0721     v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
0722         reg_data3, stdres[reg_data3 & 0x1f],
0723         (reg_data3 & 0x000020) ? ",stereo" : "",
0724         (reg_data3 & 0x000040) ? ",dual"   : "");
0725     v4l2_dbg(1, debug, sd, "detailed status: "
0726         "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
0727         (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
0728         (reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
0729         (reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
0730         (reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
0731 
0732         (reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
0733         (reg_data3 & 0x001000) ? " SAP carrier "            : "",
0734         (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
0735         (reg_data3 & 0x004000) ? " SAP noise mute "         : "",
0736         (reg_data3 & 0x008000) ? " VDSP "                   : "",
0737 
0738         (reg_data3 & 0x010000) ? " NICST "                  : "",
0739         (reg_data3 & 0x020000) ? " NICDU "                  : "",
0740         (reg_data3 & 0x040000) ? " NICAM muted "            : "",
0741         (reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
0742 
0743         (reg_data3 & 0x100000) ? " init done "              : "");
0744 
0745     if (reg_data3 & 0x000220) {
0746         v4l2_dbg(1, debug, sd, "ST!!!\n");
0747         *stereo_flag = 1;
0748     }
0749 
0750     if (reg_data3 & 0x000140) {
0751         v4l2_dbg(1, debug, sd, "DUAL!!!\n");
0752         *dual_flag = 1;
0753     }
0754 }
0755 
0756 /* regs write to set audio mode */
0757 static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
0758 {
0759     v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
0760             audio_mode);
0761 
0762     saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
0763     saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
0764 }
0765 
0766 /* write regs to set audio volume, bass and treble */
0767 static int set_audio_regs(struct v4l2_subdev *sd,
0768         struct saa717x_state *decoder)
0769 {
0770     u8 mute = 0xac; /* -84 dB */
0771     u32 val;
0772     unsigned int work_l, work_r;
0773 
0774     /* set SIF analog I/O select */
0775     saa717x_write(sd, 0x0594, decoder->audio_input);
0776     v4l2_dbg(1, debug, sd, "set audio input %d\n",
0777             decoder->audio_input);
0778 
0779     /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
0780     work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
0781     work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
0782     decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
0783     decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
0784 
0785     /* set main volume */
0786     /* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
0787     /*    def:0dB->6dB(MPG600GR) */
0788     /* if mute is on, set mute */
0789     if (decoder->audio_main_mute) {
0790         val = mute | (mute << 8);
0791     } else {
0792         val = (u8)decoder->audio_main_vol_l |
0793             ((u8)decoder->audio_main_vol_r << 8);
0794     }
0795 
0796     saa717x_write(sd, 0x480, val);
0797 
0798     /* set bass and treble */
0799     val = decoder->audio_main_bass & 0x1f;
0800     val |= (decoder->audio_main_treble & 0x1f) << 5;
0801     saa717x_write(sd, 0x488, val);
0802     return 0;
0803 }
0804 
0805 /********** scaling staff ***********/
0806 static void set_h_prescale(struct v4l2_subdev *sd,
0807         int task, int prescale)
0808 {
0809     static const struct {
0810         int xpsc;
0811         int xacl;
0812         int xc2_1;
0813         int xdcg;
0814         int vpfy;
0815     } vals[] = {
0816         /* XPSC XACL XC2_1 XDCG VPFY */
0817         {    1,   0,    0,    0,   0 },
0818         {    2,   2,    1,    2,   2 },
0819         {    3,   4,    1,    3,   2 },
0820         {    4,   8,    1,    4,   2 },
0821         {    5,   8,    1,    4,   2 },
0822         {    6,   8,    1,    4,   3 },
0823         {    7,   8,    1,    4,   3 },
0824         {    8,  15,    0,    4,   3 },
0825         {    9,  15,    0,    4,   3 },
0826         {   10,  16,    1,    5,   3 },
0827     };
0828     static const int count = ARRAY_SIZE(vals);
0829     int i, task_shift;
0830 
0831     task_shift = task * 0x40;
0832     for (i = 0; i < count; i++)
0833         if (vals[i].xpsc == prescale)
0834             break;
0835     if (i == count)
0836         return;
0837 
0838     /* horizontal prescaling */
0839     saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
0840     /* accumulation length */
0841     saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
0842     /* level control */
0843     saa717x_write(sd, 0x62 + task_shift,
0844             (vals[i].xc2_1 << 3) | vals[i].xdcg);
0845     /*FIR prefilter control */
0846     saa717x_write(sd, 0x63 + task_shift,
0847             (vals[i].vpfy << 2) | vals[i].vpfy);
0848 }
0849 
0850 /********** scaling staff ***********/
0851 static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
0852 {
0853     int task_shift;
0854 
0855     task_shift = task * 0x40;
0856     /* Vertical scaling ratio (LOW) */
0857     saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
0858     /* Vertical scaling ratio (HI) */
0859     saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
0860 }
0861 
0862 static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
0863 {
0864     struct v4l2_subdev *sd = to_sd(ctrl);
0865     struct saa717x_state *state = to_state(sd);
0866 
0867     switch (ctrl->id) {
0868     case V4L2_CID_BRIGHTNESS:
0869         saa717x_write(sd, 0x10a, ctrl->val);
0870         return 0;
0871 
0872     case V4L2_CID_CONTRAST:
0873         saa717x_write(sd, 0x10b, ctrl->val);
0874         return 0;
0875 
0876     case V4L2_CID_SATURATION:
0877         saa717x_write(sd, 0x10c, ctrl->val);
0878         return 0;
0879 
0880     case V4L2_CID_HUE:
0881         saa717x_write(sd, 0x10d, ctrl->val);
0882         return 0;
0883 
0884     case V4L2_CID_AUDIO_MUTE:
0885         state->audio_main_mute = ctrl->val;
0886         break;
0887 
0888     case V4L2_CID_AUDIO_VOLUME:
0889         state->audio_main_volume = ctrl->val;
0890         break;
0891 
0892     case V4L2_CID_AUDIO_BALANCE:
0893         state->audio_main_balance = ctrl->val;
0894         break;
0895 
0896     case V4L2_CID_AUDIO_TREBLE:
0897         state->audio_main_treble = ctrl->val;
0898         break;
0899 
0900     case V4L2_CID_AUDIO_BASS:
0901         state->audio_main_bass = ctrl->val;
0902         break;
0903 
0904     default:
0905         return 0;
0906     }
0907     set_audio_regs(sd, state);
0908     return 0;
0909 }
0910 
0911 static int saa717x_s_video_routing(struct v4l2_subdev *sd,
0912                    u32 input, u32 output, u32 config)
0913 {
0914     struct saa717x_state *decoder = to_state(sd);
0915     int is_tuner = input & 0x80;  /* tuner input flag */
0916 
0917     input &= 0x7f;
0918 
0919     v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
0920     /* inputs from 0-9 are available*/
0921     /* saa717x have mode0-mode9 but mode5 is reserved. */
0922     if (input > 9 || input == 5)
0923         return -EINVAL;
0924 
0925     if (decoder->input != input) {
0926         int input_line = input;
0927 
0928         decoder->input = input_line;
0929         v4l2_dbg(1, debug, sd,  "now setting %s input %d\n",
0930                 input_line >= 6 ? "S-Video" : "Composite",
0931                 input_line);
0932 
0933         /* select mode */
0934         saa717x_write(sd, 0x102,
0935                 (saa717x_read(sd, 0x102) & 0xf0) |
0936                 input_line);
0937 
0938         /* bypass chrominance trap for modes 6..9 */
0939         saa717x_write(sd, 0x109,
0940                 (saa717x_read(sd, 0x109) & 0x7f) |
0941                 (input_line < 6 ? 0x0 : 0x80));
0942 
0943         /* change audio_mode */
0944         if (is_tuner) {
0945             /* tuner */
0946             set_audio_mode(sd, decoder->tuner_audio_mode);
0947         } else {
0948             /* Force to STEREO mode if Composite or
0949              * S-Video were chosen */
0950             set_audio_mode(sd, TUNER_AUDIO_STEREO);
0951         }
0952         /* change initialize procedure (Composite/S-Video) */
0953         if (is_tuner)
0954             saa717x_write_regs(sd, reg_init_tuner_input);
0955         else if (input_line >= 6)
0956             saa717x_write_regs(sd, reg_init_svideo_input);
0957         else
0958             saa717x_write_regs(sd, reg_init_composite_input);
0959     }
0960 
0961     return 0;
0962 }
0963 
0964 #ifdef CONFIG_VIDEO_ADV_DEBUG
0965 static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
0966 {
0967     reg->val = saa717x_read(sd, reg->reg);
0968     reg->size = 1;
0969     return 0;
0970 }
0971 
0972 static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
0973 {
0974     u16 addr = reg->reg & 0xffff;
0975     u8 val = reg->val & 0xff;
0976 
0977     saa717x_write(sd, addr, val);
0978     return 0;
0979 }
0980 #endif
0981 
0982 static int saa717x_set_fmt(struct v4l2_subdev *sd,
0983         struct v4l2_subdev_state *sd_state,
0984         struct v4l2_subdev_format *format)
0985 {
0986     struct v4l2_mbus_framefmt *fmt = &format->format;
0987     int prescale, h_scale, v_scale;
0988 
0989     v4l2_dbg(1, debug, sd, "decoder set size\n");
0990 
0991     if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
0992         return -EINVAL;
0993 
0994     /* FIXME need better bounds checking here */
0995     if (fmt->width < 1 || fmt->width > 1440)
0996         return -EINVAL;
0997     if (fmt->height < 1 || fmt->height > 960)
0998         return -EINVAL;
0999 
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);