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

Annotation of sys/dev/isa/radiotrack.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: radiotrack.c,v 1.4 2002/08/28 21:20:48 mickey Exp $ */
                      2: /* $RuOBSD: radiotrack.c,v 1.3 2001/10/18 16:51:36 pva Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 2001, 2002 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 FM Radio Card device driver */
                     31:
                     32: /*
                     33:  * Sanyo LM7000 Direct PLL Frequency Synthesizer
                     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/ioctl.h>
                     39: #include <sys/device.h>
                     40: #include <sys/radioio.h>
                     41:
                     42: #include <machine/bus.h>
                     43:
                     44: #include <dev/ic/lm700x.h>
                     45: #include <dev/isa/isavar.h>
                     46: #include <dev/isa/rtreg.h>
                     47: #include <dev/isa/rtvar.h>
                     48: #include <dev/radio_if.h>
                     49:
                     50: void   rtattach(struct rt_softc *);
                     51: int    rt_get_info(void *, struct radio_info *);
                     52: int    rt_set_info(void *, struct radio_info *);
                     53:
                     54: struct radio_hw_if rt_hw_if = {
                     55:        NULL,   /* open */
                     56:        NULL,   /* close */
                     57:        rt_get_info,
                     58:        rt_set_info,
                     59:        NULL
                     60: };
                     61:
                     62: struct cfdriver rt_cd = {
                     63:        NULL, "rt", DV_DULL
                     64: };
                     65:
                     66: void   rt_set_mute(struct rt_softc *, int);
                     67: void   rt_set_freq(struct rt_softc *, u_int32_t);
                     68: u_int8_t       rt_state(bus_space_tag_t, bus_space_handle_t);
                     69:
                     70: void   sfi_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
                     71: void   rt_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
                     72: void   rt_lm700x_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
                     73:
                     74: u_int8_t       rt_conv_vol(u_int8_t);
                     75: u_int8_t       rt_unconv_vol(u_int8_t);
                     76:
                     77: void
                     78: rtattach(struct rt_softc *sc) {
                     79:        sc->sc_freq = MIN_FM_FREQ;
                     80:        sc->sc_mute = 0;
                     81:        sc->sc_vol = 0;
                     82:        sc->sc_rf = LM700X_REF_050;
                     83:        sc->sc_stereo = LM700X_STEREO;
                     84:
                     85:        sc->lm.wzcl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_OFF;
                     86:        sc->lm.wzch = RT_WREN_ON | RT_CLCK_ON  | RT_DATA_OFF;
                     87:        sc->lm.wocl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_ON;
                     88:        sc->lm.woch = RT_WREN_ON | RT_CLCK_ON  | RT_DATA_ON;
                     89:
                     90:        switch (sc->sc_ct) {
                     91:        case CARD_RADIOTRACK:
                     92:                sc->lm.initdata = 0;
                     93:                sc->lm.rsetdata = RT_SIGNAL_METER;
                     94:                sc->lm.init = rt_lm700x_init;
                     95:                sc->lm.rset = rt_lm700x_rset;
                     96:                break;
                     97:        case CARD_SF16FMI:
                     98:                sc->lm.initdata = RT_CARD_OFF;
                     99:                sc->lm.rsetdata = RT_CARD_ON;
                    100:                sc->lm.init = sfi_lm700x_init;
                    101:                sc->lm.rset = sfi_lm700x_init;
                    102:                break;
                    103:        }
                    104:
                    105:        rt_set_freq(sc, sc->sc_freq);
                    106:        rt_set_mute(sc, sc->sc_vol);
                    107:
                    108:        radio_attach_mi(&rt_hw_if, sc, &sc->sc_dev);
                    109: }
                    110:
                    111: int
                    112: rt_set_info(void *v, struct radio_info *ri)
                    113: {
                    114:        struct rt_softc *sc = v;
                    115:
                    116:        sc->sc_mute = ri->mute ? 1 : 0;
                    117:        sc->sc_rf = lm700x_encode_ref(ri->rfreq);
                    118:
                    119:        switch (sc->sc_ct) {
                    120:        case CARD_RADIOTRACK:
                    121:                sc->sc_vol = rt_conv_vol(ri->volume);
                    122:                break;
                    123:        case CARD_SF16FMI:
                    124:                sc->sc_vol = ri->volume ? 1 : 0;
                    125:                break;
                    126:        }
                    127:        /*
                    128:         * Though SF16-FMI does not set stereo/mono
                    129:         * it won't hurt to have this
                    130:         */
                    131:        sc->sc_stereo = ri->stereo ? LM700X_STEREO : LM700X_MONO;
                    132:
                    133:        rt_set_freq(sc, ri->freq);
                    134:        rt_set_mute(sc, sc->sc_vol);
                    135:
                    136:        return (0);
                    137: }
                    138:
                    139: int
                    140: rt_get_info(void *v, struct radio_info *ri)
                    141: {
                    142:        struct rt_softc *sc = v;
                    143:
                    144:        switch (sc->sc_ct) {
                    145:        case CARD_RADIOTRACK:
                    146:                ri->caps = RTRACK_CAPABILITIES;
                    147:                ri->info = 3 & rt_state(sc->lm.iot, sc->lm.ioh);
                    148:                ri->volume = rt_unconv_vol(sc->sc_vol);
                    149:                break;
                    150:        case CARD_SF16FMI:
                    151:                ri->caps = SF16FMI_CAPABILITIES;
                    152:                ri->volume = sc->sc_vol ? 255 : 0;
                    153:                ri->info = 0; /* UNSUPPORTED */
                    154:                break;
                    155:        default:
                    156:                /* No such card */
                    157:                return (1);
                    158:        }
                    159:
                    160:        ri->mute = sc->sc_mute;
                    161:        ri->stereo = sc->sc_stereo == LM700X_STEREO ? 0 : 1;
                    162:        ri->rfreq = lm700x_decode_ref(sc->sc_rf);
                    163:        ri->freq = sc->sc_freq;
                    164:
                    165:        /* UNSUPPORTED */
                    166:        ri->lock = 0;
                    167:
                    168:        return (0);
                    169: }
                    170:
                    171: /*
                    172:  * Mute the card
                    173:  */
                    174: void
                    175: rt_set_mute(struct rt_softc *sc, int vol)
                    176: {
                    177:        int val;
                    178:
                    179:        if (sc->sc_ct == CARD_UNKNOWN)
                    180:                return;
                    181:
                    182:        if (sc->sc_ct == CARD_SF16FMI) {
                    183:                val = vol ? RT_CARD_ON : RT_CARD_OFF;
                    184:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    185:                                sc->sc_mute ? RT_CARD_OFF : val);
                    186:                return;
                    187:        }
                    188:
                    189:        /* CARD_RADIOTRACK */
                    190:        if (sc->sc_mute) {
                    191:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    192:                                RT_VOLUME_DOWN | RT_CARD_ON);
                    193:                DELAY(MAX_VOL * RT_VOLUME_DELAY);
                    194:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    195:                                RT_VOLUME_STEADY | RT_CARD_ON);
                    196:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, RT_CARD_OFF);
                    197:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, RT_CARD_OFF);
                    198:        } else {
                    199:                val = sc->sc_vol - vol;
                    200:                if (val < 0) {
                    201:                        val *= -1;
                    202:                        bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    203:                                        RT_VOLUME_DOWN | RT_CARD_ON);
                    204:                } else {
                    205:                        bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    206:                                        RT_VOLUME_UP | RT_CARD_ON);
                    207:                }
                    208:                DELAY(val * RT_VOLUME_DELAY);
                    209:                bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
                    210:                                RT_VOLUME_STEADY | RT_CARD_ON);
                    211:        }
                    212: }
                    213:
                    214: void
                    215: rt_set_freq(struct rt_softc *sc, u_int32_t nfreq)
                    216: {
                    217:        u_int32_t reg;
                    218:
                    219:        if (nfreq > MAX_FM_FREQ)
                    220:                nfreq = MAX_FM_FREQ;
                    221:        if (nfreq < MIN_FM_FREQ)
                    222:                nfreq = MIN_FM_FREQ;
                    223:
                    224:        sc->sc_freq = nfreq;
                    225:
                    226:        reg = lm700x_encode_freq(nfreq, sc->sc_rf);
                    227:        reg |= sc->sc_stereo | sc->sc_rf | LM700X_DIVIDER_FM;
                    228:
                    229:        lm700x_hardware_write(&sc->lm, reg, RT_VOLUME_STEADY);
                    230:
                    231:        rt_set_mute(sc, sc->sc_vol);
                    232: }
                    233:
                    234: /*
                    235:  * Return state of the card - tuned/not tuned, mono/stereo
                    236:  */
                    237: u_int8_t
                    238: rt_state(bus_space_tag_t iot, bus_space_handle_t ioh)
                    239: {
                    240:        u_int8_t ret;
                    241:
                    242:        bus_space_write_1(iot, ioh, 0,
                    243:                        RT_VOLUME_STEADY | RT_SIGNAL_METER | RT_CARD_ON);
                    244:        DELAY(RT_SIGNAL_METER_DELAY);
                    245:        ret = bus_space_read_1(iot, ioh, 0);
                    246:
                    247:        switch (ret) {
                    248:        case 0xFD:
                    249:                ret = RADIO_INFO_SIGNAL | RADIO_INFO_STEREO;
                    250:                break;
                    251:        case 0xFF:
                    252:                ret = 0;
                    253:                break;
                    254:        default:
                    255:                ret = RADIO_INFO_SIGNAL;
                    256:                break;
                    257:        }
                    258:
                    259:        return ret;
                    260: }
                    261:
                    262: /*
                    263:  * Convert volume to hardware representation.
                    264:  */
                    265: u_int8_t
                    266: rt_conv_vol(u_int8_t vol)
                    267: {
                    268:        if (vol < VOLUME_RATIO(1))
                    269:                return 0;
                    270:        else if (vol >= VOLUME_RATIO(1) && vol < VOLUME_RATIO(2))
                    271:                return 1;
                    272:        else if (vol >= VOLUME_RATIO(2) && vol < VOLUME_RATIO(3))
                    273:                return 2;
                    274:        else if (vol >= VOLUME_RATIO(3) && vol < VOLUME_RATIO(4))
                    275:                return 3;
                    276:        else
                    277:                return 4;
                    278: }
                    279:
                    280: /*
                    281:  * Convert volume from hardware representation
                    282:  */
                    283: u_int8_t
                    284: rt_unconv_vol(u_int8_t vol)
                    285: {
                    286:        return VOLUME_RATIO(vol);
                    287: }
                    288:
                    289: void
                    290: sfi_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
                    291:                u_int32_t data)
                    292: {
                    293:        bus_space_write_1(iot, ioh, off, data);
                    294: }
                    295:
                    296: void
                    297: rt_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
                    298:                u_int32_t data)
                    299: {
                    300:        /* Do nothing */
                    301:        return;
                    302: }
                    303:
                    304: void
                    305: rt_lm700x_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
                    306:                u_int32_t data)
                    307: {
                    308:        DELAY(1000);
                    309:        bus_space_write_1(iot, ioh, off, RT_CARD_OFF | data);
                    310:        DELAY(50000);
                    311:        bus_space_write_1(iot, ioh, off, RT_VOLUME_STEADY | RT_CARD_ON | data);
                    312: }

CVSweb