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