[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     ! 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