Annotation of sys/dev/pci/fmsradio.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: fmsradio.c,v 1.6 2002/06/06 16:29:37 mickey 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/ioctl.h>
! 43: #include <sys/audioio.h>
! 44: #include <sys/radioio.h>
! 45:
! 46: #include <machine/bus.h>
! 47:
! 48: #include <dev/pci/pcireg.h>
! 49: #include <dev/pci/pcivar.h>
! 50: #include <dev/pci/pcidevs.h>
! 51:
! 52: #include <dev/audio_if.h>
! 53: #include <dev/radio_if.h>
! 54:
! 55: #include <dev/ic/ac97.h>
! 56:
! 57: #include <dev/pci/fmsreg.h>
! 58: #include <dev/pci/fmsvar.h>
! 59:
! 60: #include <dev/ic/tea5757.h>
! 61:
! 62: #define TUNER_UNKNOWN 0
! 63: #define TUNER_SF256PCPR 1
! 64: #define TUNER_SF64PCR 2
! 65: #define TUNER_SF256PCS 3
! 66:
! 67: #define SF64PCR_CAPS RADIO_CAPS_DETECT_STEREO | \
! 68: RADIO_CAPS_DETECT_SIGNAL | \
! 69: RADIO_CAPS_SET_MONO | \
! 70: RADIO_CAPS_HW_SEARCH | \
! 71: RADIO_CAPS_HW_AFC | \
! 72: RADIO_CAPS_LOCK_SENSITIVITY
! 73:
! 74: #define SF256PCPR_CAPS RADIO_CAPS_DETECT_STEREO | \
! 75: RADIO_CAPS_SET_MONO | \
! 76: RADIO_CAPS_HW_SEARCH | \
! 77: RADIO_CAPS_HW_AFC | \
! 78: RADIO_CAPS_LOCK_SENSITIVITY
! 79:
! 80: #define SF256PCS_CAPS RADIO_CAPS_SET_MONO | \
! 81: RADIO_CAPS_HW_SEARCH | \
! 82: RADIO_CAPS_HW_AFC | \
! 83: RADIO_CAPS_LOCK_SENSITIVITY
! 84:
! 85: #define PCR_WREN_ON 0
! 86: #define PCR_WREN_OFF FM_IO_PIN1
! 87: #define PCR_CLOCK_ON FM_IO_PIN0
! 88: #define PCR_CLOCK_OFF 0
! 89: #define PCR_DATA_ON FM_IO_PIN2
! 90: #define PCR_DATA_OFF 0
! 91:
! 92: #define PCR_SIGNAL 0x80
! 93: #define PCR_STEREO 0x80
! 94: #define PCR_INFO_SIGNAL (1 << 24)
! 95: #define PCR_INFO_STEREO (1 << 25)
! 96:
! 97: #define PCPR_WREN_ON 0
! 98: #define PCPR_WREN_OFF FM_IO_PIN2
! 99: #define PCPR_CLOCK_ON FM_IO_PIN0
! 100: #define PCPR_CLOCK_OFF 0
! 101: #define PCPR_DATA_ON FM_IO_PIN1
! 102: #define PCPR_DATA_OFF 0
! 103: #define PCPR_INFO_STEREO 0x04
! 104:
! 105: #define PCS_WREN_ON 0
! 106: #define PCS_WREN_OFF FM_IO_PIN2
! 107: #define PCS_CLOCK_ON FM_IO_PIN3
! 108: #define PCS_CLOCK_OFF 0
! 109: #define PCS_DATA_ON FM_IO_PIN1
! 110: #define PCS_DATA_OFF 0
! 111:
! 112: /*
! 113: * Function prototypes
! 114: */
! 115: void fmsradio_set_mute(struct fms_softc *);
! 116:
! 117: void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 118: void sf64pcr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 119: void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
! 120: u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
! 121: int sf64pcr_probe(struct fms_softc *);
! 122:
! 123: void sf256pcpr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 124: void sf256pcpr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 125: void sf256pcpr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
! 126: u_int32_t sf256pcpr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
! 127: int sf256pcpr_probe(struct fms_softc *);
! 128:
! 129: void sf256pcs_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 130: void sf256pcs_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 131: void sf256pcs_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
! 132: u_int32_t sf256pcs_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
! 133: int sf256pcs_probe(struct fms_softc *);
! 134:
! 135: int fmsradio_get_info(void *, struct radio_info *);
! 136: int fmsradio_set_info(void *, struct radio_info *);
! 137: int fmsradio_search(void *, int);
! 138:
! 139: struct radio_hw_if fmsradio_hw_if = {
! 140: NULL, /* open */
! 141: NULL, /* close */
! 142: fmsradio_get_info,
! 143: fmsradio_set_info,
! 144: fmsradio_search
! 145: };
! 146:
! 147: struct fmsradio_if {
! 148: int type; /* Card type */
! 149:
! 150: int mute;
! 151: u_int8_t vol;
! 152: u_int32_t freq;
! 153: u_int32_t stereo;
! 154: u_int32_t lock;
! 155:
! 156: struct tea5757_t tea;
! 157: };
! 158:
! 159: int
! 160: fmsradio_attach(struct fms_softc *sc)
! 161: {
! 162: struct fmsradio_if *r;
! 163:
! 164: r = malloc(sizeof(struct fmsradio_if), M_DEVBUF, M_NOWAIT);
! 165: if (r == NULL) {
! 166: printf("%s: cannot allocate memory for FM tuner config\n",
! 167: sc->sc_dev.dv_xname);
! 168: return TUNER_UNKNOWN;
! 169: }
! 170:
! 171: sc->radio = r;
! 172: r->tea.iot = sc->sc_iot;
! 173: r->tea.ioh = sc->sc_ioh;
! 174: r->tea.offset = FM_IO_CTL;
! 175: r->tea.flags = sc->sc_dev.dv_cfdata->cf_flags;
! 176: r->vol = 0;
! 177: r->mute = 0;
! 178: r->freq = MIN_FM_FREQ;
! 179: r->stereo = TEA5757_STEREO;
! 180: r->lock = TEA5757_S030;
! 181:
! 182: r->type = TUNER_UNKNOWN;
! 183: if ((r->type = sf64pcr_probe(sc)) == TUNER_SF64PCR)
! 184: printf("%s: SF64-PCR FM Radio\n", sc->sc_dev.dv_xname);
! 185: else if ((r->type = sf256pcpr_probe(sc)) == TUNER_SF256PCPR)
! 186: printf("%s: SF256-PCP-R FM Radio\n", sc->sc_dev.dv_xname);
! 187: else if ((r->type = sf256pcs_probe(sc)) == TUNER_SF256PCS)
! 188: printf("%s: SF256-PCS-R FM Radio\n", sc->sc_dev.dv_xname);
! 189: else
! 190: return TUNER_UNKNOWN;
! 191:
! 192: fmsradio_set_mute(sc);
! 193: radio_attach_mi(&fmsradio_hw_if, sc, &sc->sc_dev);
! 194: return r->type;
! 195: }
! 196:
! 197: /* SF256-PCS specific routines */
! 198: int
! 199: sf256pcs_probe(struct fms_softc *sc)
! 200: {
! 201: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 202: u_int32_t freq;
! 203:
! 204: radio->tea.init = sf256pcs_init;
! 205: radio->tea.rset = sf256pcs_rset;
! 206: radio->tea.write_bit = sf256pcs_write_bit;
! 207: radio->tea.read = sf256pcs_hw_read;
! 208:
! 209: tea5757_set_freq(&radio->tea, radio->stereo,
! 210: radio->lock, radio->freq);
! 211: freq = tea5757_decode_freq(sf256pcs_hw_read(radio->tea.iot,
! 212: radio->tea.ioh, radio->tea.offset),
! 213: radio->tea.flags & TEA5757_TEA5759);
! 214: if (freq != radio->freq)
! 215: return TUNER_UNKNOWN;
! 216:
! 217: return TUNER_SF256PCS;
! 218: }
! 219:
! 220: u_int32_t
! 221: sf256pcs_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
! 222: {
! 223: u_int32_t res = 0ul;
! 224: u_int16_t i, d;
! 225:
! 226: d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3) | PCS_WREN_OFF;
! 227:
! 228: /* Now read data in */
! 229: d |= FM_IO_GPIO_IN(PCS_DATA_ON) | PCS_DATA_ON;
! 230:
! 231: bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF);
! 232:
! 233: /* Read the register */
! 234: i = 24;
! 235: while (i--) {
! 236: res <<= 1;
! 237: bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_ON);
! 238: bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF);
! 239: res |= bus_space_read_2(iot, ioh, offset) &
! 240: PCS_DATA_ON ? 1 : 0;
! 241: }
! 242:
! 243: return (res & (TEA5757_DATA | TEA5757_FREQ));
! 244: }
! 245:
! 246: void
! 247: sf256pcs_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
! 248: bus_size_t off, int bit)
! 249: {
! 250: u_int16_t data, wren;
! 251:
! 252: wren = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
! 253: wren |= PCS_WREN_ON;
! 254: data = bit ? PCPR_DATA_ON : PCS_DATA_OFF;
! 255:
! 256: bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data);
! 257: bus_space_write_2(iot, ioh, off, PCS_CLOCK_ON | wren | data);
! 258: bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data);
! 259: }
! 260:
! 261: void
! 262: sf256pcs_init(bus_space_tag_t iot, bus_space_handle_t ioh,
! 263: bus_size_t offset, u_int32_t d)
! 264: {
! 265: d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
! 266: d |= PCS_WREN_ON | PCS_DATA_OFF | PCS_CLOCK_OFF;
! 267:
! 268: bus_space_write_2(iot, ioh, offset, d);
! 269: bus_space_write_2(iot, ioh, offset, d);
! 270: }
! 271:
! 272: void
! 273: sf256pcs_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
! 274: bus_size_t offset, u_int32_t d)
! 275: {
! 276: d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
! 277: d |= PCS_WREN_OFF | PCS_DATA_OFF | PCS_CLOCK_OFF;
! 278:
! 279: bus_space_write_2(iot, ioh, offset, d);
! 280: bus_space_write_2(iot, ioh, offset, d);
! 281: }
! 282:
! 283: /* SF256-PCP-R specific routines */
! 284: int
! 285: sf256pcpr_probe(struct fms_softc *sc)
! 286: {
! 287: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 288: u_int32_t freq;
! 289:
! 290: radio->tea.init = sf256pcpr_init;
! 291: radio->tea.rset = sf256pcpr_rset;
! 292: radio->tea.write_bit = sf256pcpr_write_bit;
! 293: radio->tea.read = sf256pcpr_hw_read;
! 294:
! 295: tea5757_set_freq(&radio->tea, radio->stereo,
! 296: radio->lock, radio->freq);
! 297: freq = tea5757_decode_freq(sf256pcpr_hw_read(radio->tea.iot,
! 298: radio->tea.ioh, radio->tea.offset),
! 299: radio->tea.flags & TEA5757_TEA5759);
! 300: if (freq != radio->freq)
! 301: return TUNER_UNKNOWN;
! 302:
! 303: return TUNER_SF256PCPR;
! 304: }
! 305:
! 306: u_int32_t
! 307: sf256pcpr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh,
! 308: bus_size_t offset)
! 309: {
! 310: u_int32_t res = 0ul;
! 311: u_int16_t i, d;
! 312:
! 313: d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCPR_DATA_ON | FM_IO_PIN3);
! 314:
! 315: /* Now read data in */
! 316: d |= PCPR_WREN_OFF | PCPR_DATA_ON;
! 317:
! 318: bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF);
! 319:
! 320: /* Read the register */
! 321: i = 24;
! 322: while (i--) {
! 323: res <<= 1;
! 324: bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_ON);
! 325: bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF);
! 326: res |= bus_space_read_2(iot, ioh, offset) &
! 327: PCPR_DATA_ON ? 1 : 0;
! 328: }
! 329:
! 330: return (res & (TEA5757_DATA | TEA5757_FREQ));
! 331: }
! 332:
! 333: void
! 334: sf256pcpr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
! 335: bus_size_t off, int bit)
! 336: {
! 337: u_int16_t data, wren;
! 338:
! 339: wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCPR_WREN_ON;
! 340: data = bit ? PCPR_DATA_ON : PCPR_DATA_OFF;
! 341:
! 342: bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data);
! 343: bus_space_write_2(iot, ioh, off, PCPR_CLOCK_ON | wren | data);
! 344: bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data);
! 345: }
! 346:
! 347: void
! 348: sf256pcpr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
! 349: bus_size_t offset, u_int32_t d)
! 350: {
! 351: d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
! 352: d |= PCPR_WREN_ON | PCPR_DATA_OFF | PCPR_CLOCK_OFF;
! 353:
! 354: bus_space_write_2(iot, ioh, offset, d);
! 355: bus_space_write_2(iot, ioh, offset, d);
! 356: }
! 357:
! 358: void
! 359: sf256pcpr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
! 360: bus_size_t offset, u_int32_t d)
! 361: {
! 362: d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
! 363: d |= PCPR_WREN_OFF | PCPR_DATA_OFF | PCPR_CLOCK_OFF;
! 364:
! 365: bus_space_write_2(iot, ioh, offset, d);
! 366: bus_space_write_2(iot, ioh, offset, d);
! 367: }
! 368:
! 369: /* SF64-PCR specific routines */
! 370: int
! 371: sf64pcr_probe(struct fms_softc *sc)
! 372: {
! 373: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 374: u_int32_t freq;
! 375:
! 376: radio->tea.init = sf64pcr_init;
! 377: radio->tea.rset = sf64pcr_rset;
! 378: radio->tea.write_bit = sf64pcr_write_bit;
! 379: radio->tea.read = sf64pcr_hw_read;
! 380:
! 381: tea5757_set_freq(&radio->tea, radio->stereo,
! 382: radio->lock, radio->freq);
! 383: freq = tea5757_decode_freq(sf64pcr_hw_read(radio->tea.iot,
! 384: radio->tea.ioh, radio->tea.offset),
! 385: radio->tea.flags & TEA5757_TEA5759);
! 386: if (freq != radio->freq)
! 387: return TUNER_UNKNOWN;
! 388:
! 389: return TUNER_SF64PCR;
! 390: }
! 391:
! 392: u_int32_t
! 393: sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
! 394: {
! 395: u_int32_t res = 0ul;
! 396: u_int16_t d, i, ind = 0;
! 397:
! 398: d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCR_DATA_ON | FM_IO_PIN3);
! 399:
! 400: /* Now read data in */
! 401: d |= PCR_WREN_OFF | PCR_DATA_ON;
! 402:
! 403: bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
! 404: DELAY(4);
! 405:
! 406: /* Read the register */
! 407: i = 23;
! 408: while (i--) {
! 409: bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON);
! 410: DELAY(4);
! 411:
! 412: bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
! 413: DELAY(4);
! 414:
! 415: res |= bus_space_read_2(iot, ioh, offset) & PCR_DATA_ON ? 1 : 0;
! 416: res <<= 1;
! 417: }
! 418:
! 419: bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON);
! 420: DELAY(4);
! 421:
! 422: i = bus_space_read_1(iot, ioh, offset);
! 423: ind = i & PCR_SIGNAL ? (1 << 1) : (0 << 1); /* Tuning */
! 424:
! 425: bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
! 426:
! 427: i = bus_space_read_2(iot, ioh, offset);
! 428: ind |= i & PCR_STEREO ? (1 << 0) : (0 << 0); /* Mono */
! 429: res |= i & PCR_DATA_ON ? (1 << 0) : (0 << 0);
! 430:
! 431: return (res & (TEA5757_DATA | TEA5757_FREQ)) | (ind << 24);
! 432: }
! 433:
! 434: void
! 435: sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
! 436: bus_size_t off, int bit)
! 437: {
! 438: u_int16_t data, wren;
! 439:
! 440: wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCR_WREN_ON;
! 441: data = bit ? PCR_DATA_ON : PCR_DATA_OFF;
! 442:
! 443: bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data);
! 444: DELAY(4);
! 445: bus_space_write_2(iot, ioh, off, PCR_CLOCK_ON | wren | data);
! 446: DELAY(4);
! 447: bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data);
! 448: DELAY(4);
! 449: }
! 450:
! 451: void
! 452: sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
! 453: bus_size_t offset, u_int32_t d)
! 454: {
! 455: d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
! 456: d |= PCR_WREN_ON | PCR_DATA_ON | PCR_CLOCK_OFF;
! 457:
! 458: bus_space_write_2(iot, ioh, offset, d);
! 459: DELAY(4);
! 460: }
! 461:
! 462: void
! 463: sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
! 464: bus_size_t offset, u_int32_t d)
! 465: {
! 466: /* Do nothing */
! 467: return;
! 468: }
! 469:
! 470:
! 471: /* Common tuner routines */
! 472: /*
! 473: * Mute/unmute
! 474: */
! 475: void
! 476: fmsradio_set_mute(struct fms_softc *sc)
! 477: {
! 478: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 479: u_int16_t v, mute, unmute;
! 480:
! 481: switch (radio->type) {
! 482: case TUNER_SF256PCS:
! 483: mute = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
! 484: unmute = mute | PCS_WREN_OFF;
! 485: break;
! 486: case TUNER_SF256PCPR:
! 487: mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
! 488: unmute = mute | PCPR_WREN_OFF;
! 489: break;
! 490: case TUNER_SF64PCR:
! 491: mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
! 492: unmute = mute | PCR_WREN_OFF;
! 493: break;
! 494: default:
! 495: return;
! 496: }
! 497: v = (radio->mute || !radio->vol) ? mute : unmute;
! 498: bus_space_write_2(radio->tea.iot, radio->tea.ioh,
! 499: radio->tea.offset, v);
! 500: DELAY(64);
! 501: bus_space_write_2(radio->tea.iot, radio->tea.ioh,
! 502: radio->tea.offset, v);
! 503: }
! 504:
! 505: int
! 506: fmsradio_get_info(void *v, struct radio_info *ri)
! 507: {
! 508: struct fms_softc *sc = v;
! 509: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 510: u_int32_t buf;
! 511:
! 512: ri->mute = radio->mute;
! 513: ri->volume = radio->vol ? 255 : 0;
! 514: ri->stereo = radio->stereo == TEA5757_STEREO ? 1 : 0;
! 515: ri->lock = tea5757_decode_lock(radio->lock);
! 516:
! 517: switch (radio->type) {
! 518: case TUNER_SF256PCS:
! 519: ri->caps = SF256PCS_CAPS;
! 520: buf = sf256pcs_hw_read(radio->tea.iot, radio->tea.ioh,
! 521: radio->tea.offset);
! 522: ri->info = 0; /* UNSUPPORTED */
! 523: break;
! 524: case TUNER_SF256PCPR:
! 525: ri->caps = SF256PCPR_CAPS;
! 526: buf = sf256pcpr_hw_read(radio->tea.iot, radio->tea.ioh,
! 527: radio->tea.offset);
! 528: ri->info = bus_space_read_2(radio->tea.iot, radio->tea.ioh,
! 529: FM_VOLUME) == PCPR_INFO_STEREO ?
! 530: RADIO_INFO_STEREO : 0;
! 531: break;
! 532: case TUNER_SF64PCR:
! 533: ri->caps = SF64PCR_CAPS;
! 534: buf = sf64pcr_hw_read(radio->tea.iot, radio->tea.ioh,
! 535: radio->tea.offset);
! 536: ri->info = buf & PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL;
! 537: ri->info |= buf & PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO;
! 538: break;
! 539: default:
! 540: break;
! 541: }
! 542:
! 543: ri->freq = radio->freq = tea5757_decode_freq(buf,
! 544: sc->sc_dev.dv_cfdata->cf_flags & TEA5757_TEA5759);
! 545:
! 546: fmsradio_set_mute(sc);
! 547:
! 548: /* UNSUPPORTED */
! 549: ri->rfreq = 0;
! 550:
! 551: return (0);
! 552: }
! 553:
! 554: int
! 555: fmsradio_set_info(void *v, struct radio_info *ri)
! 556: {
! 557: struct fms_softc *sc = v;
! 558: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 559:
! 560: radio->mute = ri->mute ? 1 : 0;
! 561: radio->vol = ri->volume ? 255 : 0;
! 562: radio->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
! 563: radio->lock = tea5757_encode_lock(ri->lock);
! 564: ri->freq = radio->freq = tea5757_set_freq(&radio->tea,
! 565: radio->lock, radio->stereo, ri->freq);
! 566: fmsradio_set_mute(sc);
! 567:
! 568: return (0);
! 569: }
! 570:
! 571: int
! 572: fmsradio_search(void *v, int f)
! 573: {
! 574: struct fms_softc *sc = v;
! 575: struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
! 576:
! 577: tea5757_search(&radio->tea, radio->lock,
! 578: radio->stereo, f);
! 579: fmsradio_set_mute(sc);
! 580:
! 581: return (0);
! 582: }
CVSweb