diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-05-06 16:37:44 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-05-06 16:37:44 +0000 |
commit | 727735f9b8695da8e8be8b2b43e15da667ec4b25 (patch) | |
tree | c7adf2628f635115d199b6604d99b83c266c7d41 /sys/dev/pci | |
parent | 1e31d52f75e880b62599cf3c47960019f4bfcc24 (diff) |
tuner driver for the fms cards.
attach radio at the fms(4), instead of a separate device,
which would never work out fine.
from Vladimir Popov <jumbo@narod.ru>
rework the radio config stuff (radio at radiobus, instead of radio at radio),
allowing to tag source files in the files.* files w/ radio attribute.
from mickey@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/files.pci | 14 | ||||
-rw-r--r-- | sys/dev/pci/fms.c | 95 | ||||
-rw-r--r-- | sys/dev/pci/fmsradio.c | 420 | ||||
-rw-r--r-- | sys/dev/pci/fmsradio.h | 59 | ||||
-rw-r--r-- | sys/dev/pci/fmsreg.h | 115 | ||||
-rw-r--r-- | sys/dev/pci/fmsvar.h | 6 | ||||
-rw-r--r-- | sys/dev/pci/sf64pcr.c | 349 |
7 files changed, 635 insertions, 423 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index bdec482014c..c91efd1e8dd 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.132 2002/04/15 06:23:07 deraadt Exp $ +# $OpenBSD: files.pci,v 1.133 2002/05/06 16:37:43 mickey Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -131,9 +131,10 @@ attach opl at yds with opl_yds file dev/pci/opl_yds.c opl_yds # Forte Media FM801 -device fms: audio, auconv, mulaw, ac97, midibus +device fms: audio, auconv, mulaw, ac97, midibus, tea5757, radiobus attach fms at pci file dev/pci/fms.c fms +file dev/pci/fmsradio.c fms & radio # VIA VT82C686A AC'97 Audio device auvia: audio, auconv, mulaw, ac97 @@ -257,7 +258,7 @@ attach sv at pci file dev/pci/sv.c sv # Brooktree Bt848 video capture -device bktr: pcibus, radio +device bktr: pcibus, radiobus attach bktr at pci file dev/pci/bktr/bktr_audio.c bktr needs-count file dev/pci/bktr/bktr_card.c bktr @@ -397,15 +398,10 @@ attach pcscp at pci file dev/pci/pcscp.c pcscp # Guillemot Maxi Radio FM 2000 Radio Card -device mr: radio +device mr: radiobus attach mr at pci file dev/pci/maxiradio.c mr -# MediaForte SoundForte SF64-PCR Radio card -device sf4r: radio, tea5757 -attach sf4r at pci -file dev/pci/sf64pcr.c sf4r - # National Semiconductor DP83820/DP83821 based GigE device nge: ether, ifnet, mii, ifmedia, mii_phy attach nge at pci diff --git a/sys/dev/pci/fms.c b/sys/dev/pci/fms.c index ee56e5227da..ad3af60b850 100644 --- a/sys/dev/pci/fms.c +++ b/sys/dev/pci/fms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fms.c,v 1.8 2002/03/14 03:16:06 millert Exp $ */ +/* $OpenBSD: fms.c,v 1.9 2002/05/06 16:37:43 mickey Exp $ */ /* $NetBSD: fms.c,v 1.5.4.1 2000/06/30 16:27:50 simonb Exp $ */ /*- @@ -41,6 +41,8 @@ * Forte Media FM801 Audio Device Driver */ +#include "radio.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -59,10 +61,16 @@ #include <dev/auconv.h> #include <dev/ic/ac97.h> +#if NRADIO > 0 +#include <sys/radioio.h> +#include <dev/radio_if.h> +#include <dev/pci/fmsradio.h> +#endif /* NRADIO > 0 */ #if 0 #include <dev/ic/mpuvar.h> #endif +#include <dev/pci/fmsreg.h> #include <dev/pci/fmsvar.h> @@ -146,6 +154,17 @@ struct audio_hw_if fms_hw_if = { fms_trigger_input }; +#if NRADIO > 0 +struct radio_hw_if fmsradio_hw_if = { + NULL, /* open */ + NULL, /* close */ + fmsradio_get_info, + fmsradio_set_info, + fmsradio_search +}; +#endif /* NRADIO > 0 */ + + int fms_attach_codec(void *, struct ac97_codec_if *); int fms_read_codec(void *, u_int8_t, u_int16_t *); int fms_write_codec(void *, u_int8_t, u_int16_t); @@ -155,69 +174,6 @@ int fms_allocmem(struct fms_softc *, size_t, size_t, struct fms_dma *); int fms_freemem(struct fms_softc *, struct fms_dma *); -#define FM_PCM_VOLUME 0x00 -#define FM_FM_VOLUME 0x02 -#define FM_I2S_VOLUME 0x04 -#define FM_RECORD_SOURCE 0x06 - -#define FM_PLAY_CTL 0x08 -#define FM_PLAY_RATE_MASK 0x0f00 -#define FM_PLAY_BUF1_LAST 0x0001 -#define FM_PLAY_BUF2_LAST 0x0002 -#define FM_PLAY_START 0x0020 -#define FM_PLAY_PAUSE 0x0040 -#define FM_PLAY_STOPNOW 0x0080 -#define FM_PLAY_16BIT 0x4000 -#define FM_PLAY_STEREO 0x8000 - -#define FM_PLAY_DMALEN 0x0a -#define FM_PLAY_DMABUF1 0x0c -#define FM_PLAY_DMABUF2 0x10 - - -#define FM_REC_CTL 0x14 -#define FM_REC_RATE_MASK 0x0f00 -#define FM_REC_BUF1_LAST 0x0001 -#define FM_REC_BUF2_LAST 0x0002 -#define FM_REC_START 0x0020 -#define FM_REC_PAUSE 0x0040 -#define FM_REC_STOPNOW 0x0080 -#define FM_REC_16BIT 0x4000 -#define FM_REC_STEREO 0x8000 - - -#define FM_REC_DMALEN 0x16 -#define FM_REC_DMABUF1 0x18 -#define FM_REC_DMABUF2 0x1c - -#define FM_CODEC_CTL 0x22 -#define FM_VOLUME 0x26 -#define FM_VOLUME_MUTE 0x8000 - -#define FM_CODEC_CMD 0x2a -#define FM_CODEC_CMD_READ 0x0080 -#define FM_CODEC_CMD_VALID 0x0100 -#define FM_CODEC_CMD_BUSY 0x0200 - -#define FM_CODEC_DATA 0x2c - -#define FM_IO_CTL 0x52 -#define FM_CARD_CTL 0x54 - -#define FM_INTMASK 0x56 -#define FM_INTMASK_PLAY 0x0001 -#define FM_INTMASK_REC 0x0002 -#define FM_INTMASK_VOL 0x0040 -#define FM_INTMASK_MPU 0x0080 - -#define FM_INTSTATUS 0x5a -#define FM_INTSTATUS_PLAY 0x0100 -#define FM_INTSTATUS_REC 0x0200 -#define FM_INTSTATUS_VOL 0x4000 -#define FM_INTSTATUS_MPU 0x8000 - - - int fms_match(parent, match, aux) struct device *parent; @@ -311,6 +267,17 @@ fms_attach(parent, self, aux) bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | FM_INTSTATUS_VOL); + +#if NRADIO > 0 + sc->radio.tea.iot = sc->sc_iot; + sc->radio.tea.ioh = sc->sc_ioh; + sc->radio.tea.offset = FM_IO_CTL; + sc->radio.tea.flags = sc->sc_dev.dv_cfdata->cf_flags; + + fmsradio_attach(&sc->radio, sc->sc_dev.dv_xname); + /* /dev/radio will attach anyway */ + radio_attach_mi(&fmsradio_hw_if, sc, &sc->sc_dev); +#endif /* NRADIO > 0 */ sc->host_if.arg = sc; sc->host_if.attach = fms_attach_codec; diff --git a/sys/dev/pci/fmsradio.c b/sys/dev/pci/fmsradio.c new file mode 100644 index 00000000000..84b433328b4 --- /dev/null +++ b/sys/dev/pci/fmsradio.c @@ -0,0 +1,420 @@ +/* $OpenBSD: fmsradio.c,v 1.1 2002/05/06 16:37:43 mickey Exp $ */ + +/* + * Copyright (c) 2002 Vladimir Popov <jumbo@narod.ru> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Device Driver for FM Tuners attached to FM801 */ + +/* Currently supported tuners: + * o MediaForte SoundForte SF64-PCR PCI Radio Card + * o MediaForte SoundForte SF256-PCP-R PCI Sound Card with FM Radio + */ + +#include "radio.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/audioio.h> +#include <sys/radioio.h> + +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/audio_if.h> +#include <dev/radio_if.h> + +#include <dev/ic/ac97.h> +#include <dev/pci/fmsradio.h> +#include <dev/pci/fmsreg.h> +#include <dev/pci/fmsvar.h> + +#include <dev/ic/tea5757.h> + +#define TUNER_UNKNOWN 0 +#define TUNER_SF256PCPR 1 +#define TUNER_SF64PCR 2 +#define TUNER_NOT_ATTACHED 0xFFFF + +#define SF64PCR_CAPS RADIO_CAPS_DETECT_STEREO | \ + RADIO_CAPS_DETECT_SIGNAL | \ + RADIO_CAPS_SET_MONO | \ + RADIO_CAPS_HW_SEARCH | \ + RADIO_CAPS_HW_AFC | \ + RADIO_CAPS_LOCK_SENSITIVITY + +#define SF256PCPR_CAPS RADIO_CAPS_SET_MONO | \ + RADIO_CAPS_HW_SEARCH | \ + RADIO_CAPS_HW_AFC | \ + RADIO_CAPS_LOCK_SENSITIVITY + +#define PCR_WREN_ON (0 << 1) +#define PCR_WREN_OFF (1 << 1) +#define PCR_CLOCK_ON (1 << 0) +#define PCR_CLOCK_OFF (0 << 0) +#define PCR_DATA_ON (1 << 2) +#define PCR_DATA_OFF (0 << 2) + +#define PCR_SIGNAL 0x80 +#define PCR_STEREO 0x80 +#define PCR_INFO_SIGNAL (1 << 24) +#define PCR_INFO_STEREO (1 << 25) + +#define PCPR_WREN_ON (0 << 2) +#define PCPR_WREN_OFF (1 << 2) +#define PCPR_CLOCK_ON (1 << 0) +#define PCPR_CLOCK_OFF (0 << 0) +#define PCPR_DATA_ON (1 << 1) +#define PCPR_DATA_OFF (0 << 1) + +/* + * Function prototypes + */ +void fmsradio_set_mute(struct fmsradio_if *); + +void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void sf64pcr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); +u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int sf64pcr_probe(struct fmsradio_if *); + +void sf256pcpr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void sf256pcpr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void sf256pcpr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); +u_int32_t sf256pcpr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int sf256pcpr_probe(struct fmsradio_if *); + +int +fmsradio_attach(struct fmsradio_if *sc, char *devname) +{ + sc->vol = 0; + sc->mute = 0; + sc->freq = MIN_FM_FREQ; + sc->stereo = TEA5757_STEREO; + sc->lock = TEA5757_S030; + + sc->card = TUNER_UNKNOWN; + if ((sc->card = sf64pcr_probe(sc)) == TUNER_SF64PCR) + printf("%s: SoundForte SF64-PCR FM Radio\n", devname); + else if ((sc->card = sf256pcpr_probe(sc)) == TUNER_SF256PCPR) + printf("%s: SoundForte SF256-PCP-R FM Radio\n", devname); + else { + sc->card = TUNER_NOT_ATTACHED; + return 0; + } + + fmsradio_set_mute(sc); + + return sc->card; +} + +/* SF256-PCP-R specific routines */ +int +sf256pcpr_probe(struct fmsradio_if *sc) +{ + u_int32_t freq; + + sc->tea.init = sf256pcpr_init; + sc->tea.rset = sf256pcpr_rset; + sc->tea.write_bit = sf256pcpr_write_bit; + sc->tea.read = sf256pcpr_hw_read; + + tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq); + freq = sf256pcpr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); + if (tea5757_decode_freq(freq, sc->tea.flags & TEA5757_TEA5759) + != sc->freq) + return TUNER_UNKNOWN; + + return TUNER_SF256PCPR; +} + +u_int32_t +sf256pcpr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) +{ + u_int32_t res = 0ul; + u_int16_t i, d; + + d = FM_IO_GPIO; + d |= FM_IO_GPIO3_IN | PCPR_WREN_OFF; + + /* Now read data in */ + d |= FM_IO_GPIO1_IN | PCPR_DATA_ON; + + bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF); + + /* Read the register */ + i = 24; + while (i--) { + res <<= 1; + bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_ON); + bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF); + res |= bus_space_read_2(iot, ioh, offset) & PCPR_DATA_ON ? 1 : 0; + } + + return (res & (TEA5757_DATA | TEA5757_FREQ)); +} + +void +sf256pcpr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, + int bit) +{ + u_int16_t data, wren; + + wren = FM_IO_GPIO | FM_IO_GPIO3_IN | PCPR_WREN_ON; + data = bit ? PCPR_DATA_ON : PCPR_DATA_OFF; + + bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data); + bus_space_write_2(iot, ioh, off, PCPR_CLOCK_ON | wren | data); + bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data); +} + +void +sf256pcpr_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset, + u_int32_t d) +{ + d = FM_IO_GPIO | FM_IO_GPIO3_IN; + d |= PCPR_WREN_ON | PCPR_DATA_OFF | PCPR_CLOCK_OFF; + + bus_space_write_2(iot, ioh, offset, d); + bus_space_write_2(iot, ioh, offset, d); +} + +void +sf256pcpr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset, + u_int32_t d) +{ + d = FM_IO_GPIO | FM_IO_GPIO3_IN; + d |= PCPR_WREN_OFF | PCPR_DATA_OFF | PCPR_CLOCK_OFF; + + bus_space_write_2(iot, ioh, offset, d); + bus_space_write_2(iot, ioh, offset, d); +} + +/* SF64-PCR specific routines */ +int +sf64pcr_probe(struct fmsradio_if *sc) +{ + u_int32_t freq; + + sc->tea.init = sf64pcr_init; + sc->tea.rset = sf64pcr_rset; + sc->tea.write_bit = sf64pcr_write_bit; + sc->tea.read = sf64pcr_hw_read; + + tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq); + freq = sf64pcr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); + if (tea5757_decode_freq(freq, sc->tea.flags & TEA5757_TEA5759) + != sc->freq) + return TUNER_UNKNOWN; + + return TUNER_SF64PCR; +} + +u_int32_t +sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) +{ + u_int32_t res = 0ul; + u_int16_t d, i, ind = 0; + + d = FM_IO_GPIO; + d |= FM_IO_GPIO3_IN | PCR_WREN_OFF; + + /* Now read data in */ + d |= FM_IO_GPIO2_IN | PCR_DATA_ON; + + bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); + DELAY(4); + + /* Read the register */ + i = 23; + while (i--) { + bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON); + DELAY(4); + + bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); + DELAY(4); + + res |= bus_space_read_2(iot, ioh, offset) & PCR_DATA_ON ? 1 : 0; + res <<= 1; + } + + bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON); + DELAY(4); + + i = bus_space_read_1(iot, ioh, offset); + ind = i & PCR_SIGNAL ? (1 << 1) : (0 << 1); /* Tuning */ + + bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF); + + i = bus_space_read_2(iot, ioh, offset); + ind |= i & PCR_STEREO ? (1 << 0) : (0 << 0); /* Mono */ + res |= i & PCR_DATA_ON ? (1 << 0) : (0 << 0); + + return (res & (TEA5757_DATA | TEA5757_FREQ)) | (ind << 24); +} + +void +sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, + int bit) +{ + u_int16_t data, wren; + + wren = FM_IO_GPIO | FM_IO_GPIO3_IN | PCR_WREN_ON; + data = bit ? PCR_DATA_ON : PCR_DATA_OFF; + + bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data); + DELAY(4); + bus_space_write_2(iot, ioh, off, PCR_CLOCK_ON | wren | data); + DELAY(4); + bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data); + DELAY(4); +} + +void +sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset, + u_int32_t d) +{ + d = FM_IO_GPIO | FM_IO_GPIO3_IN; + d |= PCR_WREN_ON | PCR_DATA_ON | PCR_CLOCK_OFF; + + bus_space_write_2(iot, ioh, offset, d); + DELAY(4); +} + +void +sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset, + u_int32_t d) +{ + /* Do nothing */ + return; +} + + +/* Common tuner routines */ +/* + * Mute/unmute + */ +void +fmsradio_set_mute(struct fmsradio_if *sc) +{ + u_int16_t v, mute, unmute; + + mute = FM_IO_GPIO | FM_IO_GPIO3_IN; + switch (sc->card) { + case TUNER_SF256PCPR: + unmute = FM_IO_GPIO | FM_IO_GPIO3_IN | FM_IO_GPIO2; + break; + case TUNER_SF64PCR: + unmute = FM_IO_GPIO | FM_IO_GPIO3_IN | FM_IO_GPIO1; + break; + default: + return; + } + v = (sc->mute || !sc->vol) ? mute : unmute; + bus_space_write_2(sc->tea.iot, sc->tea.ioh, sc->tea.offset, v); +} + +int +fmsradio_get_info(void *v, struct radio_info *ri) +{ + struct fms_softc *fms_sc = v; + struct fmsradio_if *sc = &fms_sc->radio; + u_int32_t buf; + + if (sc->card == TUNER_NOT_ATTACHED) + return (ENXIO); + + ri->mute = sc->mute; + ri->volume = sc->vol ? 255 : 0; + ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0; + ri->lock = tea5757_decode_lock(sc->lock); + + switch (sc->card) { + case TUNER_SF256PCPR: + ri->caps = SF256PCPR_CAPS; + buf = sf256pcpr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); + ri->info = 0; /* UNSUPPORTED */ + break; + case TUNER_SF64PCR: + ri->caps = SF64PCR_CAPS; + buf = sf64pcr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); + ri->info = buf & PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL; + ri->info |= buf & PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO; + break; + default: + break; + } + + ri->freq = sc->freq = tea5757_decode_freq(buf, + sc->tea.flags & TEA5757_TEA5759); + + fmsradio_set_mute(sc); + + /* UNSUPPORTED */ + ri->rfreq = 0; + + return (0); +} + +int +fmsradio_set_info(void *v, struct radio_info *ri) +{ + struct fms_softc *fms_sc = v; + struct fmsradio_if *sc = &fms_sc->radio; + + if (sc->card == TUNER_NOT_ATTACHED) + return (ENXIO); + + sc->mute = ri->mute ? 1 : 0; + sc->vol = ri->volume ? 255 : 0; + sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO; + sc->lock = tea5757_encode_lock(ri->lock); + ri->freq = sc->freq = tea5757_set_freq(&sc->tea, + sc->lock, sc->stereo, ri->freq); + fmsradio_set_mute(sc); + + return (0); +} + +int +fmsradio_search(void *v, int f) +{ + struct fms_softc *fms_sc = v; + struct fmsradio_if *sc = &fms_sc->radio; + + if (sc->card == TUNER_NOT_ATTACHED) + return (ENXIO); + + tea5757_search(&sc->tea, sc->lock, sc->stereo, f); + fmsradio_set_mute(sc); + + return (0); +} diff --git a/sys/dev/pci/fmsradio.h b/sys/dev/pci/fmsradio.h new file mode 100644 index 00000000000..dc09c5d976d --- /dev/null +++ b/sys/dev/pci/fmsradio.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fmsradio.h,v 1.1 2002/05/06 16:37:43 mickey Exp $ */ + +/* + * Copyright (c) 2002 Vladimir Popov <jumbo@narod.ru> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Device Driver for FM801-based FM Tuners */ + +/* Currently supported tuners: + * o MediaForte SoundForte SF64-PCR PCI Radio Card + * o MediaForte SoundForte SF256-PCP-R PCI Sound Card with FM tuner + */ + +#ifndef _FMS_RADIO_H_ +#define _FMS_RADIO_H_ + +#include <dev/ic/tea5757.h> + +struct fmsradio_if { + int card; /* Card type */ + + int mute; + u_int8_t vol; + u_int32_t freq; + u_int32_t stereo; + u_int32_t lock; + + struct tea5757_t tea; +}; + +int fmsradio_attach(struct fmsradio_if *, char *); + +int fmsradio_get_info(void *, struct radio_info *); +int fmsradio_set_info(void *, struct radio_info *); +int fmsradio_search(void *, int); + +#endif /* _FMS_RADIO_H_ */ diff --git a/sys/dev/pci/fmsreg.h b/sys/dev/pci/fmsreg.h new file mode 100644 index 00000000000..6e56e6ac247 --- /dev/null +++ b/sys/dev/pci/fmsreg.h @@ -0,0 +1,115 @@ +/* $OpenBSD: fmsreg.h,v 1.1 2002/05/06 16:37:43 mickey Exp $ */ +/* $NetBSD: fms.c,v 1.5.4.1 2000/06/30 16:27:50 simonb Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Witold J. Wnuk. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _DEV_PCI_FMSREG_H_ +#define _DEV_PCI_FMSREG_H_ + +#define FM_PCM_VOLUME 0x00 +#define FM_FM_VOLUME 0x02 +#define FM_I2S_VOLUME 0x04 +#define FM_RECORD_SOURCE 0x06 + +#define FM_PLAY_CTL 0x08 +#define FM_PLAY_RATE_MASK 0x0f00 +#define FM_PLAY_BUF1_LAST 0x0001 +#define FM_PLAY_BUF2_LAST 0x0002 +#define FM_PLAY_START 0x0020 +#define FM_PLAY_PAUSE 0x0040 +#define FM_PLAY_STOPNOW 0x0080 +#define FM_PLAY_16BIT 0x4000 +#define FM_PLAY_STEREO 0x8000 + +#define FM_PLAY_DMALEN 0x0a +#define FM_PLAY_DMABUF1 0x0c +#define FM_PLAY_DMABUF2 0x10 + + +#define FM_REC_CTL 0x14 +#define FM_REC_RATE_MASK 0x0f00 +#define FM_REC_BUF1_LAST 0x0001 +#define FM_REC_BUF2_LAST 0x0002 +#define FM_REC_START 0x0020 +#define FM_REC_PAUSE 0x0040 +#define FM_REC_STOPNOW 0x0080 +#define FM_REC_16BIT 0x4000 +#define FM_REC_STEREO 0x8000 + + +#define FM_REC_DMALEN 0x16 +#define FM_REC_DMABUF1 0x18 +#define FM_REC_DMABUF2 0x1c + +#define FM_CODEC_CTL 0x22 +#define FM_VOLUME 0x26 +#define FM_VOLUME_MUTE 0x8000 + +#define FM_CODEC_CMD 0x2a +#define FM_CODEC_CMD_READ 0x0080 +#define FM_CODEC_CMD_VALID 0x0100 +#define FM_CODEC_CMD_BUSY 0x0200 + +#define FM_CODEC_DATA 0x2c + +#define FM_IO_CTL 0x52 +#define FM_IO_GPIO 0xf000 +#define FM_IO_GPIO0 0x0001 +#define FM_IO_GPIO1 0x0002 +#define FM_IO_GPIO2 0x0004 +#define FM_IO_GPIO3 0x0008 +#define FM_IO_GPIO0_IN 0x0100 /* 1 - input; 0 - output */ +#define FM_IO_GPIO1_IN 0x0200 +#define FM_IO_GPIO2_IN 0x0400 +#define FM_IO_GPIO3_IN 0x0800 + +#define FM_CARD_CTL 0x54 + +#define FM_INTMASK 0x56 +#define FM_INTMASK_PLAY 0x0001 +#define FM_INTMASK_REC 0x0002 +#define FM_INTMASK_VOL 0x0040 +#define FM_INTMASK_MPU 0x0080 + +#define FM_INTSTATUS 0x5a +#define FM_INTSTATUS_PLAY 0x0100 +#define FM_INTSTATUS_REC 0x0200 +#define FM_INTSTATUS_VOL 0x4000 +#define FM_INTSTATUS_MPU 0x8000 + +#endif /* _DEV_PCI_FMSREG_H_ */ diff --git a/sys/dev/pci/fmsvar.h b/sys/dev/pci/fmsvar.h index 355281e4d77..5bdd53c0eeb 100644 --- a/sys/dev/pci/fmsvar.h +++ b/sys/dev/pci/fmsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fmsvar.h,v 1.2 2000/10/14 18:04:07 aaron Exp $ */ +/* $OpenBSD: fmsvar.h,v 1.3 2002/05/06 16:37:43 mickey Exp $ */ /* $NetBSD: fmsvar.h,v 1.1 1999/11/01 21:54:12 augustss Exp $ */ /*- @@ -59,6 +59,10 @@ struct fms_softc { struct ac97_codec_if *codec_if; struct ac97_host_if host_if; +#if NRADIO > 0 + struct fmsradio_if radio; +#endif + struct fms_dma *sc_dmas; void (*sc_pintr)(void *); diff --git a/sys/dev/pci/sf64pcr.c b/sys/dev/pci/sf64pcr.c deleted file mode 100644 index 1f2d841b0f1..00000000000 --- a/sys/dev/pci/sf64pcr.c +++ /dev/null @@ -1,349 +0,0 @@ -/* $OpenBSD: sf64pcr.c,v 1.4 2002/01/07 18:32:19 mickey Exp $ */ -/* $RuOBSD: sf64pcr.c,v 1.11 2001/12/05 10:19:40 mickey Exp $ */ - -/* - * Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* MediaForte SoundForte SF64-PCR PCI Radio Card Device Driver */ - -/* - * Philips TEA5757H AM/FM Self Tuned Radio: - * http://www.semiconductors.philips.com/pip/TEA5757H - * - * ForteMedia FM801: - * ??? - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/radioio.h> - -#include <machine/bus.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> - -#include <dev/radio_if.h> -#include <dev/ic/tea5757.h> - -/* config base I/O address ? */ -#define PCI_CBIO 0x6400 -#define SF64PCR_PCI_OFFSET 0x52 - -#define CARD_RADIO_CAPS RADIO_CAPS_DETECT_STEREO | \ - RADIO_CAPS_DETECT_SIGNAL | \ - RADIO_CAPS_SET_MONO | \ - RADIO_CAPS_HW_SEARCH | \ - RADIO_CAPS_HW_AFC | \ - RADIO_CAPS_LOCK_SENSITIVITY - -#define SF64PCR_MUTE 0xF800 -#define SF64PCR_UNMUTE 0xF802 - -#define SF64PCR_SIGNAL 0x80 -#define SF64PCR_STEREO 0x80 - -#define SF64PCR_INFO_STEREO (1 << 24) -#define SF64PCR_INFO_SIGNAL (1 << 25) - -#define SF64PCR_CLCK_ON (1 << 0) -#define SF64PCR_CLCK_OFF (0 << 0) - -#define SF64PCR_WREN1_ON (0 << 1) -#define SF64PCR_WREN1_OFF (1 << 1) - -#define SF64PCR_DATA_ON (1 << 2) -#define SF64PCR_DATA_OFF (0 << 2) - -#define SF64PCR_WREN2_ON (0 << 10) -#define SF64PCR_WREN2_OFF (1 << 10) - -#define SF64PCR_0xF800 0xF800 - -#define SF64PCR_WRITE_ONE_CLOCK_LOW \ - SF64PCR_0xF800 | \ - SF64PCR_WREN1_ON | \ - SF64PCR_WREN2_ON | \ - SF64PCR_DATA_ON | \ - SF64PCR_CLCK_OFF - -/* 0xFC02 */ -#define SF64PCR_READ_CLOCK_LOW \ - SF64PCR_0xF800 | \ - SF64PCR_CLCK_OFF | \ - SF64PCR_WREN1_OFF | \ - SF64PCR_DATA_OFF | \ - SF64PCR_WREN2_OFF - -/* 0xFC03 */ -#define SF64PCR_READ_CLOCK_HIGH \ - SF64PCR_0xF800 | \ - SF64PCR_CLCK_ON | \ - SF64PCR_WREN1_OFF | \ - SF64PCR_DATA_OFF | \ - SF64PCR_WREN2_OFF - -int sf64pcr_match(struct device *, void *, void *); -void sf64pcr_attach(struct device *, struct device * self, void *); - -int sf64pcr_get_info(void *, struct radio_info *); -int sf64pcr_set_info(void *, struct radio_info *); -int sf64pcr_search(void *, int); - -/* define our interface to the high-level radio driver */ -struct radio_hw_if sf4r_hw_if = { - NULL, /* open */ - NULL, /* close */ - sf64pcr_get_info, - sf64pcr_set_info, - sf64pcr_search -}; - -struct sf64pcr_softc { - struct device dev; - - int mute; - u_int8_t vol; - u_int32_t freq; - u_int32_t stereo; - u_int32_t lock; - - struct tea5757_t tea; -}; - -struct cfattach sf4r_ca = { - sizeof(struct sf64pcr_softc), sf64pcr_match, sf64pcr_attach -}; - -struct cfdriver sf4r_cd = { - NULL, "sf4r", DV_DULL -}; - -/* - * Function prototypes - */ -void sf64pcr_set_mute(struct sf64pcr_softc *); - -void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); -void sf64pcr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); -void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int); -u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t); - -/* - * PCI initialization stuff - */ -int -sf64pcr_match(struct device *parent, void *match, void *aux) -{ - struct pci_attach_args *pa = aux; - /* FIXME: more thorough testing */ - if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_FORTEMEDIA && - PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_FORTEMEDIA_FM801) - return (1); - return (0); -} - -void -sf64pcr_attach(struct device *parent, struct device *self, void *aux) -{ - struct sf64pcr_softc *sc = (struct sf64pcr_softc *) self; - struct pci_attach_args *pa = aux; - struct cfdata *cf = sc->dev.dv_cfdata; - pci_chipset_tag_t pc = pa->pa_pc; - pcireg_t csr; - - if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, - &sc->tea.iot, &sc->tea.ioh, NULL, NULL, 0)) { - printf(": can't map i/o space\n"); - return; - } - - /* Enable the card */ - csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); - pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, - csr | PCI_COMMAND_MASTER_ENABLE); - - sc->vol = 0; - sc->mute = 0; - sc->freq = MIN_FM_FREQ; - sc->stereo = TEA5757_STEREO; - sc->lock = TEA5757_S030; - sc->tea.offset = SF64PCR_PCI_OFFSET; - sc->tea.flags = cf->cf_flags; - sc->tea.init = sf64pcr_init; - sc->tea.rset = sf64pcr_rset; - sc->tea.write_bit = sf64pcr_write_bit; - sc->tea.read = sf64pcr_hw_read; - - printf(": SoundForte RadioLink SF64-PCR PCI\n"); - - tea5757_set_freq(&sc->tea, sc->lock, sc->stereo, sc->freq); - sf64pcr_set_mute(sc); - - radio_attach_mi(&sf4r_hw_if, sc, &sc->dev); -} - -/* - * Mute/unmute - */ -void -sf64pcr_set_mute(struct sf64pcr_softc *sc) -{ - u_int16_t mute; - - mute = (sc->mute || !sc->vol) ? SF64PCR_MUTE : SF64PCR_UNMUTE; - bus_space_write_2(sc->tea.iot, sc->tea.ioh, sc->tea.offset, mute); -} - -void -sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, - bus_size_t off, int bit) -{ - u_int16_t data, wren; - - wren = SF64PCR_0xF800 | SF64PCR_WREN1_ON | SF64PCR_WREN2_ON; - data = bit ? SF64PCR_DATA_ON : SF64PCR_DATA_OFF; - - bus_space_write_2(iot, ioh, off, SF64PCR_CLCK_OFF | wren | data); - DELAY(4); - bus_space_write_2(iot, ioh, off, SF64PCR_CLCK_ON | wren | data); - DELAY(4); - bus_space_write_2(iot, ioh, off, SF64PCR_CLCK_OFF | wren | data); - DELAY(4); -} - -void -sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh, - bus_size_t offset, u_int32_t d) -{ - d = SF64PCR_WRITE_ONE_CLOCK_LOW; - - bus_space_write_2(iot, ioh, offset, d); - DELAY(4); -} - -void -sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, - bus_size_t offset, u_int32_t d) -{ - /* Do nothing */ - return; -} - -/* - * Read TEA5757 shift register - */ -u_int32_t -sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) -{ - u_int32_t res = 0ul; - int rb, ind = 0; - - bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_LOW); - DELAY(4); - - /* Read the register */ - rb = 23; - while (rb--) { - bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_HIGH); - DELAY(4); - - bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_LOW); - DELAY(4); - - res |= bus_space_read_2(iot, ioh, offset) & SF64PCR_DATA_ON ? - 1 : 0; - res <<= 1; - } - - bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_HIGH); - DELAY(4); - - rb = bus_space_read_1(iot, ioh, offset); - ind = rb & SF64PCR_SIGNAL ? (1 << 1) : (0 << 1); /* Tuning */ - - bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_LOW); - - rb = bus_space_read_2(iot, ioh, offset); - ind |= rb & SF64PCR_STEREO ? (1 << 0) : (0 << 0); /* Mono */ - res |= rb & SF64PCR_DATA_ON ? 1 : 0; - - return (res & (TEA5757_DATA | TEA5757_FREQ)) | (ind << 24); -} - -int -sf64pcr_get_info(void *v, struct radio_info *ri) -{ - struct sf64pcr_softc *sc = v; - u_int32_t buf; - - ri->mute = sc->mute; - ri->volume = sc->vol ? 255 : 0; - ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0; - ri->caps = CARD_RADIO_CAPS; - ri->rfreq = 0; - ri->lock = tea5757_decode_lock(sc->lock); - - buf = sf64pcr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); - ri->freq = sc->freq = tea5757_decode_freq(buf, - sc->tea.flags & TEA5757_TEA5759); - ri->info = buf & SF64PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL; - ri->info |= buf & SF64PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO; - - return (0); -} - -int -sf64pcr_set_info(void *v, struct radio_info *ri) -{ - - struct sf64pcr_softc *sc = v; - - sc->mute = ri->mute ? 1 : 0; - sc->vol = ri->volume ? 255 : 0; - sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO; - sc->lock = tea5757_encode_lock(ri->lock); - ri->freq = sc->freq = tea5757_set_freq(&sc->tea, - sc->lock, sc->stereo, ri->freq); - sf64pcr_set_mute(sc); - - return (0); -} - -int -sf64pcr_search(void *v, int f) -{ - struct sf64pcr_softc *sc = v; - - tea5757_search(&sc->tea, sc->lock, sc->stereo, f); - sf64pcr_set_mute(sc); - - return (0); -} |