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