[BACK]Return to fmsradio.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

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