Annotation of sys/dev/pci/gtp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: gtp.c,v 1.3 2006/04/20 20:30:29 miod 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 AUTHORS ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
! 20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: */
! 27:
! 28: /* Gemtek PCI Radio Card Device Driver */
! 29:
! 30: #include <sys/param.h>
! 31: #include <sys/systm.h>
! 32: #include <sys/device.h>
! 33: #include <sys/errno.h>
! 34: #include <sys/ioctl.h>
! 35: #include <sys/proc.h>
! 36: #include <sys/radioio.h>
! 37:
! 38: #include <machine/bus.h>
! 39:
! 40: #include <dev/pci/pcireg.h>
! 41: #include <dev/pci/pcivar.h>
! 42: #include <dev/pci/pcidevs.h>
! 43:
! 44: #include <dev/ic/tea5757.h>
! 45: #include <dev/radio_if.h>
! 46:
! 47: int gtp_match(struct device *, void *, void *);
! 48: void gtp_attach(struct device *, struct device *, void *);
! 49:
! 50: int gtp_get_info(void *, struct radio_info *);
! 51: int gtp_set_info(void *, struct radio_info *);
! 52: int gtp_search(void *, int);
! 53:
! 54: #define GEMTEK_PCI_CAPS RADIO_CAPS_DETECT_SIGNAL | \
! 55: RADIO_CAPS_DETECT_STEREO | \
! 56: RADIO_CAPS_SET_MONO | \
! 57: RADIO_CAPS_HW_SEARCH | \
! 58: RADIO_CAPS_HW_AFC | \
! 59: RADIO_CAPS_LOCK_SENSITIVITY
! 60:
! 61: #define GEMTEK_PCI_MUTE 0x00
! 62: #define GEMTEK_PCI_RSET 0x10
! 63:
! 64: #define GEMTEK_PCI_SIGNAL 0x08
! 65: #define GEMTEK_PCI_STEREO 0x08
! 66:
! 67: #define GTP_WREN_ON (1 << 2)
! 68: #define GTP_WREN_OFF (0 << 2)
! 69:
! 70: #define GTP_DATA_ON (1 << 1)
! 71: #define GTP_DATA_OFF (0 << 1)
! 72:
! 73: #define GTP_CLCK_ON (1 << 0)
! 74: #define GTP_CLCK_OFF (0 << 0)
! 75:
! 76: #define GTP_READ_CLOCK_LOW (GTP_WREN_OFF | GTP_DATA_ON | GTP_CLCK_OFF)
! 77: #define GTP_READ_CLOCK_HIGH (GTP_WREN_OFF | GTP_DATA_ON | GTP_CLCK_ON)
! 78:
! 79: /* define our interface to the high-level radio driver */
! 80:
! 81: struct radio_hw_if gtp_hw_if = {
! 82: NULL, /* open */
! 83: NULL, /* close */
! 84: gtp_get_info,
! 85: gtp_set_info,
! 86: gtp_search
! 87: };
! 88:
! 89: struct gtp_softc {
! 90: struct device sc_dev;
! 91:
! 92: int mute;
! 93: u_int8_t vol;
! 94: u_int32_t freq;
! 95: u_int32_t stereo;
! 96: u_int32_t lock;
! 97:
! 98: struct tea5757_t tea;
! 99: };
! 100:
! 101: struct cfattach gtp_ca = {
! 102: sizeof(struct gtp_softc), gtp_match, gtp_attach
! 103: };
! 104:
! 105: struct cfdriver gtp_cd = {
! 106: NULL, "gtp", DV_DULL
! 107: };
! 108:
! 109: void gtp_set_mute(struct gtp_softc *);
! 110: void gtp_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
! 111: void gtp_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 112: void gtp_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
! 113: int gtp_state(bus_space_tag_t, bus_space_handle_t);
! 114: u_int32_t gtp_hardware_read(bus_space_tag_t, bus_space_handle_t,
! 115: bus_size_t);
! 116:
! 117: int
! 118: gtp_match(struct device *parent, void *match, void *aux)
! 119: {
! 120: struct pci_attach_args *pa = aux;
! 121: /* FIXME:
! 122: * Guillemot produces the card that
! 123: * was originally developed by Gemtek
! 124: */
! 125: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_GEMTEK &&
! 126: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_GEMTEK_PR103)
! 127: return (1);
! 128: return (0);
! 129: }
! 130:
! 131: void
! 132: gtp_attach(struct device *parent, struct device *self, void *aux)
! 133: {
! 134: struct gtp_softc *sc = (struct gtp_softc *) self;
! 135: struct pci_attach_args *pa = aux;
! 136: struct cfdata *cf = sc->sc_dev.dv_cfdata;
! 137:
! 138: if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->tea.iot,
! 139: &sc->tea.ioh, NULL, NULL, 0)) {
! 140: printf(": can't map i/o space\n");
! 141: return;
! 142: }
! 143:
! 144: sc->vol = 0;
! 145: sc->mute = 0;
! 146: sc->freq = MIN_FM_FREQ;
! 147: sc->stereo = TEA5757_STEREO;
! 148: sc->lock = TEA5757_S030;
! 149: sc->tea.offset = 0;
! 150: sc->tea.flags = cf->cf_flags;
! 151: sc->tea.init = gtp_init;
! 152: sc->tea.rset = gtp_rset;
! 153: sc->tea.write_bit = gtp_write_bit;
! 154: sc->tea.read = gtp_hardware_read;
! 155:
! 156: printf(": Gemtek PR103\n");
! 157:
! 158: radio_attach_mi(>p_hw_if, sc, &sc->sc_dev);
! 159: }
! 160:
! 161: int
! 162: gtp_get_info(void *v, struct radio_info *ri)
! 163: {
! 164: struct gtp_softc *sc = v;
! 165:
! 166: ri->mute = sc->mute;
! 167: ri->volume = sc->vol ? 255 : 0;
! 168: ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
! 169: ri->caps = GEMTEK_PCI_CAPS;
! 170: ri->rfreq = 0;
! 171: ri->lock = tea5757_decode_lock(sc->lock);
! 172:
! 173: /* Frequency read unsupported */
! 174: ri->freq = sc->freq;
! 175:
! 176: ri->info = gtp_state(sc->tea.iot, sc->tea.ioh);
! 177: gtp_set_mute(sc);
! 178:
! 179: return (0);
! 180: }
! 181:
! 182: int
! 183: gtp_set_info(void *v, struct radio_info *ri)
! 184: {
! 185: struct gtp_softc *sc = v;
! 186:
! 187: sc->mute = ri->mute ? 1 : 0;
! 188: sc->vol = ri->volume ? 255 : 0;
! 189: sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
! 190: sc->lock = tea5757_encode_lock(ri->lock);
! 191: ri->freq = sc->freq = tea5757_set_freq(&sc->tea,
! 192: sc->lock, sc->stereo, ri->freq);
! 193: gtp_set_mute(sc);
! 194:
! 195: return (0);
! 196: }
! 197:
! 198: int
! 199: gtp_search(void *v, int f)
! 200: {
! 201: struct gtp_softc *sc = v;
! 202:
! 203: tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
! 204: gtp_set_mute(sc);
! 205:
! 206: return (0);
! 207: }
! 208:
! 209: void
! 210: gtp_set_mute(struct gtp_softc *sc)
! 211: {
! 212: if (sc->mute || !sc->vol)
! 213: bus_space_write_2(sc->tea.iot, sc->tea.ioh, 0, GEMTEK_PCI_MUTE);
! 214: else
! 215: sc->freq = tea5757_set_freq(&sc->tea,
! 216: sc->lock, sc->stereo, sc->freq);
! 217: }
! 218:
! 219: void
! 220: gtp_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
! 221: int bit)
! 222: {
! 223: u_int8_t data;
! 224:
! 225: data = bit ? GTP_DATA_ON : GTP_DATA_OFF;
! 226: bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_OFF | data);
! 227: bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_ON | data);
! 228: bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_OFF | data);
! 229: }
! 230:
! 231: void
! 232: gtp_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
! 233: {
! 234: bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_DATA_ON | GTP_CLCK_OFF);
! 235: }
! 236:
! 237: void
! 238: gtp_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
! 239: {
! 240: bus_space_write_1(iot, ioh, off, GEMTEK_PCI_RSET);
! 241: }
! 242:
! 243: u_int32_t
! 244: gtp_hardware_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
! 245: {
! 246: /* UNSUPPORTED */
! 247: return 0;
! 248: }
! 249:
! 250: int
! 251: gtp_state(bus_space_tag_t iot, bus_space_handle_t ioh)
! 252: {
! 253: int ret;
! 254:
! 255: bus_space_write_2(iot, ioh, 0,
! 256: GTP_DATA_ON | GTP_WREN_OFF | GTP_CLCK_OFF);
! 257: ret = bus_space_read_2(iot, ioh, 0) &
! 258: GEMTEK_PCI_STEREO? 0 : RADIO_INFO_STEREO;
! 259: bus_space_write_2(iot, ioh, 0,
! 260: GTP_DATA_ON | GTP_WREN_OFF | GTP_CLCK_ON);
! 261: ret |= bus_space_read_2(iot, ioh, 0) &
! 262: GEMTEK_PCI_SIGNAL? 0 : RADIO_INFO_SIGNAL;
! 263:
! 264: return ret;
! 265: }
CVSweb