[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

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