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

Annotation of sys/dev/isa/radiotrack2.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: radiotrack2.c,v 1.3 2002/01/07 18:32:19 mickey Exp $ */
        !             2: /* $RuOBSD: radiotrack2.c,v 1.2 2001/10/18 16:51:36 pva Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
        !             6:  *                    Vladimir Popov <jumbo@narod.ru>
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
        !            19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            21:  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            27:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /* AIMS Lab Radiotrack II FM Radio Card device driver */
        !            31:
        !            32: /*
        !            33:  * Philips TEA5757H AM/FM Self Tuned Radio:
        !            34:  *     http://www.semiconductors.philips.com/pip/TEA5757H
        !            35:  */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/proc.h>
        !            40: #include <sys/errno.h>
        !            41: #include <sys/ioctl.h>
        !            42: #include <sys/device.h>
        !            43: #include <sys/radioio.h>
        !            44:
        !            45: #include <dev/isa/isavar.h>
        !            46: #include <dev/radio_if.h>
        !            47: #include <dev/ic/tea5757.h>
        !            48:
        !            49: #define RTII_BASE_VALID(x)     ((x == 0x20C) || (x == 0x30C))
        !            50: #define RTII_CAPABILITIES      RADIO_CAPS_DETECT_STEREO |              \
        !            51:                                RADIO_CAPS_DETECT_SIGNAL |              \
        !            52:                                RADIO_CAPS_SET_MONO |                   \
        !            53:                                RADIO_CAPS_LOCK_SENSITIVITY |           \
        !            54:                                RADIO_CAPS_HW_AFC |                     \
        !            55:                                RADIO_CAPS_HW_SEARCH
        !            56:
        !            57: #if 0
        !            58: #define RTII_SIGNAL            (1 << 3)
        !            59: #define RTII_STEREO            (1 << 3)
        !            60: #endif /* 0 */
        !            61:
        !            62: #define RTII_MUTE              0x01
        !            63: #define RTII_UNMUTE            0x00
        !            64:
        !            65: #define RTII_RESET             0xC8
        !            66:
        !            67: #define RTII_DATA_ON           (1 << 2)
        !            68: #define RTII_DATA_OFF          (0 << 2)
        !            69:
        !            70: #define RTII_CLCK_ON           (1 << 1)
        !            71: #define RTII_CLCK_OFF          (0 << 1)
        !            72:
        !            73: #define RTII_WREN_ON           (0 << 0)
        !            74: #define RTII_WREN_OFF          (1 << 0)
        !            75:
        !            76: #define RTII_READ_CLOCK_LOW    (RTII_DATA_ON | RTII_CLCK_OFF | RTII_WREN_OFF)
        !            77: #define RTII_READ_CLOCK_HIGH   (RTII_DATA_ON | RTII_CLCK_ON | RTII_WREN_OFF)
        !            78:
        !            79: int    rtii_probe(struct device *, void *, void *);
        !            80: void   rtii_attach(struct device *, struct device * self, void *);
        !            81:
        !            82: int    rtii_get_info(void *, struct radio_info *);
        !            83: int    rtii_set_info(void *, struct radio_info *);
        !            84: int    rtii_search(void *, int);
        !            85:
        !            86: /* define our interface to the higher level radio driver */
        !            87: struct radio_hw_if rtii_hw_if = {
        !            88:        NULL,   /* open */
        !            89:        NULL,   /* close */
        !            90:        rtii_get_info,
        !            91:        rtii_set_info,
        !            92:        rtii_search
        !            93: };
        !            94:
        !            95: struct rtii_softc {
        !            96:        struct device   dev;
        !            97:
        !            98:        u_int32_t       freq;
        !            99:        u_int32_t       stereo;
        !           100:        u_int32_t       lock;
        !           101:        u_int8_t        vol;
        !           102:        int     mute;
        !           103:
        !           104:        struct tea5757_t        tea;
        !           105: };
        !           106:
        !           107: struct cfattach rtii_ca = {
        !           108:        sizeof(struct rtii_softc), rtii_probe, rtii_attach
        !           109: };
        !           110:
        !           111: struct cfdriver rtii_cd = {
        !           112:        NULL, "rtii", DV_DULL
        !           113: };
        !           114:
        !           115: void   rtii_set_mute(struct rtii_softc *);
        !           116: int    rtii_find(bus_space_tag_t, bus_space_handle_t, int);
        !           117:
        !           118: u_int32_t      rtii_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
        !           119:
        !           120: void   rtii_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
        !           121: void   rtii_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
        !           122: void   rtii_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
        !           123:
        !           124: int
        !           125: rtii_probe(struct device *parent, void *match, void *aux)
        !           126: {
        !           127:        struct isa_attach_args *ia = aux;
        !           128:        bus_space_tag_t iot = ia->ia_iot;
        !           129:        bus_space_handle_t ioh;
        !           130:        struct cfdata *cf = match;
        !           131:        int iosize = 1, iobase = ia->ia_iobase;
        !           132:
        !           133:        if (!RTII_BASE_VALID(iobase)) {
        !           134:                printf("rtii: configured iobase 0x%x invalid\n", iobase);
        !           135:                return (0);
        !           136:        }
        !           137:
        !           138:        if (bus_space_map(iot, iobase, iosize, 0, &ioh))
        !           139:                return (0);
        !           140:
        !           141:        if (!rtii_find(iot, ioh, cf->cf_flags)) {
        !           142:                bus_space_unmap(iot, ioh, iosize);
        !           143:                return (0);
        !           144:        }
        !           145:
        !           146:        bus_space_unmap(iot, ioh, iosize);
        !           147:        ia->ia_iosize = iosize;
        !           148:        return (1);
        !           149: }
        !           150:
        !           151: void
        !           152: rtii_attach(struct device *parent, struct device *self, void *aux)
        !           153: {
        !           154:        struct rtii_softc *sc = (void *) self;
        !           155:        struct isa_attach_args *ia = aux;
        !           156:        struct cfdata *cf = sc->dev.dv_cfdata;
        !           157:
        !           158:        sc->tea.iot = ia->ia_iot;
        !           159:        sc->mute = 0;
        !           160:        sc->vol = 0;
        !           161:        sc->freq = MIN_FM_FREQ;
        !           162:        sc->stereo = TEA5757_STEREO;
        !           163:        sc->lock = TEA5757_S030;
        !           164:
        !           165:        /* remap I/O */
        !           166:        if (bus_space_map(sc->tea.iot, ia->ia_iobase, ia->ia_iosize,
        !           167:                          0, &sc->tea.ioh)) {
        !           168:                printf(": bus_space_map() failed\n");
        !           169:                return;
        !           170:        }
        !           171:
        !           172:        sc->tea.offset = 0;
        !           173:        sc->tea.flags = cf->cf_flags;
        !           174:
        !           175:        sc->tea.init = rtii_init;
        !           176:        sc->tea.rset = rtii_rset;
        !           177:        sc->tea.write_bit = rtii_write_bit;
        !           178:        sc->tea.read = rtii_hw_read;
        !           179:
        !           180:        printf(": AIMS Lab Radiotrack II\n");
        !           181:        tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq);
        !           182:        rtii_set_mute(sc);
        !           183:
        !           184:        radio_attach_mi(&rtii_hw_if, sc, &sc->dev);
        !           185: }
        !           186:
        !           187: /*
        !           188:  * Mute/unmute the card
        !           189:  */
        !           190: void
        !           191: rtii_set_mute(struct rtii_softc *sc)
        !           192: {
        !           193:        u_int8_t mute;
        !           194:
        !           195:        mute = (sc->mute || !sc->vol) ? RTII_MUTE : RTII_UNMUTE;
        !           196:        bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
        !           197:        DELAY(6);
        !           198:        bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
        !           199: }
        !           200:
        !           201: void
        !           202: rtii_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
        !           203: {
        !           204:        bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
        !           205:        bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
        !           206:        bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
        !           207: }
        !           208:
        !           209: void
        !           210: rtii_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
        !           211: {
        !           212:        bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
        !           213: }
        !           214:
        !           215: int
        !           216: rtii_find(bus_space_tag_t iot, bus_space_handle_t ioh, int flags)
        !           217: {
        !           218:        struct rtii_softc sc;
        !           219:        u_int32_t freq;
        !           220:
        !           221:        sc.tea.iot = iot;
        !           222:        sc.tea.ioh = ioh;
        !           223:        sc.tea.offset = 0;
        !           224:        sc.tea.flags = flags;
        !           225:        sc.tea.init = rtii_init;
        !           226:        sc.tea.rset = rtii_rset;
        !           227:        sc.tea.write_bit = rtii_write_bit;
        !           228:        sc.tea.read = rtii_hw_read;
        !           229:        sc.lock = TEA5757_S030;
        !           230:        sc.stereo = TEA5757_STEREO;
        !           231:
        !           232:        /*
        !           233:         * Let's try to write and read a frequency.
        !           234:         * If the written and read frequencies are
        !           235:         * the same then success.
        !           236:         */
        !           237:        sc.freq = MIN_FM_FREQ;
        !           238:        tea5757_set_freq(&sc.tea, sc.stereo, sc.lock, sc.freq);
        !           239:        rtii_set_mute(&sc);
        !           240:        freq = rtii_hw_read(iot, ioh, sc.tea.offset);
        !           241:        if (tea5757_decode_freq(freq, sc.tea.flags & TEA5757_TEA5759)
        !           242:                        == sc.freq)
        !           243:                return 1;
        !           244:
        !           245:        return 0;
        !           246: }
        !           247:
        !           248: void
        !           249: rtii_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, int bit)
        !           250: {
        !           251:        u_int8_t data;
        !           252:
        !           253:        data = bit ? RTII_DATA_ON : RTII_DATA_OFF;
        !           254:
        !           255:        bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
        !           256:        bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_ON  | data);
        !           257:        bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
        !           258: }
        !           259:
        !           260: u_int32_t
        !           261: rtii_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
        !           262: {
        !           263:        u_int8_t i;
        !           264:        u_int32_t res = 0;
        !           265:
        !           266:        bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
        !           267:        DELAY(6);
        !           268:
        !           269:        i = 24;
        !           270:        while ( i-- ) {
        !           271:                bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_HIGH);
        !           272:                DELAY(6);
        !           273:                bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
        !           274:                res |= bus_space_read_1(iot, ioh, off) & RTII_DATA_ON ? 1 : 0;
        !           275:                DELAY(6);
        !           276:                res <<= 1;
        !           277:        }
        !           278:
        !           279:        return (res & (TEA5757_DATA | TEA5757_FREQ)) >> 1;
        !           280: }
        !           281:
        !           282: int
        !           283: rtii_get_info(void *v, struct radio_info *ri)
        !           284: {
        !           285:        struct rtii_softc *sc = v;
        !           286:
        !           287:        ri->mute = sc->mute;
        !           288:        ri->volume = sc->vol ? 255 : 0;
        !           289:        ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
        !           290:        ri->caps = RTII_CAPABILITIES;
        !           291:        ri->rfreq = 0;
        !           292:        ri->lock = tea5757_decode_lock(sc->lock);
        !           293:
        !           294:        ri->freq  = sc->freq = tea5757_decode_freq(rtii_hw_read(sc->tea.iot,
        !           295:            sc->tea.ioh, sc->tea.offset), sc->tea.flags & TEA5757_TEA5759);
        !           296:
        !           297:        switch (bus_space_read_1(sc->tea.iot, sc->tea.ioh, 0)) {
        !           298:        case 0xFD:
        !           299:                ri->info = RADIO_INFO_SIGNAL | RADIO_INFO_STEREO;
        !           300:                break;
        !           301:        case 0xFF:
        !           302:                ri->info = 0;
        !           303:                break;
        !           304:        default:
        !           305:                ri->info = RADIO_INFO_SIGNAL;
        !           306:        }
        !           307:
        !           308:        return (0);
        !           309: }
        !           310:
        !           311: int
        !           312: rtii_set_info(void *v, struct radio_info *ri)
        !           313: {
        !           314:        struct rtii_softc *sc = v;
        !           315:
        !           316:        sc->mute = ri->mute ? 1 : 0;
        !           317:        sc->vol = ri->volume ? 255 : 0;
        !           318:        sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
        !           319:        sc->lock = tea5757_encode_lock(ri->lock);
        !           320:        ri->freq = sc->freq = tea5757_set_freq(&sc->tea,
        !           321:                        sc->lock, sc->stereo, ri->freq);
        !           322:        rtii_set_mute(sc);
        !           323:
        !           324:        return (0);
        !           325: }
        !           326:
        !           327: int
        !           328: rtii_search(void *v, int f)
        !           329: {
        !           330:        struct rtii_softc *sc = v;
        !           331:
        !           332:        tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
        !           333:        rtii_set_mute(sc);
        !           334:
        !           335:        return (0);
        !           336: }

CVSweb