1 /* 2 * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips 3 * 4 * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> 5 * 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 */ 18 19 #include <linux/delay.h> 20 #include <linux/module.h> 21 #include <linux/init.h> 22 #include <linux/slab.h> 23 #include <linux/sched.h> 24 #include <asm/io.h> 25 #include <media/v4l2-device.h> 26 #include <media/v4l2-dev.h> 27 #include <media/v4l2-fh.h> 28 #include <media/v4l2-ioctl.h> 29 #include <media/v4l2-event.h> 30 #include <media/drv-intf/tea575x.h> 31 32 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 33 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); 34 MODULE_LICENSE("GPL"); 35 36 /* 37 * definitions 38 */ 39 40 #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ 41 #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ 42 #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ 43 #define TEA575X_BIT_BAND_MASK (3<<20) 44 #define TEA575X_BIT_BAND_FM (0<<20) 45 #define TEA575X_BIT_BAND_MW (1<<20) 46 #define TEA575X_BIT_BAND_LW (2<<20) 47 #define TEA575X_BIT_BAND_SW (3<<20) 48 #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ 49 #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ 50 #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ 51 #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ 52 #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ 53 #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ 54 #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ 55 #define TEA575X_BIT_DUMMY (1<<15) /* buffer */ 56 #define TEA575X_BIT_FREQ_MASK 0x7fff 57 58 enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; 59 60 static const struct v4l2_frequency_band bands[] = { 61 { 62 .type = V4L2_TUNER_RADIO, 63 .index = 0, 64 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | 65 V4L2_TUNER_CAP_FREQ_BANDS, 66 .rangelow = 87500 * 16, 67 .rangehigh = 108000 * 16, 68 .modulation = V4L2_BAND_MODULATION_FM, 69 }, 70 { 71 .type = V4L2_TUNER_RADIO, 72 .index = 0, 73 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | 74 V4L2_TUNER_CAP_FREQ_BANDS, 75 .rangelow = 76000 * 16, 76 .rangehigh = 91000 * 16, 77 .modulation = V4L2_BAND_MODULATION_FM, 78 }, 79 { 80 .type = V4L2_TUNER_RADIO, 81 .index = 1, 82 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, 83 .rangelow = 530 * 16, 84 .rangehigh = 1710 * 16, 85 .modulation = V4L2_BAND_MODULATION_AM, 86 }, 87 }; 88 89 /* 90 * lowlevel part 91 */ 92 93 static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) 94 { 95 u16 l; 96 u8 data; 97 98 if (tea->ops->write_val) 99 return tea->ops->write_val(tea, val); 100 101 tea->ops->set_direction(tea, 1); 102 udelay(16); 103 104 for (l = 25; l > 0; l--) { 105 data = (val >> 24) & TEA575X_DATA; 106 val <<= 1; /* shift data */ 107 tea->ops->set_pins(tea, data | TEA575X_WREN); 108 udelay(2); 109 tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); 110 udelay(2); 111 tea->ops->set_pins(tea, data | TEA575X_WREN); 112 udelay(2); 113 } 114 115 if (!tea->mute) 116 tea->ops->set_pins(tea, 0); 117 } 118 119 static u32 snd_tea575x_read(struct snd_tea575x *tea) 120 { 121 u16 l, rdata; 122 u32 data = 0; 123 124 if (tea->ops->read_val) 125 return tea->ops->read_val(tea); 126 127 tea->ops->set_direction(tea, 0); 128 tea->ops->set_pins(tea, 0); 129 udelay(16); 130 131 for (l = 24; l--;) { 132 tea->ops->set_pins(tea, TEA575X_CLK); 133 udelay(2); 134 if (!l) 135 tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; 136 tea->ops->set_pins(tea, 0); 137 udelay(2); 138 data <<= 1; /* shift data */ 139 rdata = tea->ops->get_pins(tea); 140 if (!l) 141 tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; 142 if (rdata & TEA575X_DATA) 143 data++; 144 udelay(2); 145 } 146 147 if (tea->mute) 148 tea->ops->set_pins(tea, TEA575X_WREN); 149 150 return data; 151 } 152 153 static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) 154 { 155 u32 freq = val & TEA575X_BIT_FREQ_MASK; 156 157 if (freq == 0) 158 return freq; 159 160 switch (tea->band) { 161 case BAND_FM: 162 /* freq *= 12.5 */ 163 freq *= 125; 164 freq /= 10; 165 /* crystal fixup */ 166 freq -= TEA575X_FMIF; 167 break; 168 case BAND_FM_JAPAN: 169 /* freq *= 12.5 */ 170 freq *= 125; 171 freq /= 10; 172 /* crystal fixup */ 173 freq += TEA575X_FMIF; 174 break; 175 case BAND_AM: 176 /* crystal fixup */ 177 freq -= TEA575X_AMIF; 178 break; 179 } 180 181 return clamp(freq * 16, bands[tea->band].rangelow, 182 bands[tea->band].rangehigh); /* from kHz */ 183 } 184 185 static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) 186 { 187 return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); 188 } 189 190 void snd_tea575x_set_freq(struct snd_tea575x *tea) 191 { 192 u32 freq = tea->freq / 16; /* to kHz */ 193 u32 band = 0; 194 195 switch (tea->band) { 196 case BAND_FM: 197 band = TEA575X_BIT_BAND_FM; 198 /* crystal fixup */ 199 freq += TEA575X_FMIF; 200 /* freq /= 12.5 */ 201 freq *= 10; 202 freq /= 125; 203 break; 204 case BAND_FM_JAPAN: 205 band = TEA575X_BIT_BAND_FM; 206 /* crystal fixup */ 207 freq -= TEA575X_FMIF; 208 /* freq /= 12.5 */ 209 freq *= 10; 210 freq /= 125; 211 break; 212 case BAND_AM: 213 band = TEA575X_BIT_BAND_MW; 214 /* crystal fixup */ 215 freq += TEA575X_AMIF; 216 break; 217 } 218 219 tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); 220 tea->val |= band; 221 tea->val |= freq & TEA575X_BIT_FREQ_MASK; 222 snd_tea575x_write(tea, tea->val); 223 tea->freq = snd_tea575x_val_to_freq(tea, tea->val); 224 } 225 EXPORT_SYMBOL(snd_tea575x_set_freq); 226 227 /* 228 * Linux Video interface 229 */ 230 231 static int vidioc_querycap(struct file *file, void *priv, 232 struct v4l2_capability *v) 233 { 234 struct snd_tea575x *tea = video_drvdata(file); 235 236 strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); 237 strscpy(v->card, tea->card, sizeof(v->card)); 238 strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); 239 strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); 240 v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 241 if (!tea->cannot_read_data) 242 v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; 243 v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; 244 return 0; 245 } 246 247 int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea, 248 struct v4l2_frequency_band *band) 249 { 250 int index; 251 252 if (band->tuner != 0) 253 return -EINVAL; 254 255 switch (band->index) { 256 case 0: 257 if (tea->tea5759) 258 index = BAND_FM_JAPAN; 259 else 260 index = BAND_FM; 261 break; 262 case 1: 263 if (tea->has_am) { 264 index = BAND_AM; 265 break; 266 } 267 /* Fall through */ 268 default: 269 return -EINVAL; 270 } 271 272 *band = bands[index]; 273 if (!tea->cannot_read_data) 274 band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; 275 276 return 0; 277 } 278 EXPORT_SYMBOL(snd_tea575x_enum_freq_bands); 279 280 static int vidioc_enum_freq_bands(struct file *file, void *priv, 281 struct v4l2_frequency_band *band) 282 { 283 struct snd_tea575x *tea = video_drvdata(file); 284 285 return snd_tea575x_enum_freq_bands(tea, band); 286 } 287 288 int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v) 289 { 290 struct v4l2_frequency_band band_fm = { 0, }; 291 292 if (v->index > 0) 293 return -EINVAL; 294 295 snd_tea575x_read(tea); 296 snd_tea575x_enum_freq_bands(tea, &band_fm); 297 298 memset(v, 0, sizeof(*v)); 299 strscpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); 300 v->type = V4L2_TUNER_RADIO; 301 v->capability = band_fm.capability; 302 v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; 303 v->rangehigh = band_fm.rangehigh; 304 v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; 305 v->audmode = (tea->val & TEA575X_BIT_MONO) ? 306 V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; 307 v->signal = tea->tuned ? 0xffff : 0; 308 return 0; 309 } 310 EXPORT_SYMBOL(snd_tea575x_g_tuner); 311 312 static int vidioc_g_tuner(struct file *file, void *priv, 313 struct v4l2_tuner *v) 314 { 315 struct snd_tea575x *tea = video_drvdata(file); 316 317 return snd_tea575x_g_tuner(tea, v); 318 } 319 320 static int vidioc_s_tuner(struct file *file, void *priv, 321 const struct v4l2_tuner *v) 322 { 323 struct snd_tea575x *tea = video_drvdata(file); 324 u32 orig_val = tea->val; 325 326 if (v->index) 327 return -EINVAL; 328 tea->val &= ~TEA575X_BIT_MONO; 329 if (v->audmode == V4L2_TUNER_MODE_MONO) 330 tea->val |= TEA575X_BIT_MONO; 331 /* Only apply changes if currently tuning FM */ 332 if (tea->band != BAND_AM && tea->val != orig_val) 333 snd_tea575x_set_freq(tea); 334 335 return 0; 336 } 337 338 static int vidioc_g_frequency(struct file *file, void *priv, 339 struct v4l2_frequency *f) 340 { 341 struct snd_tea575x *tea = video_drvdata(file); 342 343 if (f->tuner != 0) 344 return -EINVAL; 345 f->type = V4L2_TUNER_RADIO; 346 f->frequency = tea->freq; 347 return 0; 348 } 349 350 static int vidioc_s_frequency(struct file *file, void *priv, 351 const struct v4l2_frequency *f) 352 { 353 struct snd_tea575x *tea = video_drvdata(file); 354 355 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 356 return -EINVAL; 357 358 if (tea->has_am && f->frequency < (20000 * 16)) 359 tea->band = BAND_AM; 360 else if (tea->tea5759) 361 tea->band = BAND_FM_JAPAN; 362 else 363 tea->band = BAND_FM; 364 365 tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, 366 bands[tea->band].rangehigh); 367 snd_tea575x_set_freq(tea); 368 return 0; 369 } 370 371 int snd_tea575x_s_hw_freq_seek(struct file *file, struct snd_tea575x *tea, 372 const struct v4l2_hw_freq_seek *a) 373 { 374 unsigned long timeout; 375 int i, spacing; 376 377 if (tea->cannot_read_data) 378 return -ENOTTY; 379 if (a->tuner || a->wrap_around) 380 return -EINVAL; 381 382 if (file->f_flags & O_NONBLOCK) 383 return -EWOULDBLOCK; 384 385 if (a->rangelow || a->rangehigh) { 386 for (i = 0; i < ARRAY_SIZE(bands); i++) { 387 if ((i == BAND_FM && tea->tea5759) || 388 (i == BAND_FM_JAPAN && !tea->tea5759) || 389 (i == BAND_AM && !tea->has_am)) 390 continue; 391 if (bands[i].rangelow == a->rangelow && 392 bands[i].rangehigh == a->rangehigh) 393 break; 394 } 395 if (i == ARRAY_SIZE(bands)) 396 return -EINVAL; /* No matching band found */ 397 if (i != tea->band) { 398 tea->band = i; 399 tea->freq = clamp(tea->freq, bands[i].rangelow, 400 bands[i].rangehigh); 401 snd_tea575x_set_freq(tea); 402 } 403 } 404 405 spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ 406 407 /* clear the frequency, HW will fill it in */ 408 tea->val &= ~TEA575X_BIT_FREQ_MASK; 409 tea->val |= TEA575X_BIT_SEARCH; 410 if (a->seek_upward) 411 tea->val |= TEA575X_BIT_UPDOWN; 412 else 413 tea->val &= ~TEA575X_BIT_UPDOWN; 414 snd_tea575x_write(tea, tea->val); 415 timeout = jiffies + msecs_to_jiffies(10000); 416 for (;;) { 417 if (time_after(jiffies, timeout)) 418 break; 419 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { 420 /* some signal arrived, stop search */ 421 tea->val &= ~TEA575X_BIT_SEARCH; 422 snd_tea575x_set_freq(tea); 423 return -ERESTARTSYS; 424 } 425 if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { 426 u32 freq; 427 428 /* Found a frequency, wait until it can be read */ 429 for (i = 0; i < 100; i++) { 430 msleep(10); 431 freq = snd_tea575x_get_freq(tea); 432 if (freq) /* available */ 433 break; 434 } 435 if (freq == 0) /* shouldn't happen */ 436 break; 437 /* 438 * if we moved by less than the spacing, or in the 439 * wrong direction, continue seeking 440 */ 441 if (abs(tea->freq - freq) < 16 * spacing || 442 (a->seek_upward && freq < tea->freq) || 443 (!a->seek_upward && freq > tea->freq)) { 444 snd_tea575x_write(tea, tea->val); 445 continue; 446 } 447 tea->freq = freq; 448 tea->val &= ~TEA575X_BIT_SEARCH; 449 return 0; 450 } 451 } 452 tea->val &= ~TEA575X_BIT_SEARCH; 453 snd_tea575x_set_freq(tea); 454 return -ENODATA; 455 } 456 EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek); 457 458 static int vidioc_s_hw_freq_seek(struct file *file, void *fh, 459 const struct v4l2_hw_freq_seek *a) 460 { 461 struct snd_tea575x *tea = video_drvdata(file); 462 463 return snd_tea575x_s_hw_freq_seek(file, tea, a); 464 } 465 466 static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) 467 { 468 struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); 469 470 switch (ctrl->id) { 471 case V4L2_CID_AUDIO_MUTE: 472 tea->mute = ctrl->val; 473 snd_tea575x_set_freq(tea); 474 return 0; 475 } 476 477 return -EINVAL; 478 } 479 480 static const struct v4l2_file_operations tea575x_fops = { 481 .unlocked_ioctl = video_ioctl2, 482 .open = v4l2_fh_open, 483 .release = v4l2_fh_release, 484 .poll = v4l2_ctrl_poll, 485 }; 486 487 static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { 488 .vidioc_querycap = vidioc_querycap, 489 .vidioc_g_tuner = vidioc_g_tuner, 490 .vidioc_s_tuner = vidioc_s_tuner, 491 .vidioc_g_frequency = vidioc_g_frequency, 492 .vidioc_s_frequency = vidioc_s_frequency, 493 .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, 494 .vidioc_enum_freq_bands = vidioc_enum_freq_bands, 495 .vidioc_log_status = v4l2_ctrl_log_status, 496 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 497 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 498 }; 499 500 static const struct video_device tea575x_radio = { 501 .ioctl_ops = &tea575x_ioctl_ops, 502 .release = video_device_release_empty, 503 }; 504 505 static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { 506 .s_ctrl = tea575x_s_ctrl, 507 }; 508 509 510 int snd_tea575x_hw_init(struct snd_tea575x *tea) 511 { 512 tea->mute = true; 513 514 /* Not all devices can or know how to read the data back. 515 Such devices can set cannot_read_data to true. */ 516 if (!tea->cannot_read_data) { 517 snd_tea575x_write(tea, 0x55AA); 518 if (snd_tea575x_read(tea) != 0x55AA) 519 return -ENODEV; 520 } 521 522 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; 523 tea->freq = 90500 * 16; /* 90.5Mhz default */ 524 snd_tea575x_set_freq(tea); 525 526 return 0; 527 } 528 EXPORT_SYMBOL(snd_tea575x_hw_init); 529 530 int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) 531 { 532 int retval = snd_tea575x_hw_init(tea); 533 534 if (retval) 535 return retval; 536 537 tea->vd = tea575x_radio; 538 video_set_drvdata(&tea->vd, tea); 539 mutex_init(&tea->mutex); 540 strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); 541 tea->vd.lock = &tea->mutex; 542 tea->vd.v4l2_dev = tea->v4l2_dev; 543 tea->fops = tea575x_fops; 544 tea->fops.owner = owner; 545 tea->vd.fops = &tea->fops; 546 /* disable hw_freq_seek if we can't use it */ 547 if (tea->cannot_read_data) 548 v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); 549 550 if (!tea->cannot_mute) { 551 tea->vd.ctrl_handler = &tea->ctrl_handler; 552 v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); 553 v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, 554 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); 555 retval = tea->ctrl_handler.error; 556 if (retval) { 557 v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); 558 v4l2_ctrl_handler_free(&tea->ctrl_handler); 559 return retval; 560 } 561 562 if (tea->ext_init) { 563 retval = tea->ext_init(tea); 564 if (retval) { 565 v4l2_ctrl_handler_free(&tea->ctrl_handler); 566 return retval; 567 } 568 } 569 570 v4l2_ctrl_handler_setup(&tea->ctrl_handler); 571 } 572 573 retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); 574 if (retval) { 575 v4l2_err(tea->v4l2_dev, "can't register video device!\n"); 576 v4l2_ctrl_handler_free(tea->vd.ctrl_handler); 577 return retval; 578 } 579 580 return 0; 581 } 582 EXPORT_SYMBOL(snd_tea575x_init); 583 584 void snd_tea575x_exit(struct snd_tea575x *tea) 585 { 586 video_unregister_device(&tea->vd); 587 v4l2_ctrl_handler_free(tea->vd.ctrl_handler); 588 } 589 EXPORT_SYMBOL(snd_tea575x_exit); 590