1 /* $OpenBSD: fmsradio.c,v 1.9 2024/05/24 06:02:53 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Vladimir Popov <jumbo@narod.ru> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* Device Driver for FM Tuners attached to FM801 */ 30 31 /* Currently supported tuners: 32 * o SoundForte RadioLink SF64-PCR PCI Radio Card 33 * o SoundForte Quad X-treme SF256-PCP-R PCI Sound Card with FM Radio 34 * o SoundForte Theatre X-treme 5.1 SF256-PCS-R PCI Sound Card with FM Radio 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/malloc.h> 40 #include <sys/device.h> 41 #include <sys/errno.h> 42 #include <sys/audioio.h> 43 #include <sys/radioio.h> 44 45 #include <machine/bus.h> 46 47 #include <dev/radio_if.h> 48 49 #include <dev/ic/ac97.h> 50 51 #include <dev/pci/fmsreg.h> 52 #include <dev/pci/fmsvar.h> 53 54 #include <dev/ic/tea5757.h> 55 56 #define TUNER_UNKNOWN 0 57 #define TUNER_SF256PCPR 1 58 #define TUNER_SF64PCR 2 59 #define TUNER_SF256PCS 3 60 61 #define SF64PCR_CAPS RADIO_CAPS_DETECT_STEREO | \ 62 RADIO_CAPS_DETECT_SIGNAL | \ 63 RADIO_CAPS_SET_MONO | \ 64 RADIO_CAPS_HW_SEARCH | \ 65 RADIO_CAPS_HW_AFC | \ 66 RADIO_CAPS_LOCK_SENSITIVITY 67 68 #define SF256PCPR_CAPS RADIO_CAPS_DETECT_STEREO | \ 69 RADIO_CAPS_SET_MONO | \ 70 RADIO_CAPS_HW_SEARCH | \ 71 RADIO_CAPS_HW_AFC | \ 72 RADIO_CAPS_LOCK_SENSITIVITY 73 74 #define SF256PCS_CAPS RADIO_CAPS_SET_MONO | \ 75 RADIO_CAPS_HW_SEARCH | \ 76 RADIO_CAPS_HW_AFC | \ 77 RADIO_CAPS_LOCK_SENSITIVITY 78 79 #define PCR_WREN_ON 0 80 #define PCR_WREN_OFF FM_IO_PIN1 81 #define PCR_CLOCK_ON FM_IO_PIN0 82 #define PCR_CLOCK_OFF 0 83 #define PCR_DATA_ON FM_IO_PIN2 84 #define PCR_DATA_OFF 0 85 86 #define PCR_SIGNAL 0x80 87 #define PCR_STEREO 0x80 88 #define PCR_INFO_SIGNAL (1 << 24) 89 #define PCR_INFO_STEREO (1 << 25) 90 91 #define PCPR_WREN_ON 0 92 #define PCPR_WREN_OFF FM_IO_PIN2 93 #define PCPR_CLOCK_ON FM_IO_PIN0 94 #define PCPR_CLOCK_OFF 0 95 #define PCPR_DATA_ON FM_IO_PIN1 96 #define PCPR_DATA_OFF 0 97 #define PCPR_INFO_STEREO 0x04 98 99 #define PCS_WREN_ON 0 100 #define PCS_WREN_OFF FM_IO_PIN2 101 #define PCS_CLOCK_ON FM_IO_PIN3 102 #define PCS_CLOCK_OFF 0 103 #define PCS_DATA_ON FM_IO_PIN1 104 #define PCS_DATA_OFF 0 105 106 /* 107 * Function prototypes 108 */ 109 void fmsradio_set_mute(struct fms_softc *); 110 111 void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 112 void sf64pcr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 113 void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); 114 u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); 115 int sf64pcr_probe(struct fms_softc *); 116 117 void sf256pcpr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 118 void sf256pcpr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 119 void sf256pcpr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); 120 u_int32_t sf256pcpr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); 121 int sf256pcpr_probe(struct fms_softc *); 122 123 void sf256pcs_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 124 void sf256pcs_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 125 void sf256pcs_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); 126 u_int32_t sf256pcs_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); 127 int sf256pcs_probe(struct fms_softc *); 128 129 int fmsradio_get_info(void *, struct radio_info *); 130 int fmsradio_set_info(void *, struct radio_info *); 131 int fmsradio_search(void *, int); 132 133 const struct radio_hw_if fmsradio_hw_if = { 134 NULL, /* open */ 135 NULL, /* close */ 136 fmsradio_get_info, 137 fmsradio_set_info, 138 fmsradio_search 139 }; 140 141 struct fmsradio_if { 142 int type; /* Card type */ 143 144 int mute; 145 u_int8_t vol; 146 u_int32_t freq; 147 u_int32_t stereo; 148 u_int32_t lock; 149 150 struct tea5757_t tea; 151 }; 152 153 int 154 fmsradio_attach(struct fms_softc *sc) 155 { 156 struct fmsradio_if *r; 157 158 r = malloc(sizeof(struct fmsradio_if), M_DEVBUF, M_NOWAIT); 159 if (r == NULL) { 160 printf("%s: cannot allocate memory for FM tuner config\n", 161 sc->sc_dev.dv_xname); 162 return TUNER_UNKNOWN; 163 } 164 165 sc->radio = r; 166 r->tea.iot = sc->sc_iot; 167 r->tea.ioh = sc->sc_ioh; 168 r->tea.offset = FM_IO_CTL; 169 r->tea.flags = sc->sc_dev.dv_cfdata->cf_flags; 170 r->vol = 0; 171 r->mute = 0; 172 r->freq = MIN_FM_FREQ; 173 r->stereo = TEA5757_STEREO; 174 r->lock = TEA5757_S030; 175 176 r->type = TUNER_UNKNOWN; 177 if ((r->type = sf64pcr_probe(sc)) == TUNER_SF64PCR) 178 printf("%s: SF64-PCR FM Radio\n", sc->sc_dev.dv_xname); 179 else if ((r->type = sf256pcpr_probe(sc)) == TUNER_SF256PCPR) 180 printf("%s: SF256-PCP-R FM Radio\n", sc->sc_dev.dv_xname); 181 else if ((r->type = sf256pcs_probe(sc)) == TUNER_SF256PCS) 182 printf("%s: SF256-PCS-R FM Radio\n", sc->sc_dev.dv_xname); 183 else 184 return TUNER_UNKNOWN; 185 186 fmsradio_set_mute(sc); 187 radio_attach_mi(&fmsradio_hw_if, sc, &sc->sc_dev); 188 return r->type; 189 } 190 191 /* SF256-PCS specific routines */ 192 int 193 sf256pcs_probe(struct fms_softc *sc) 194 { 195 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 196 u_int32_t freq; 197 198 radio->tea.init = sf256pcs_init; 199 radio->tea.rset = sf256pcs_rset; 200 radio->tea.write_bit = sf256pcs_write_bit; 201 radio->tea.read = sf256pcs_hw_read; 202 203 tea5757_set_freq(&radio->tea, radio->stereo, 204 radio->lock, radio->freq); 205 freq = tea5757_decode_freq(sf256pcs_hw_read(radio->tea.iot, 206 radio->tea.ioh, radio->tea.offset), 207 radio->tea.flags & TEA5757_TEA5759); 208 if (freq != radio->freq) 209 return TUNER_UNKNOWN; 210 211 return TUNER_SF256PCS; 212 } 213 214 u_int32_t 215 sf256pcs_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) 216 { 217 u_int32_t res = 0ul; 218 u_int16_t i, d; 219 220 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3) | PCS_WREN_OFF; 221 222 /* Now read data in */ 223 d |= FM_IO_GPIO_IN(PCS_DATA_ON) | PCS_DATA_ON; 224 225 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF); 226 227 /* Read the register */ 228 i = 24; 229 while (i--) { 230 res <<= 1; 231 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_ON); 232 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF); 233 res |= bus_space_read_2(iot, ioh, offset) & 234 PCS_DATA_ON ? 1 : 0; 235 } 236 237 return (res & (TEA5757_DATA | TEA5757_FREQ)); 238 } 239 240 void 241 sf256pcs_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, 242 bus_size_t off, int bit) 243 { 244 u_int16_t data, wren; 245 246 wren = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3); 247 wren |= PCS_WREN_ON; 248 data = bit ? PCPR_DATA_ON : PCS_DATA_OFF; 249 250 bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data); 251 bus_space_write_2(iot, ioh, off, PCS_CLOCK_ON | wren | data); 252 bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data); 253 } 254 255 void 256 sf256pcs_init(bus_space_tag_t iot, bus_space_handle_t ioh, 257 bus_size_t offset, u_int32_t d) 258 { 259 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3); 260 d |= PCS_WREN_ON | PCS_DATA_OFF | PCS_CLOCK_OFF; 261 262 bus_space_write_2(iot, ioh, offset, d); 263 bus_space_write_2(iot, ioh, offset, d); 264 } 265 266 void 267 sf256pcs_rset(bus_space_tag_t iot, bus_space_handle_t ioh, 268 bus_size_t offset, u_int32_t d) 269 { 270 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3); 271 d |= PCS_WREN_OFF | PCS_DATA_OFF | PCS_CLOCK_OFF; 272 273 bus_space_write_2(iot, ioh, offset, d); 274 bus_space_write_2(iot, ioh, offset, d); 275 } 276 277 /* SF256-PCP-R specific routines */ 278 int 279 sf256pcpr_probe(struct fms_softc *sc) 280 { 281 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 282 u_int32_t freq; 283 284 radio->tea.init = sf256pcpr_init; 285 radio->tea.rset = sf256pcpr_rset; 286 radio->tea.write_bit = sf256pcpr_write_bit; 287 radio->tea.read = sf256pcpr_hw_read; 288 289 tea5757_set_freq(&radio->tea, radio->stereo, 290 radio->lock, radio->freq); 291 freq = tea5757_decode_freq(sf256pcpr_hw_read(radio->tea.iot, 292 radio->tea.ioh, radio->tea.offset), 293 radio->tea.flags & TEA5757_TEA5759); 294 if (freq != radio->freq) 295 return TUNER_UNKNOWN; 296 297 return TUNER_SF256PCPR; 298 } 299 300 u_int32_t 301 sf256pcpr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, 302 bus_size_t offset) 303 { 304 u_int32_t res = 0ul; 305 u_int16_t i, d; 306 307 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCPR_DATA_ON | FM_IO_PIN3); 308 309 /* Now read data in */ 310 d |= PCPR_WREN_OFF | PCPR_DATA_ON; 311 312 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF); 313 314 /* Read the register */ 315 i = 24; 316 while (i--) { 317 res <<= 1; 318 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_ON); 319 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF); 320 res |= bus_space_read_2(iot, ioh, offset) & 321 PCPR_DATA_ON ? 1 : 0; 322 } 323 324 return (res & (TEA5757_DATA | TEA5757_FREQ)); 325 } 326 327 void 328 sf256pcpr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, 329 bus_size_t off, int bit) 330 { 331 u_int16_t data, wren; 332 333 wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCPR_WREN_ON; 334 data = bit ? PCPR_DATA_ON : PCPR_DATA_OFF; 335 336 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data); 337 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_ON | wren | data); 338 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data); 339 } 340 341 void 342 sf256pcpr_init(bus_space_tag_t iot, bus_space_handle_t ioh, 343 bus_size_t offset, u_int32_t d) 344 { 345 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3); 346 d |= PCPR_WREN_ON | PCPR_DATA_OFF | PCPR_CLOCK_OFF; 347 348 bus_space_write_2(iot, ioh, offset, d); 349 bus_space_write_2(iot, ioh, offset, d); 350 } 351 352 void 353 sf256pcpr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, 354 bus_size_t offset, u_int32_t d) 355 { 356 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3); 357 d |= PCPR_WREN_OFF | PCPR_DATA_OFF | PCPR_CLOCK_OFF; 358 359 bus_space_write_2(iot, ioh, offset, d); 360 bus_space_write_2(iot, ioh, offset, d); 361 } 362 363 /* SF64-PCR specific routines */ 364 int 365 sf64pcr_probe(struct fms_softc *sc) 366 { 367 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 368 u_int32_t freq; 369 370 radio->tea.init = sf64pcr_init; 371 radio->tea.rset = sf64pcr_rset; 372 radio->tea.write_bit = sf64pcr_write_bit; 373 radio->tea.read = sf64pcr_hw_read; 374 375 tea5757_set_freq(&radio->tea, radio->stereo, 376 radio->lock, radio->freq); 377 freq = tea5757_decode_freq(sf64pcr_hw_read(radio->tea.iot, 378 radio->tea.ioh, radio->tea.offset), 379 radio->tea.flags & TEA5757_TEA5759); 380 if (freq != radio->freq) 381 return TUNER_UNKNOWN; 382 383 return TUNER_SF64PCR; 384 } 385 386 u_int32_t 387 sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) 388 { 389 u_int32_t res = 0ul; 390 u_int16_t d, i, ind = 0; 391 392 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCR_DATA_ON | FM_IO_PIN3); 393 394 /* Now read data in */ 395 d |= PCR_WREN_OFF | PCR_DATA_ON; 396 397 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); 398 DELAY(4); 399 400 /* Read the register */ 401 i = 23; 402 while (i--) { 403 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON); 404 DELAY(4); 405 406 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); 407 DELAY(4); 408 409 res |= bus_space_read_2(iot, ioh, offset) & PCR_DATA_ON ? 1 : 0; 410 res <<= 1; 411 } 412 413 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON); 414 DELAY(4); 415 416 i = bus_space_read_1(iot, ioh, offset); 417 ind = i & PCR_SIGNAL ? (1 << 1) : (0 << 1); /* Tuning */ 418 419 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); 420 421 i = bus_space_read_2(iot, ioh, offset); 422 ind |= i & PCR_STEREO ? (1 << 0) : (0 << 0); /* Mono */ 423 res |= i & PCR_DATA_ON ? (1 << 0) : (0 << 0); 424 425 return (res & (TEA5757_DATA | TEA5757_FREQ)) | (ind << 24); 426 } 427 428 void 429 sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, 430 bus_size_t off, int bit) 431 { 432 u_int16_t data, wren; 433 434 wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCR_WREN_ON; 435 data = bit ? PCR_DATA_ON : PCR_DATA_OFF; 436 437 bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data); 438 DELAY(4); 439 bus_space_write_2(iot, ioh, off, PCR_CLOCK_ON | wren | data); 440 DELAY(4); 441 bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data); 442 DELAY(4); 443 } 444 445 void 446 sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh, 447 bus_size_t offset, u_int32_t d) 448 { 449 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3); 450 d |= PCR_WREN_ON | PCR_DATA_ON | PCR_CLOCK_OFF; 451 452 bus_space_write_2(iot, ioh, offset, d); 453 DELAY(4); 454 } 455 456 void 457 sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, 458 bus_size_t offset, u_int32_t d) 459 { 460 /* Do nothing */ 461 return; 462 } 463 464 465 /* Common tuner routines */ 466 /* 467 * Mute/unmute 468 */ 469 void 470 fmsradio_set_mute(struct fms_softc *sc) 471 { 472 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 473 u_int16_t v, mute, unmute; 474 475 switch (radio->type) { 476 case TUNER_SF256PCS: 477 mute = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3); 478 unmute = mute | PCS_WREN_OFF; 479 break; 480 case TUNER_SF256PCPR: 481 mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3); 482 unmute = mute | PCPR_WREN_OFF; 483 break; 484 case TUNER_SF64PCR: 485 mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3); 486 unmute = mute | PCR_WREN_OFF; 487 break; 488 default: 489 return; 490 } 491 v = (radio->mute || !radio->vol) ? mute : unmute; 492 bus_space_write_2(radio->tea.iot, radio->tea.ioh, 493 radio->tea.offset, v); 494 DELAY(64); 495 bus_space_write_2(radio->tea.iot, radio->tea.ioh, 496 radio->tea.offset, v); 497 } 498 499 int 500 fmsradio_get_info(void *v, struct radio_info *ri) 501 { 502 struct fms_softc *sc = v; 503 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 504 u_int32_t buf; 505 506 ri->mute = radio->mute; 507 ri->volume = radio->vol ? 255 : 0; 508 ri->stereo = radio->stereo == TEA5757_STEREO ? 1 : 0; 509 ri->lock = tea5757_decode_lock(radio->lock); 510 511 switch (radio->type) { 512 case TUNER_SF256PCS: 513 ri->caps = SF256PCS_CAPS; 514 buf = sf256pcs_hw_read(radio->tea.iot, radio->tea.ioh, 515 radio->tea.offset); 516 ri->info = 0; /* UNSUPPORTED */ 517 break; 518 case TUNER_SF256PCPR: 519 ri->caps = SF256PCPR_CAPS; 520 buf = sf256pcpr_hw_read(radio->tea.iot, radio->tea.ioh, 521 radio->tea.offset); 522 ri->info = bus_space_read_2(radio->tea.iot, radio->tea.ioh, 523 FM_VOLUME) == PCPR_INFO_STEREO ? 524 RADIO_INFO_STEREO : 0; 525 break; 526 case TUNER_SF64PCR: 527 ri->caps = SF64PCR_CAPS; 528 buf = sf64pcr_hw_read(radio->tea.iot, radio->tea.ioh, 529 radio->tea.offset); 530 ri->info = buf & PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL; 531 ri->info |= buf & PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO; 532 break; 533 default: 534 return EINVAL; 535 } 536 537 ri->freq = radio->freq = tea5757_decode_freq(buf, 538 sc->sc_dev.dv_cfdata->cf_flags & TEA5757_TEA5759); 539 540 fmsradio_set_mute(sc); 541 542 /* UNSUPPORTED */ 543 ri->rfreq = 0; 544 545 return (0); 546 } 547 548 int 549 fmsradio_set_info(void *v, struct radio_info *ri) 550 { 551 struct fms_softc *sc = v; 552 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 553 554 radio->mute = ri->mute ? 1 : 0; 555 radio->vol = ri->volume ? 255 : 0; 556 radio->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO; 557 radio->lock = tea5757_encode_lock(ri->lock); 558 ri->freq = radio->freq = tea5757_set_freq(&radio->tea, 559 radio->lock, radio->stereo, ri->freq); 560 fmsradio_set_mute(sc); 561 562 return (0); 563 } 564 565 int 566 fmsradio_search(void *v, int f) 567 { 568 struct fms_softc *sc = v; 569 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio; 570 571 tea5757_search(&radio->tea, radio->lock, 572 radio->stereo, f); 573 fmsradio_set_mute(sc); 574 575 return (0); 576 } 577