0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
0040
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
0076 #define TUNER_AUDIO_MONO 0
0077 #define TUNER_AUDIO_STEREO 1
0078 #define TUNER_AUDIO_LANG1 2
0079 #define TUNER_AUDIO_LANG2 3
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;
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;
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
0155 0x101, 0x008,
0156
0157 0x103, 0x000,
0158 0x104, 0x090,
0159 0x105, 0x090,
0160 0x106, 0x0eb,
0161 0x107, 0x0e0,
0162 0x109, 0x055,
0163
0164 0x10f, 0x02a,
0165 0x110, 0x000,
0166
0167 0x114, 0x045,
0168
0169 0x118, 0x040,
0170 0x119, 0x080,
0171
0172 0x044, 0x000,
0173 0x045, 0x000,
0174 0x046, 0x0cf,
0175 0x047, 0x002,
0176
0177 0x049, 0x000,
0178
0179 0x04c, 0x0d0,
0180 0x04d, 0x002,
0181
0182 0x064, 0x080,
0183 0x065, 0x040,
0184 0x066, 0x040,
0185
0186 0x068, 0x000,
0187 0x069, 0x004,
0188 0x06a, 0x000,
0189
0190 0x06e, 0x000,
0191 0x06f, 0x000,
0192
0193 0x072, 0x000,
0194
0195 0x084, 0x000,
0196 0x085, 0x000,
0197 0x086, 0x0cf,
0198 0x087, 0x002,
0199
0200 0x089, 0x000,
0201
0202 0x08c, 0x0d0,
0203 0x08d, 0x002,
0204
0205 0x0a4, 0x080,
0206 0x0a5, 0x040,
0207 0x0a6, 0x040,
0208
0209 0x0a8, 0x000,
0210 0x0a9, 0x004,
0211 0x0aa, 0x000,
0212
0213 0x0ae, 0x000,
0214 0x0af, 0x000,
0215
0216 0x0b2, 0x000,
0217
0218 0x00c, 0x000,
0219 0x00d, 0x000,
0220 0x00e, 0x000,
0221
0222 0x010, 0x010,
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,
0238
0239 0x020, 0x010,
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,
0255
0256 0x030, 0x010,
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,
0272
0273 0x109, 0x085,
0274
0275
0276 0x584, 0x000,
0277 0x585, 0x000,
0278 0x586, 0x003,
0279 0x588, 0x0ff,
0280 0x589, 0x00f,
0281 0x58a, 0x000,
0282 0x58b, 0x000,
0283 0x58c, 0x010,
0284 0x58d, 0x032,
0285 0x58e, 0x054,
0286 0x58f, 0x023,
0287 0x590, 0x000,
0288
0289 0x595, 0x000,
0290 0x596, 0x000,
0291 0x597, 0x000,
0292
0293 0x464, 0x00,
0294
0295 0x46c, 0xbbbb10,
0296 0x470, 0x101010,
0297
0298 0x478, 0x00,
0299
0300 0x474, 0x18,
0301
0302 0x454, 0x0425b9,
0303 0x454, 0x042539,
0304
0305
0306
0307 0x042, 0x003,
0308
0309 0x082, 0x003,
0310
0311 0x108, 0x0f8,
0312 0x2a9, 0x0fd,
0313 0x102, 0x089,
0314 0x111, 0x000,
0315
0316 0x10e, 0x00a,
0317
0318 0x594, 0x002,
0319
0320 0x454, 0x0425b9,
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
0624 static u32 reg_init_tuner_input[] = {
0625 0x108, 0x0f8,
0626 0x111, 0x000,
0627 0x10e, 0x00a,
0628 0, 0
0629 };
0630
0631
0632 static u32 reg_init_composite_input[] = {
0633 0x108, 0x0e8,
0634 0x111, 0x000,
0635 0x10e, 0x04a,
0636 0, 0
0637 };
0638
0639
0640 static u32 reg_init_svideo_input[] = {
0641 0x108, 0x0e8,
0642 0x111, 0x000,
0643 0x10e, 0x04a,
0644 0, 0
0645 };
0646
0647 static u32 reg_set_audio_template[4][2] =
0648 {
0649 {
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 0xbbbb00,
0660
0661
0662
0663
0664
0665 0x00,
0666 },
0667 {
0668 0xbbbb10, 0x101010,
0669 },
0670 {
0671 0xbbbb00, 0x00,
0672 },
0673 {
0674 0xbbbb11, 0x111111,
0675 }
0676 };
0677
0678
0679
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
0717
0718
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
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
0767 static int set_audio_regs(struct v4l2_subdev *sd,
0768 struct saa717x_state *decoder)
0769 {
0770 u8 mute = 0xac;
0771 u32 val;
0772 unsigned int work_l, work_r;
0773
0774
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
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
0786
0787
0788
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
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
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
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
0839 saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
0840
0841 saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
0842
0843 saa717x_write(sd, 0x62 + task_shift,
0844 (vals[i].xc2_1 << 3) | vals[i].xdcg);
0845
0846 saa717x_write(sd, 0x63 + task_shift,
0847 (vals[i].vpfy << 2) | vals[i].vpfy);
0848 }
0849
0850
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
0857 saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
0858
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;
0916
0917 input &= 0x7f;
0918
0919 v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
0920
0921
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
0934 saa717x_write(sd, 0x102,
0935 (saa717x_read(sd, 0x102) & 0xf0) |
0936 input_line);
0937
0938
0939 saa717x_write(sd, 0x109,
0940 (saa717x_read(sd, 0x109) & 0x7f) |
0941 (input_line < 6 ? 0x0 : 0x80));
0942
0943
0944 if (is_tuner) {
0945
0946 set_audio_mode(sd, decoder->tuner_audio_mode);
0947 } else {
0948
0949
0950 set_audio_mode(sd, TUNER_AUDIO_STEREO);
0951 }
0952
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
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
1007
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
1013 v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1014
1015
1016 set_h_prescale(sd, 0, prescale);
1017 set_h_prescale(sd, 1, prescale);
1018
1019
1020
1021 saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
1022 saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1023
1024 saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
1025 saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1026
1027
1028 set_v_scale(sd, 0, v_scale);
1029 set_v_scale(sd, 1, v_scale);
1030
1031
1032
1033
1034 saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1035 saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1036
1037 saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1038 saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1039
1040
1041
1042 saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1043 saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1044
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) {
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
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
1127
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
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
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
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
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
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
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
1305 decoder->playback = 0;
1306 decoder->audio = 1;
1307
1308 decoder->audio_input = 2;
1309
1310 decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1311
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
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);