1 /* 2 * Copyright (C) 2005-2006 Micronas USA Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License (Version 2) as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/i2c.h> 17 #include <linux/videodev2.h> 18 #include <media/tuner.h> 19 #include <media/v4l2-common.h> 20 #include <media/v4l2-ioctl.h> 21 #include <media/v4l2-device.h> 22 #include <linux/slab.h> 23 24 MODULE_DESCRIPTION("sony-btf-mpx driver"); 25 MODULE_LICENSE("GPL v2"); 26 27 static int debug; 28 module_param(debug, int, 0644); 29 MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on"); 30 31 /* #define MPX_DEBUG */ 32 33 /* 34 * Note: 35 * 36 * AS(IF/MPX) pin: LOW HIGH/OPEN 37 * IF/MPX address: 0x42/0x40 0x43/0x44 38 */ 39 40 41 static int force_mpx_mode = -1; 42 module_param(force_mpx_mode, int, 0644); 43 44 struct sony_btf_mpx { 45 struct v4l2_subdev sd; 46 int mpxmode; 47 u32 audmode; 48 }; 49 50 static inline struct sony_btf_mpx *to_state(struct v4l2_subdev *sd) 51 { 52 return container_of(sd, struct sony_btf_mpx, sd); 53 } 54 55 static int mpx_write(struct i2c_client *client, int dev, int addr, int val) 56 { 57 u8 buffer[5]; 58 struct i2c_msg msg; 59 60 buffer[0] = dev; 61 buffer[1] = addr >> 8; 62 buffer[2] = addr & 0xff; 63 buffer[3] = val >> 8; 64 buffer[4] = val & 0xff; 65 msg.addr = client->addr; 66 msg.flags = 0; 67 msg.len = 5; 68 msg.buf = buffer; 69 i2c_transfer(client->adapter, &msg, 1); 70 return 0; 71 } 72 73 /* 74 * MPX register values for the BTF-PG472Z: 75 * 76 * FM_ NICAM_ SCART_ 77 * MODUS SOURCE ACB PRESCAL PRESCAL PRESCAL SYSTEM VOLUME 78 * 10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000 79 * --------------------------------------------------------------- 80 * Auto 1003 0020 0100 2603 5000 XXXX 0001 7500 81 * 82 * B/G 83 * Mono 1003 0020 0100 2603 5000 XXXX 0003 7500 84 * A2 1003 0020 0100 2601 5000 XXXX 0003 7500 85 * NICAM 1003 0120 0100 2603 5000 XXXX 0008 7500 86 * 87 * I 88 * Mono 1003 0020 0100 2603 7900 XXXX 000A 7500 89 * NICAM 1003 0120 0100 2603 7900 XXXX 000A 7500 90 * 91 * D/K 92 * Mono 1003 0020 0100 2603 5000 XXXX 0004 7500 93 * A2-1 1003 0020 0100 2601 5000 XXXX 0004 7500 94 * A2-2 1003 0020 0100 2601 5000 XXXX 0005 7500 95 * A2-3 1003 0020 0100 2601 5000 XXXX 0007 7500 96 * NICAM 1003 0120 0100 2603 5000 XXXX 000B 7500 97 * 98 * L/L' 99 * Mono 0003 0200 0100 7C03 5000 2200 0009 7500 100 * NICAM 0003 0120 0100 7C03 5000 XXXX 0009 7500 101 * 102 * M 103 * Mono 1003 0200 0100 2B03 5000 2B00 0002 7500 104 * 105 * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX. 106 * 107 * Bilingual selection in A2/NICAM: 108 * 109 * High byte of SOURCE Left chan Right chan 110 * 0x01 MAIN SUB 111 * 0x03 MAIN MAIN 112 * 0x04 SUB SUB 113 * 114 * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or 115 * 0x00 (all other bands). Force mono in A2 with FMONO_A2: 116 * 117 * FMONO_A2 118 * 10/0022 119 * -------- 120 * Forced mono ON 07F0 121 * Forced mono OFF 0190 122 */ 123 124 static const struct { 125 enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode; 126 u16 modus; 127 u16 source; 128 u16 acb; 129 u16 fm_prescale; 130 u16 nicam_prescale; 131 u16 scart_prescale; 132 u16 system; 133 u16 volume; 134 } mpx_audio_modes[] = { 135 /* Auto */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, 136 0x5000, 0x0000, 0x0001, 0x7500 }, 137 /* B/G Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, 138 0x5000, 0x0000, 0x0003, 0x7500 }, 139 /* B/G A2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, 140 0x5000, 0x0000, 0x0003, 0x7500 }, 141 /* B/G NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, 142 0x5000, 0x0000, 0x0008, 0x7500 }, 143 /* I Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, 144 0x7900, 0x0000, 0x000A, 0x7500 }, 145 /* I NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, 146 0x7900, 0x0000, 0x000A, 0x7500 }, 147 /* D/K Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, 148 0x5000, 0x0000, 0x0004, 0x7500 }, 149 /* D/K A2-1 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, 150 0x5000, 0x0000, 0x0004, 0x7500 }, 151 /* D/K A2-2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, 152 0x5000, 0x0000, 0x0005, 0x7500 }, 153 /* D/K A2-3 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, 154 0x5000, 0x0000, 0x0007, 0x7500 }, 155 /* D/K NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, 156 0x5000, 0x0000, 0x000B, 0x7500 }, 157 /* L/L' Mono */ { AUD_MONO, 0x0003, 0x0200, 0x0100, 0x7C03, 158 0x5000, 0x2200, 0x0009, 0x7500 }, 159 /* L/L' NICAM */{ AUD_NICAM_L, 0x0003, 0x0120, 0x0100, 0x7C03, 160 0x5000, 0x0000, 0x0009, 0x7500 }, 161 }; 162 163 #define MPX_NUM_MODES ARRAY_SIZE(mpx_audio_modes) 164 165 static int mpx_setup(struct sony_btf_mpx *t) 166 { 167 struct i2c_client *client = v4l2_get_subdevdata(&t->sd); 168 u16 source = 0; 169 u8 buffer[3]; 170 struct i2c_msg msg; 171 int mode = t->mpxmode; 172 173 /* reset MPX */ 174 buffer[0] = 0x00; 175 buffer[1] = 0x80; 176 buffer[2] = 0x00; 177 msg.addr = client->addr; 178 msg.flags = 0; 179 msg.len = 3; 180 msg.buf = buffer; 181 i2c_transfer(client->adapter, &msg, 1); 182 buffer[1] = 0x00; 183 i2c_transfer(client->adapter, &msg, 1); 184 185 if (t->audmode != V4L2_TUNER_MODE_MONO) 186 mode++; 187 188 if (mpx_audio_modes[mode].audio_mode != AUD_MONO) { 189 switch (t->audmode) { 190 case V4L2_TUNER_MODE_MONO: 191 switch (mpx_audio_modes[mode].audio_mode) { 192 case AUD_A2: 193 source = mpx_audio_modes[mode].source; 194 break; 195 case AUD_NICAM: 196 source = 0x0000; 197 break; 198 case AUD_NICAM_L: 199 source = 0x0200; 200 break; 201 default: 202 break; 203 } 204 break; 205 case V4L2_TUNER_MODE_STEREO: 206 source = mpx_audio_modes[mode].source; 207 break; 208 case V4L2_TUNER_MODE_LANG1: 209 source = 0x0300; 210 break; 211 case V4L2_TUNER_MODE_LANG2: 212 source = 0x0400; 213 break; 214 } 215 source |= mpx_audio_modes[mode].source & 0x00ff; 216 } else 217 source = mpx_audio_modes[mode].source; 218 219 mpx_write(client, 0x10, 0x0030, mpx_audio_modes[mode].modus); 220 mpx_write(client, 0x12, 0x0008, source); 221 mpx_write(client, 0x12, 0x0013, mpx_audio_modes[mode].acb); 222 mpx_write(client, 0x12, 0x000e, 223 mpx_audio_modes[mode].fm_prescale); 224 mpx_write(client, 0x12, 0x0010, 225 mpx_audio_modes[mode].nicam_prescale); 226 mpx_write(client, 0x12, 0x000d, 227 mpx_audio_modes[mode].scart_prescale); 228 mpx_write(client, 0x10, 0x0020, mpx_audio_modes[mode].system); 229 mpx_write(client, 0x12, 0x0000, mpx_audio_modes[mode].volume); 230 if (mpx_audio_modes[mode].audio_mode == AUD_A2) 231 mpx_write(client, 0x10, 0x0022, 232 t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190); 233 234 #ifdef MPX_DEBUG 235 { 236 u8 buf1[3], buf2[2]; 237 struct i2c_msg msgs[2]; 238 239 v4l2_info(client, 240 "MPX registers: %04x %04x %04x %04x %04x %04x %04x %04x\n", 241 mpx_audio_modes[mode].modus, 242 source, 243 mpx_audio_modes[mode].acb, 244 mpx_audio_modes[mode].fm_prescale, 245 mpx_audio_modes[mode].nicam_prescale, 246 mpx_audio_modes[mode].scart_prescale, 247 mpx_audio_modes[mode].system, 248 mpx_audio_modes[mode].volume); 249 buf1[0] = 0x11; 250 buf1[1] = 0x00; 251 buf1[2] = 0x7e; 252 msgs[0].addr = client->addr; 253 msgs[0].flags = 0; 254 msgs[0].len = 3; 255 msgs[0].buf = buf1; 256 msgs[1].addr = client->addr; 257 msgs[1].flags = I2C_M_RD; 258 msgs[1].len = 2; 259 msgs[1].buf = buf2; 260 i2c_transfer(client->adapter, msgs, 2); 261 v4l2_info(client, "MPX system: %02x%02x\n", 262 buf2[0], buf2[1]); 263 buf1[0] = 0x11; 264 buf1[1] = 0x02; 265 buf1[2] = 0x00; 266 i2c_transfer(client->adapter, msgs, 2); 267 v4l2_info(client, "MPX status: %02x%02x\n", 268 buf2[0], buf2[1]); 269 } 270 #endif 271 return 0; 272 } 273 274 275 static int sony_btf_mpx_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 276 { 277 struct sony_btf_mpx *t = to_state(sd); 278 int default_mpx_mode = 0; 279 280 if (std & V4L2_STD_PAL_BG) 281 default_mpx_mode = 1; 282 else if (std & V4L2_STD_PAL_I) 283 default_mpx_mode = 4; 284 else if (std & V4L2_STD_PAL_DK) 285 default_mpx_mode = 6; 286 else if (std & V4L2_STD_SECAM_L) 287 default_mpx_mode = 11; 288 289 if (default_mpx_mode != t->mpxmode) { 290 t->mpxmode = default_mpx_mode; 291 mpx_setup(t); 292 } 293 return 0; 294 } 295 296 static int sony_btf_mpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) 297 { 298 struct sony_btf_mpx *t = to_state(sd); 299 300 vt->capability = V4L2_TUNER_CAP_NORM | 301 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | 302 V4L2_TUNER_CAP_LANG2; 303 vt->rxsubchans = V4L2_TUNER_SUB_MONO | 304 V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 | 305 V4L2_TUNER_SUB_LANG2; 306 vt->audmode = t->audmode; 307 return 0; 308 } 309 310 static int sony_btf_mpx_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) 311 { 312 struct sony_btf_mpx *t = to_state(sd); 313 314 if (vt->type != V4L2_TUNER_ANALOG_TV) 315 return -EINVAL; 316 317 if (vt->audmode != t->audmode) { 318 t->audmode = vt->audmode; 319 mpx_setup(t); 320 } 321 return 0; 322 } 323 324 /* --------------------------------------------------------------------------*/ 325 326 static const struct v4l2_subdev_tuner_ops sony_btf_mpx_tuner_ops = { 327 .s_tuner = sony_btf_mpx_s_tuner, 328 .g_tuner = sony_btf_mpx_g_tuner, 329 }; 330 331 static const struct v4l2_subdev_video_ops sony_btf_mpx_video_ops = { 332 .s_std = sony_btf_mpx_s_std, 333 }; 334 335 static const struct v4l2_subdev_ops sony_btf_mpx_ops = { 336 .tuner = &sony_btf_mpx_tuner_ops, 337 .video = &sony_btf_mpx_video_ops, 338 }; 339 340 /* --------------------------------------------------------------------------*/ 341 342 static int sony_btf_mpx_probe(struct i2c_client *client, 343 const struct i2c_device_id *id) 344 { 345 struct sony_btf_mpx *t; 346 struct v4l2_subdev *sd; 347 348 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 349 return -ENODEV; 350 351 v4l_info(client, "chip found @ 0x%x (%s)\n", 352 client->addr << 1, client->adapter->name); 353 354 t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); 355 if (t == NULL) 356 return -ENOMEM; 357 358 sd = &t->sd; 359 v4l2_i2c_subdev_init(sd, client, &sony_btf_mpx_ops); 360 361 /* Initialize sony_btf_mpx */ 362 t->mpxmode = 0; 363 t->audmode = V4L2_TUNER_MODE_STEREO; 364 365 return 0; 366 } 367 368 static int sony_btf_mpx_remove(struct i2c_client *client) 369 { 370 struct v4l2_subdev *sd = i2c_get_clientdata(client); 371 372 v4l2_device_unregister_subdev(sd); 373 374 return 0; 375 } 376 377 /* ----------------------------------------------------------------------- */ 378 379 static const struct i2c_device_id sony_btf_mpx_id[] = { 380 { "sony-btf-mpx", 0 }, 381 { } 382 }; 383 MODULE_DEVICE_TABLE(i2c, sony_btf_mpx_id); 384 385 static struct i2c_driver sony_btf_mpx_driver = { 386 .driver = { 387 .name = "sony-btf-mpx", 388 }, 389 .probe = sony_btf_mpx_probe, 390 .remove = sony_btf_mpx_remove, 391 .id_table = sony_btf_mpx_id, 392 }; 393 module_i2c_driver(sony_btf_mpx_driver); 394