1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

update for radio drivers from tm@oganer.net und jumbo@narod.ru

This commit is contained in:
mickey 2001-12-05 10:27:05 +00:00
parent 4d13926c39
commit 0984a33e87
10 changed files with 1223 additions and 467 deletions

View File

@ -1,5 +1,5 @@
/* $OpenBSD: aztech.c,v 1.1 2001/10/04 20:15:42 gluk Exp $ */ /* $OpenBSD: aztech.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: aztech.c,v 1.8 2001/10/04 18:51:50 pva Exp $ */ /* $RuOBSD: aztech.c,v 1.11 2001/10/20 13:23:47 pva Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>, * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
@ -75,24 +75,27 @@
int az_probe(struct device *, void *, void *); int az_probe(struct device *, void *, void *);
void az_attach(struct device *, struct device * self, void *); void az_attach(struct device *, struct device * self, void *);
int az_open(dev_t, int, int, struct proc *);
int az_close(dev_t, int, int, struct proc *); int az_get_info(void *, struct radio_info *);
int az_ioctl(dev_t, u_long, caddr_t, int, struct proc *); int az_set_info(void *, struct radio_info *);
struct radio_hw_if az_hw_if = { struct radio_hw_if az_hw_if = {
az_open, NULL, /* open */
az_close, NULL, /* close */
az_ioctl az_get_info,
az_set_info,
NULL
}; };
struct az_softc { struct az_softc {
struct device sc_dev; struct device sc_dev;
u_long sc_freq; int mute;
u_long sc_rf; u_int8_t vol;
u_char sc_vol; u_int32_t freq;
u_char sc_muted; u_int32_t rf;
u_long sc_stereo; u_int32_t stereo;
struct lm700x_t lm; struct lm700x_t lm;
}; };
@ -106,14 +109,14 @@ struct cfdriver az_cd = {
u_int az_find(bus_space_tag_t, bus_space_handle_t); u_int az_find(bus_space_tag_t, bus_space_handle_t);
void az_set_mute(struct az_softc *); void az_set_mute(struct az_softc *);
void az_set_freq(struct az_softc *, u_long); void az_set_freq(struct az_softc *, u_int32_t);
u_char az_state(bus_space_tag_t, bus_space_handle_t); u_int8_t az_state(bus_space_tag_t, bus_space_handle_t);
void az_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_long); void az_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void az_lm700x_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_long); void az_lm700x_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
u_char az_conv_vol(u_char); u_int8_t az_conv_vol(u_int8_t);
u_char az_unconv_vol(u_char); u_int8_t az_unconv_vol(u_int8_t);
int int
az_probe(struct device *parent, void *self, void *aux) az_probe(struct device *parent, void *self, void *aux)
@ -148,23 +151,11 @@ az_attach(struct device *parent, struct device *self, void *aux)
struct isa_attach_args *ia = aux; struct isa_attach_args *ia = aux;
sc->lm.iot = ia->ia_iot; sc->lm.iot = ia->ia_iot;
sc->sc_rf = LM700X_REF_050; sc->rf = LM700X_REF_050;
sc->sc_stereo = LM700X_STEREO; sc->stereo = LM700X_STEREO;
#ifdef RADIO_INIT_MUTE sc->mute = 0;
sc->sc_muted = RADIO_INIT_MUTE; sc->freq = MIN_FM_FREQ;
#else sc->vol = 0;
sc->sc_muted = 0;
#endif /* RADIO_INIT_MUTE */
#ifdef RADIO_INIT_FREQ
sc->sc_freq = RADIO_INIT_FREQ;
#else
sc->sc_freq = MIN_FM_FREQ;
#endif /* RADIO_INIT_FREQ */
#ifdef RADIO_INIT_VOL
sc->sc_vol = az_conv_vol(RADIO_INIT_VOL);
#else
sc->sc_vol = 0;
#endif /* RADIO_INIT_VOL */
/* remap I/O */ /* remap I/O */
if (bus_space_map(sc->lm.iot, ia->ia_iobase, ia->ia_iosize, if (bus_space_map(sc->lm.iot, ia->ia_iobase, ia->ia_iosize,
@ -184,90 +175,11 @@ az_attach(struct device *parent, struct device *self, void *aux)
sc->lm.init = az_lm700x_init; sc->lm.init = az_lm700x_init;
sc->lm.rset = az_lm700x_rset; sc->lm.rset = az_lm700x_rset;
az_set_freq(sc, sc->sc_freq); az_set_freq(sc, sc->freq);
radio_attach_mi(&az_hw_if, sc, &sc->sc_dev); radio_attach_mi(&az_hw_if, sc, &sc->sc_dev);
} }
int
az_open(dev_t dev, int flags, int fmt, struct proc *p)
{
struct az_softc *sc;
return !(sc = az_cd.cd_devs[0]) ? ENXIO : 0;
}
int
az_close(dev_t dev, int flags, int fmt, struct proc *p)
{
return 0;
}
/*
* Handle the ioctl for the device
*/
int
az_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
int error;
struct az_softc *sc = az_cd.cd_devs[0];
error = 0;
switch (cmd) {
case RIOCGMUTE:
*(u_long *)data = sc->sc_muted ? 1 : 0;
break;
case RIOCSMUTE:
sc->sc_muted = *(u_long *)data ? 1 : 0;
az_set_mute(sc);
break;
case RIOCGVOLU:
*(u_long *)data = az_unconv_vol(sc->sc_vol);
break;
case RIOCSVOLU:
sc->sc_vol = az_conv_vol(*(u_int *)data);
az_set_mute(sc);
break;
case RIOCGMONO:
*(u_long *)data = sc->sc_stereo == LM700X_STEREO ? 0 : 1;
break;
case RIOCSMONO:
sc->sc_stereo = *(u_long *)data ? LM700X_MONO : LM700X_STEREO;
az_set_freq(sc, sc->sc_freq);
break;
case RIOCGFREQ:
*(u_long *)data = sc->sc_freq;
break;
case RIOCSFREQ:
az_set_freq(sc, *(u_long *)data);
break;
case RIOCGCAPS:
*(u_long *)data = AZTECH_CAPABILITIES;
break;
case RIOCGINFO: /* Get Info */
*(u_long *)data = 0x03 &
(3 ^ az_state(sc->lm.iot, sc->lm.ioh));
break;
case RIOCSREFF:
sc->sc_rf = lm700x_encode_ref(*(u_char *)data);
az_set_freq(sc, sc->sc_freq);
break;
case RIOCGREFF:
*(u_long *)data = lm700x_decode_ref(sc->sc_rf);
break;
case RIOCSSRCH:
/* FALLTHROUGH */
case RIOCSLOCK:
/* FALLTHROUGH */
case RIOCGLOCK:
/* NOT SUPPORTED */
error = ENODEV;
break;
default:
error = EINVAL;
}
return (error);
}
/* /*
* Mute the card * Mute the card
*/ */
@ -275,29 +187,29 @@ void
az_set_mute(struct az_softc *sc) az_set_mute(struct az_softc *sc)
{ {
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
sc->sc_muted ? 0 : sc->sc_vol); sc->mute ? 0 : sc->vol);
DELAY(6); DELAY(6);
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
sc->sc_muted ? 0 : sc->sc_vol); sc->mute ? 0 : sc->vol);
} }
void void
az_set_freq(struct az_softc *sc, u_long nfreq) az_set_freq(struct az_softc *sc, u_int32_t nfreq)
{ {
u_char vol; u_int8_t vol;
u_long reg; u_int32_t reg;
vol = sc->sc_muted ? 0 : sc->sc_vol; vol = sc->mute ? 0 : sc->vol;
if (nfreq > MAX_FM_FREQ) if (nfreq > MAX_FM_FREQ)
nfreq = MAX_FM_FREQ; nfreq = MAX_FM_FREQ;
if (nfreq < MIN_FM_FREQ) if (nfreq < MIN_FM_FREQ)
nfreq = MIN_FM_FREQ; nfreq = MIN_FM_FREQ;
sc->sc_freq = nfreq; sc->freq = nfreq;
reg = lm700x_encode_freq(nfreq, sc->sc_rf); reg = lm700x_encode_freq(nfreq, sc->rf);
reg |= sc->sc_stereo | sc->sc_rf | LM700X_DIVIDER_FM; reg |= sc->stereo | sc->rf | LM700X_DIVIDER_FM;
lm700x_hardware_write(&sc->lm, reg, vol); lm700x_hardware_write(&sc->lm, reg, vol);
@ -307,18 +219,18 @@ az_set_freq(struct az_softc *sc, u_long nfreq)
/* /*
* Return state of the card - tuned/not tuned, mono/stereo * Return state of the card - tuned/not tuned, mono/stereo
*/ */
u_char u_int8_t
az_state(bus_space_tag_t iot, bus_space_handle_t ioh) az_state(bus_space_tag_t iot, bus_space_handle_t ioh)
{ {
return bus_space_read_1(iot, ioh, 0) & 3; return (3 ^ bus_space_read_1(iot, ioh, 0)) & 3;
} }
/* /*
* Convert volume to hardware representation. * Convert volume to hardware representation.
* The card uses bits 00000x0x to set volume. * The card uses bits 00000x0x to set volume.
*/ */
u_char u_int8_t
az_conv_vol(u_char vol) az_conv_vol(u_int8_t vol)
{ {
if (vol < VOLUME_RATIO(1)) if (vol < VOLUME_RATIO(1))
return 0; return 0;
@ -333,8 +245,8 @@ az_conv_vol(u_char vol)
/* /*
* Convert volume from hardware representation * Convert volume from hardware representation
*/ */
u_char u_int8_t
az_unconv_vol(u_char vol) az_unconv_vol(u_int8_t vol)
{ {
switch (vol) { switch (vol) {
case 0: case 0:
@ -364,10 +276,10 @@ az_find(bus_space_tag_t iot, bus_space_handle_t ioh)
sc.lm.rsetdata = AZ_DATA_ON | AZ_CLCK_ON | AZ_WREN_OFF; sc.lm.rsetdata = AZ_DATA_ON | AZ_CLCK_ON | AZ_WREN_OFF;
sc.lm.init = az_lm700x_init; sc.lm.init = az_lm700x_init;
sc.lm.rset = az_lm700x_rset; sc.lm.rset = az_lm700x_rset;
sc.sc_rf = LM700X_REF_050; sc.rf = LM700X_REF_050;
sc.sc_muted = 0; sc.mute = 0;
sc.sc_stereo = LM700X_STEREO; sc.stereo = LM700X_STEREO;
sc.sc_vol = 0; sc.vol = 0;
/* /*
* Scan whole FM range. If there is a card it'll * Scan whole FM range. If there is a card it'll
@ -383,7 +295,7 @@ az_find(bus_space_tag_t iot, bus_space_handle_t ioh)
void void
az_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, az_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
u_long data) u_int32_t data)
{ {
/* Do nothing */ /* Do nothing */
return; return;
@ -391,7 +303,42 @@ az_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
void void
az_lm700x_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, az_lm700x_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
u_long data) u_int32_t data)
{ {
bus_space_write_1(iot, ioh, off, data); bus_space_write_1(iot, ioh, off, data);
} }
int
az_get_info(void *v, struct radio_info *ri)
{
struct az_softc *sc = v;
ri->mute = sc->mute;
ri->volume = az_unconv_vol(sc->vol);
ri->stereo = sc->stereo == LM700X_STEREO ? 1 : 0;
ri->caps = AZTECH_CAPABILITIES;
ri->rfreq = lm700x_decode_ref(sc->rf);
ri->info = az_state(sc->lm.iot, sc->lm.ioh);
ri->freq = sc->freq;
/* UNSUPPORTED */
ri->lock = 0;
return (0);
}
int
az_set_info(void *v, struct radio_info *ri)
{
struct az_softc *sc = v;
sc->mute = ri->mute ? 1 : 0;
sc->vol = az_conv_vol(ri->volume);
sc->stereo = ri->stereo ? LM700X_STEREO : LM700X_MONO;
sc->rf = lm700x_encode_ref(ri->rfreq);
az_set_freq(sc, ri->freq);
az_set_mute(sc);
return (0);
}

410
sys/dev/isa/radiotrack.c Normal file
View File

@ -0,0 +1,410 @@
/* $OpenBSD: radiotrack.c,v 1.1 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: radiotrack.c,v 1.3 2001/10/18 16:51:36 pva Exp $ */
/*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
* 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 AUTHORS ``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 AUTHORS 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.
*/
/* AIMS Lab Radiotrack FM Radio Card device driver */
/*
* Sanyo LM7000 Direct PLL Frequency Synthesizer
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/device.h>
#include <sys/radioio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/ic/lm700x.h>
#include <dev/radio_if.h>
#define RF_25K 25
#define RF_50K 50
#define RF_100K 100
#define MAX_VOL 5 /* XXX Find real value */
#define VOLUME_RATIO(x) (255 * x / MAX_VOL)
#define RT_BASE_VALID(x) \
((x == 0x30C) || (x == 0x20C) || (x == 0x284) || (x == 0x384))
#define CARD_RADIOTRACK 0x01
#define CARD_SF16FMI 0x02
#define CARD_UNKNOWN 0xFF
#define RTRACK_CAPABILITIES RADIO_CAPS_DETECT_STEREO | \
RADIO_CAPS_DETECT_SIGNAL | \
RADIO_CAPS_SET_MONO | \
RADIO_CAPS_REFERENCE_FREQ
#define RT_WREN_ON (1 << 0)
#define RT_WREN_OFF (0 << 0)
#define RT_CLCK_ON (1 << 1)
#define RT_CLCK_OFF (0 << 1)
#define RT_DATA_ON (1 << 2)
#define RT_DATA_OFF (0 << 2)
#define RT_CARD_ON (1 << 3)
#define RT_CARD_OFF (0 << 3)
#define RT_SIGNAL_METER (1 << 4)
#define RT_SIGNAL_METER_DELAY 150000
#define RT_VOLUME_DOWN (1 << 6)
#define RT_VOLUME_UP (2 << 6)
#define RT_VOLUME_STEADY (3 << 6)
#define RT_VOLUME_DELAY 100000
int rt_probe(struct device *, void *, void *);
void rt_attach(struct device *, struct device * self, void *);
int rt_get_info(void *, struct radio_info *);
int rt_set_info(void *, struct radio_info *);
struct radio_hw_if rt_hw_if = {
NULL, /* open */
NULL, /* close */
rt_get_info,
rt_set_info,
NULL
};
struct rt_softc {
struct device sc_dev;
int mute;
u_int8_t vol;
u_int8_t cardtype;
u_int32_t freq;
u_int32_t rf;
u_int32_t stereo;
struct lm700x_t lm;
};
struct cfattach rt_ca = {
sizeof(struct rt_softc), rt_probe, rt_attach
};
struct cfdriver rt_cd = {
NULL, "rt", DV_DULL
};
int rt_find(bus_space_tag_t, bus_space_handle_t);
void rt_set_mute(struct rt_softc *, int);
void rt_set_freq(struct rt_softc *, u_int32_t);
u_int8_t rt_state(bus_space_tag_t, bus_space_handle_t);
void rt_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void rt_lm700x_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
u_int8_t rt_conv_vol(u_int8_t);
u_int8_t rt_unconv_vol(u_int8_t);
int
rt_probe(struct device *parent, void *self, void *aux)
{
struct isa_attach_args *ia = aux;
bus_space_tag_t iot = ia->ia_iot;
bus_space_handle_t ioh;
int iosize = 1, iobase = ia->ia_iobase;
if (!RT_BASE_VALID(iobase)) {
printf("rt: configured iobase 0x%x invalid", iobase);
return 0;
}
if (bus_space_map(iot, iobase, iosize, 0, &ioh))
return 0;
bus_space_unmap(iot, ioh, iosize);
if (!rt_find(iot, ioh))
return 0;
ia->ia_iosize = iosize;
return 1;
}
void
rt_attach(struct device *parent, struct device *self, void *aux)
{
struct rt_softc *sc = (void *) self;
struct isa_attach_args *ia = aux;
sc->lm.iot = ia->ia_iot;
sc->rf = LM700X_REF_050;
sc->stereo = LM700X_STEREO;
sc->mute = 0;
sc->freq = MIN_FM_FREQ;
sc->vol = 0;
/* remap I/O */
if (bus_space_map(sc->lm.iot, ia->ia_iobase, ia->ia_iosize,
0, &sc->lm.ioh))
panic(": bus_space_map() of %s failed", sc->sc_dev.dv_xname);
switch (sc->lm.iot) {
case 0x20C:
/* FALLTHROUGH */
case 0x30C:
sc->cardtype = CARD_RADIOTRACK;
printf(": AIMS Lab Radiotrack or compatible");
break;
case 0x284:
/* FALLTHROUGH */
case 0x384:
sc->cardtype = CARD_SF16FMI;
printf(": SoundForte RadioX SF16-FMI");
break;
default:
sc->cardtype = CARD_UNKNOWN;
printf(": Unknown card");
break;
}
/* Configure struct lm700x_t lm */
sc->lm.offset = 0;
sc->lm.wzcl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_OFF;
sc->lm.wzch = RT_WREN_ON | RT_CLCK_ON | RT_DATA_OFF;
sc->lm.wocl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_ON;
sc->lm.woch = RT_WREN_ON | RT_CLCK_ON | RT_DATA_ON;
sc->lm.initdata = 0;
sc->lm.rsetdata = RT_DATA_ON | RT_CLCK_ON | RT_WREN_OFF;
sc->lm.init = rt_lm700x_init;
sc->lm.rset = rt_lm700x_rset;
rt_set_freq(sc, sc->freq);
radio_attach_mi(&rt_hw_if, sc, &sc->sc_dev);
}
/*
* Mute the card
*/
void
rt_set_mute(struct rt_softc *sc, int vol)
{
int val;
if (sc->mute) {
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
RT_VOLUME_DOWN | RT_CARD_ON);
DELAY(MAX_VOL * RT_VOLUME_DELAY);
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
RT_VOLUME_STEADY | RT_CARD_ON);
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, RT_CARD_OFF);
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0, RT_CARD_OFF);
} else {
val = sc->vol - vol;
if (val < 0) {
val *= -1;
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
RT_VOLUME_DOWN | RT_CARD_ON);
} else {
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
RT_VOLUME_UP | RT_CARD_ON);
}
DELAY(val * RT_VOLUME_DELAY);
bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
RT_VOLUME_STEADY | RT_CARD_ON);
}
}
void
rt_set_freq(struct rt_softc *sc, u_int32_t nfreq)
{
u_int32_t reg;
if (nfreq > MAX_FM_FREQ)
nfreq = MAX_FM_FREQ;
if (nfreq < MIN_FM_FREQ)
nfreq = MIN_FM_FREQ;
sc->freq = nfreq;
reg = lm700x_encode_freq(nfreq, sc->rf);
reg |= sc->stereo | sc->rf | LM700X_DIVIDER_FM;
lm700x_hardware_write(&sc->lm, reg, RT_VOLUME_STEADY);
rt_set_mute(sc, sc->vol);
}
/*
* Return state of the card - tuned/not tuned, mono/stereo
*/
u_int8_t
rt_state(bus_space_tag_t iot, bus_space_handle_t ioh)
{
u_int8_t ret;
bus_space_write_1(iot, ioh, 0,
RT_VOLUME_STEADY | RT_SIGNAL_METER | RT_CARD_ON);
DELAY(RT_SIGNAL_METER_DELAY);
ret = bus_space_read_1(iot, ioh, 0);
switch (ret) {
case 0xFD:
ret = RADIO_INFO_SIGNAL | RADIO_INFO_STEREO;
break;
case 0xFF:
ret = 0;
break;
default:
ret = RADIO_INFO_SIGNAL;
break;
}
return ret;
}
/*
* Convert volume to hardware representation.
*/
u_int8_t
rt_conv_vol(u_int8_t vol)
{
if (vol < VOLUME_RATIO(1))
return 0;
else if (vol >= VOLUME_RATIO(1) && vol < VOLUME_RATIO(2))
return 1;
else if (vol >= VOLUME_RATIO(2) && vol < VOLUME_RATIO(3))
return 2;
else if (vol >= VOLUME_RATIO(3) && vol < VOLUME_RATIO(4))
return 3;
else
return 4;
}
/*
* Convert volume from hardware representation
*/
u_int8_t
rt_unconv_vol(u_int8_t vol)
{
return VOLUME_RATIO(vol);
}
int
rt_find(bus_space_tag_t iot, bus_space_handle_t ioh)
{
struct rt_softc sc;
#if 0
u_int i, scanres = 0;
#endif
sc.lm.iot = iot;
sc.lm.ioh = ioh;
sc.lm.offset = 0;
sc.lm.wzcl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_OFF;
sc.lm.wzch = RT_WREN_ON | RT_CLCK_ON | RT_DATA_OFF;
sc.lm.wocl = RT_WREN_ON | RT_CLCK_OFF | RT_DATA_ON;
sc.lm.woch = RT_WREN_ON | RT_CLCK_ON | RT_DATA_ON;
sc.lm.initdata = 0;
sc.lm.rsetdata = RT_SIGNAL_METER;
sc.lm.init = rt_lm700x_init;
sc.lm.rset = rt_lm700x_rset;
sc.rf = LM700X_REF_050;
sc.mute = 0;
sc.stereo = LM700X_STEREO;
sc.vol = 0;
/*
* Scan whole FM range. If there is a card it'll
* respond on some frequency.
*/
return 0;
#if 0
for (i = MIN_FM_FREQ; !scanres && i < MAX_FM_FREQ; i += 10) {
rt_set_freq(&sc, i);
scanres += rt_state(iot, ioh);
}
return scanres;
#endif
}
void
rt_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
u_int32_t data)
{
/* Do nothing */
return;
}
void
rt_lm700x_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
u_int32_t data)
{
DELAY(1000);
bus_space_write_1(iot, ioh, off, RT_CARD_OFF | data);
DELAY(50000);
bus_space_write_1(iot, ioh, off, RT_VOLUME_STEADY | RT_CARD_ON | data);
}
int
rt_set_info(void *v, struct radio_info *ri)
{
struct rt_softc *sc = v;
sc->mute = ri->mute ? 1 : 0;
sc->vol = rt_conv_vol(ri->volume);
sc->stereo = ri->stereo ? LM700X_STEREO : LM700X_MONO;
sc->rf = lm700x_encode_ref(ri->rfreq);
rt_set_freq(sc, ri->freq);
rt_set_mute(sc, sc->vol);
return (0);
}
int
rt_get_info(void *v, struct radio_info *ri)
{
struct rt_softc *sc = v;
ri->mute = sc->mute;
ri->volume = rt_unconv_vol(sc->vol);
ri->stereo = sc->stereo == LM700X_STEREO ? 0 : 1;
ri->caps = RTRACK_CAPABILITIES;
ri->rfreq = lm700x_decode_ref(sc->rf);
ri->info = 3 & rt_state(sc->lm.iot, sc->lm.ioh);
ri->freq = sc->freq;
/* UNSUPPORTED */
ri->lock = 0;
return (0);
}

329
sys/dev/isa/radiotrack2.c Normal file
View File

@ -0,0 +1,329 @@
/* $OpenBSD: radiotrack2.c,v 1.1 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: radiotrack2.c,v 1.2 2001/10/18 16:51:36 pva Exp $ */
/*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
* 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 AUTHORS ``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 AUTHORS 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.
*/
/* AIMS Lab Radiotrack II FM Radio Card device driver */
/*
* Philips TEA5757H AM/FM Self Tuned Radio:
* http://www.semiconductors.philips.com/pip/TEA5757H
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/device.h>
#include <sys/radioio.h>
#include <dev/isa/isavar.h>
#include <dev/radio_if.h>
#include <dev/ic/tea5757.h>
#define RTII_BASE_VALID(x) ((x == 0x20C) || (x == 0x30C))
#define RTII_CAPABILITIES RADIO_CAPS_DETECT_STEREO | \
RADIO_CAPS_DETECT_SIGNAL | \
RADIO_CAPS_SET_MONO | \
RADIO_CAPS_LOCK_SENSITIVITY | \
RADIO_CAPS_HW_AFC | \
RADIO_CAPS_HW_SEARCH
#if 0
#define RTII_SIGNAL (1 << 3)
#define RTII_STEREO (1 << 3)
#endif /* 0 */
#define RTII_MUTE 0x01
#define RTII_UNMUTE 0x00
#define RTII_RESET 0xC8
#define RTII_DATA_ON (1 << 2)
#define RTII_DATA_OFF (0 << 2)
#define RTII_CLCK_ON (1 << 1)
#define RTII_CLCK_OFF (0 << 1)
#define RTII_WREN_ON (0 << 0)
#define RTII_WREN_OFF (1 << 0)
#define RTII_READ_CLOCK_LOW (RTII_DATA_ON | RTII_CLCK_OFF | RTII_WREN_OFF)
#define RTII_READ_CLOCK_HIGH (RTII_DATA_ON | RTII_CLCK_ON | RTII_WREN_OFF)
int rtii_probe(struct device *, void *, void *);
void rtii_attach(struct device *, struct device * self, void *);
int rtii_get_info(void *, struct radio_info *);
int rtii_set_info(void *, struct radio_info *);
int rtii_search(void *, int);
/* define our interface to the higher level radio driver */
struct radio_hw_if rtii_hw_if = {
NULL, /* open */
NULL, /* close */
rtii_get_info,
rtii_set_info,
rtii_search
};
struct rtii_softc {
struct device dev;
u_int32_t freq;
u_int32_t stereo;
u_int32_t lock;
u_int8_t vol;
int mute;
struct tea5757_t tea;
};
struct cfattach rtii_ca = {
sizeof(struct rtii_softc), rtii_probe, rtii_attach
};
struct cfdriver rtii_cd = {
NULL, "rtii", DV_DULL
};
void rtii_set_mute(struct rtii_softc *);
int rtii_find(bus_space_tag_t, bus_space_handle_t);
u_int32_t rtii_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void rtii_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void rtii_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void rtii_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
int
rtii_probe(struct device *parent, void *self, void *aux)
{
struct isa_attach_args *ia = aux;
bus_space_tag_t iot = ia->ia_iot;
bus_space_handle_t ioh;
int iosize = 1, iobase = ia->ia_iobase;
if (!RTII_BASE_VALID(iobase)) {
printf("rtii: configured iobase 0x%x invalid\n", iobase);
return 0;
}
if (bus_space_map(iot, iobase, iosize, 0, &ioh))
return 0;
bus_space_unmap(iot, ioh, iosize);
if (!rtii_find(iot, ioh))
return 0;
ia->ia_iosize = iosize;
return 1;
}
void
rtii_attach(struct device *parent, struct device *self, void *aux)
{
struct rtii_softc *sc = (void *) self;
struct isa_attach_args *ia = aux;
sc->tea.iot = ia->ia_iot;
sc->mute = 0;
sc->vol = 0;
sc->freq = MIN_FM_FREQ;
sc->stereo = TEA5757_STEREO;
sc->lock = TEA5757_S030;
/* remap I/O */
if (bus_space_map(sc->tea.iot, ia->ia_iobase, ia->ia_iosize,
0, &sc->tea.ioh))
panic("rtiiattach: bus_space_map() failed");
sc->tea.offset = 0;
sc->tea.init = rtii_init;
sc->tea.rset = rtii_rset;
sc->tea.write_bit = rtii_write_bit;
sc->tea.read = rtii_hw_read;
printf(": AIMS Lab Radiotrack II");
tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq);
rtii_set_mute(sc);
radio_attach_mi(&rtii_hw_if, sc, &sc->dev);
}
/*
* Mute/unmute the card
*/
void
rtii_set_mute(struct rtii_softc *sc)
{
u_int8_t mute;
mute = (sc->mute || !sc->vol) ? RTII_MUTE : RTII_UNMUTE;
bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
DELAY(6);
bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
}
void
rtii_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{
bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
}
void
rtii_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{
bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
}
int
rtii_find(bus_space_tag_t iot, bus_space_handle_t ioh)
{
struct rtii_softc sc;
u_int32_t freq;
sc.tea.iot = iot;
sc.tea.ioh = ioh;
sc.tea.offset = 0;
sc.tea.init = rtii_init;
sc.tea.rset = rtii_rset;
sc.tea.write_bit = rtii_write_bit;
sc.tea.read = rtii_hw_read;
sc.lock = TEA5757_S030;
sc.stereo = TEA5757_STEREO;
/*
* Let's try to write and read a frequency.
* If the written and read frequencies are
* the same then success.
*/
sc.freq = MIN_FM_FREQ;
tea5757_set_freq(&sc.tea, sc.stereo, sc.lock, sc.freq);
rtii_set_mute(&sc);
freq = rtii_hw_read(iot, ioh, sc.tea.offset);
if (tea5757_decode_freq(freq) == sc.freq)
return 1;
return 0;
}
void
rtii_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, int bit)
{
u_int8_t data;
data = bit ? RTII_DATA_ON : RTII_DATA_OFF;
bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_ON | data);
bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
}
u_int32_t
rtii_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
{
u_int8_t i;
u_int32_t res = 0;
bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
DELAY(6);
i = 24;
while ( i-- ) {
bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_HIGH);
DELAY(6);
bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
res |= bus_space_read_1(iot, ioh, off) & RTII_DATA_ON ? 1 : 0;
DELAY(6);
res <<= 1;
}
return (res & (TEA5757_DATA | TEA5757_FREQ)) >> 1;
}
int
rtii_get_info(void *v, struct radio_info *ri)
{
struct rtii_softc *sc = v;
ri->mute = sc->mute;
ri->volume = sc->vol ? 255 : 0;
ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
ri->caps = RTII_CAPABILITIES;
ri->rfreq = 0;
ri->lock = tea5757_decode_lock(sc->lock);
ri->freq = sc->freq = tea5757_decode_freq(rtii_hw_read(sc->tea.iot,
sc->tea.ioh, sc->tea.offset));
switch (bus_space_read_1(sc->tea.iot, sc->tea.ioh, 0)) {
case 0xFD:
ri->info = RADIO_INFO_SIGNAL | RADIO_INFO_STEREO;
break;
case 0xFF:
ri->info = 0;
break;
default:
ri->info = RADIO_INFO_SIGNAL;
}
return (0);
}
int
rtii_set_info(void *v, struct radio_info *ri)
{
struct rtii_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);
rtii_set_mute(sc);
return (0);
}
int
rtii_search(void *v, int f)
{
struct rtii_softc *sc = v;
tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
rtii_set_mute(sc);
return (0);
}

View File

@ -1,5 +1,5 @@
/* $OpenBSD: sf16fmr2.c,v 1.1 2001/10/04 20:17:43 gluk Exp $ */ /* $OpenBSD: sf16fmr2.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: sf16fmr2.c,v 1.10 2001/10/04 18:51:50 pva Exp $ */ /* $RuOBSD: sf16fmr2.c,v 1.12 2001/10/18 16:51:36 pva Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>, * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
@ -78,25 +78,28 @@
int sf2r_probe(struct device *, void *, void *); int sf2r_probe(struct device *, void *, void *);
void sf2r_attach(struct device *, struct device * self, void *); void sf2r_attach(struct device *, struct device * self, void *);
int sf2r_open(dev_t, int, int, struct proc *);
int sf2r_close(dev_t, int, int, struct proc *); int sf2r_get_info(void *, struct radio_info *);
int sf2r_ioctl(dev_t, u_long, caddr_t, int, struct proc *); int sf2r_set_info(void *, struct radio_info *);
int sf2r_search(void *, int);
/* define our interface to the higher level radio driver */ /* define our interface to the higher level radio driver */
struct radio_hw_if sf2r_hw_if = { struct radio_hw_if sf2r_hw_if = {
sf2r_open, NULL, /* open */
sf2r_close, NULL, /* close */
sf2r_ioctl sf2r_get_info,
sf2r_set_info,
sf2r_search
}; };
struct sf2r_softc { struct sf2r_softc {
struct device sc_dev; struct device sc_dev;
u_long sc_freq; u_int32_t freq;
u_long sc_stereo; u_int32_t stereo;
u_long sc_lock; u_int32_t lock;
u_char sc_vol; u_int8_t vol;
u_char sc_mute; int mute;
struct tea5757_t tea; struct tea5757_t tea;
}; };
@ -110,14 +113,13 @@ struct cfdriver sf2r_cd = {
}; };
void sf2r_set_mute(struct sf2r_softc *); void sf2r_set_mute(struct sf2r_softc *);
void sf2r_search(struct sf2r_softc *, u_char); int sf2r_find(bus_space_tag_t, bus_space_handle_t);
u_int sf2r_find(bus_space_tag_t, bus_space_handle_t);
u_long sf2r_read_register(bus_space_tag_t, bus_space_handle_t, bus_size_t); u_int32_t sf2r_read_register(bus_space_tag_t, bus_space_handle_t, bus_size_t);
void sf2r_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_long); void sf2r_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void sf2r_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_long); void sf2r_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void sf2r_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_char); void sf2r_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
int int
sf2r_probe(struct device *parent, void *self, void *aux) sf2r_probe(struct device *parent, void *self, void *aux)
@ -152,23 +154,11 @@ sf2r_attach(struct device *parent, struct device *self, void *aux)
struct isa_attach_args *ia = aux; struct isa_attach_args *ia = aux;
sc->tea.iot = ia->ia_iot; sc->tea.iot = ia->ia_iot;
#ifdef RADIO_INIT_MUTE sc->mute = 0;
sc->sc_mute = RADIO_INIT_MUTE; sc->vol = 0;
#else sc->freq = MIN_FM_FREQ;
sc->sc_mute = 1; sc->stereo = TEA5757_STEREO;
#endif /* RADIO_INIT_MUTE */ sc->lock = TEA5757_S030;
#ifdef RADIO_INIT_VOL
sc->sc_vol = RADIO_INIT_VOL;
#else
sc->sc_vol = 0;
#endif /* RADIO_INIT_VOL */
#ifdef RADIO_INIT_FREQ
sc->sc_freq = RADIO_INIT_FREQ;
#else
sc->sc_freq = MIN_FM_FREQ;
#endif /* RADIO_INIT_FREQ */
sc->sc_stereo = TEA5757_STEREO;
sc->sc_lock = TEA5757_S030;
/* remap I/O */ /* remap I/O */
if (bus_space_map(sc->tea.iot, ia->ia_iobase, ia->ia_iosize, if (bus_space_map(sc->tea.iot, ia->ia_iobase, ia->ia_iosize,
@ -183,132 +173,44 @@ sf2r_attach(struct device *parent, struct device *self, void *aux)
sc->tea.read = sf2r_read_register; sc->tea.read = sf2r_read_register;
printf(": SoundForte RadioLink SF16-FMR2"); printf(": SoundForte RadioLink SF16-FMR2");
tea5757_set_freq(&sc->tea, sc->sc_stereo, sc->sc_lock, sc->sc_freq); tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq);
sf2r_set_mute(sc); sf2r_set_mute(sc);
radio_attach_mi(&sf2r_hw_if, sc, &sc->sc_dev); radio_attach_mi(&sf2r_hw_if, sc, &sc->sc_dev);
} }
int
sf2r_open(dev_t dev, int flags, int fmt, struct proc *p)
{
struct sf2r_softc *sc;
return !(sc = sf2r_cd.cd_devs[0]) ? ENXIO : 0;
}
int
sf2r_close(dev_t dev, int flags, int fmt, struct proc *p)
{
return 0;
}
/*
* Handle the ioctl for the device
*/
int
sf2r_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
struct sf2r_softc *sc = sf2r_cd.cd_devs[0];
int error;
error = 0;
switch (cmd) {
case RIOCGMUTE:
*(u_long *)data = sc->sc_mute ? 1 : 0;
break;
case RIOCSMUTE:
sc->sc_mute = *(u_long *)data ? 1 : 0;
sf2r_set_mute(sc);
break;
case RIOCGVOLU:
*(u_long *)data = sc->sc_vol ? 255 : 0;
break;
case RIOCSVOLU:
sc->sc_vol = *(u_long *)data ? 1 : 0;
sf2r_set_mute(sc);
break;
case RIOCGMONO:
*(u_long *)data = sc->sc_stereo == TEA5757_STEREO ? 0 : 1;
break;
case RIOCSMONO:
sc->sc_stereo = *(u_long *)data ? TEA5757_MONO : TEA5757_STEREO;
tea5757_set_freq(&sc->tea, sc->sc_stereo, sc->sc_lock,
sc->sc_freq);
sf2r_set_mute(sc);
break;
case RIOCGFREQ:
sc->sc_freq = sf2r_read_register(sc->tea.iot, sc->tea.ioh,
sc->tea.offset);
sc->sc_freq = tea5757_decode_freq(sc->sc_freq);
*(u_long *)data = sc->sc_freq;
break;
case RIOCSFREQ:
sc->sc_freq = tea5757_set_freq(&sc->tea, sc->sc_stereo,
sc->sc_lock, *(u_long *)data);
sf2r_set_mute(sc);
break;
case RIOCSSRCH:
tea5757_search(&sc->tea, sc->sc_stereo, sc->sc_lock,
*(u_long *)data);
break;
case RIOCGCAPS:
*(u_long *)data = SF16FMR2_CAPABILITIES;
break;
case RIOCGINFO:
*(u_long *)data = 3 & (sf2r_read_register(sc->tea.iot,
sc->tea.ioh, 0) >> 25);
break;
case RIOCSLOCK:
sc->sc_lock = tea5757_encode_lock(*(u_char *)data);
tea5757_set_freq(&sc->tea, sc->sc_stereo, sc->sc_lock,
sc->sc_freq);
sf2r_set_mute(sc);
break;
case RIOCGLOCK:
*(u_long *)data = tea5757_decode_lock(sc->sc_lock);
break;
case RIOCSREFF:
/* FALLTHROUGH */
case RIOCGREFF:
/* NOT SUPPORTED */
default:
error = EINVAL; /* invalid agument */
}
return error;
}
/* /*
* Mute/unmute the card * Mute/unmute the card
*/ */
void void
sf2r_set_mute(struct sf2r_softc *sc) sf2r_set_mute(struct sf2r_softc *sc)
{ {
u_char mute; u_int8_t mute;
mute = (sc->sc_mute || !sc->sc_vol) ? SF16FMR2_MUTE : SF16FMR2_UNMUTE; mute = (sc->mute || !sc->vol) ? SF16FMR2_MUTE : SF16FMR2_UNMUTE;
bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute); bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
DELAY(6); DELAY(6);
bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute); bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
} }
void void
sf2r_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_long d) sf2r_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{ {
bus_space_write_1(iot, ioh, off, SF16FMR2_MUTE); bus_space_write_1(iot, ioh, off, SF16FMR2_MUTE);
} }
void void
sf2r_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_long d) sf2r_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{ {
bus_space_write_1(iot, ioh, off, SF16FMR2_MUTE); bus_space_write_1(iot, ioh, off, SF16FMR2_MUTE);
bus_space_write_1(iot, ioh, off, SF16FMR2_UNMUTE); bus_space_write_1(iot, ioh, off, SF16FMR2_UNMUTE);
} }
u_int int
sf2r_find(bus_space_tag_t iot, bus_space_handle_t ioh) sf2r_find(bus_space_tag_t iot, bus_space_handle_t ioh)
{ {
struct sf2r_softc sc; struct sf2r_softc sc;
u_long freq; u_int32_t freq;
sc.tea.iot = iot; sc.tea.iot = iot;
sc.tea.ioh = ioh; sc.tea.ioh = ioh;
@ -317,8 +219,8 @@ sf2r_find(bus_space_tag_t iot, bus_space_handle_t ioh)
sc.tea.rset = sf2r_rset; sc.tea.rset = sf2r_rset;
sc.tea.write_bit = sf2r_write_bit; sc.tea.write_bit = sf2r_write_bit;
sc.tea.read = sf2r_read_register; sc.tea.read = sf2r_read_register;
sc.sc_lock = TEA5757_S030; sc.lock = TEA5757_S030;
sc.sc_stereo = TEA5757_STEREO; sc.stereo = TEA5757_STEREO;
if ((bus_space_read_1(iot, ioh, 0) & 0x70) == 0x30) { if ((bus_space_read_1(iot, ioh, 0) & 0x70) == 0x30) {
/* /*
@ -326,15 +228,11 @@ sf2r_find(bus_space_tag_t iot, bus_space_handle_t ioh)
* If the written and read frequencies are * If the written and read frequencies are
* the same then success. * the same then success.
*/ */
#ifdef RADIO_INIT_FREQ sc.freq = MIN_FM_FREQ;
sc.sc_freq = RADIO_INIT_FREQ; tea5757_set_freq(&sc.tea, sc.stereo, sc.lock, sc.freq);
#else
sc.sc_freq = MIN_FM_FREQ;
#endif /* RADIO_INIT_FREQ */
tea5757_set_freq(&sc.tea, sc.sc_stereo, sc.sc_lock, sc.sc_freq);
sf2r_set_mute(&sc); sf2r_set_mute(&sc);
freq = sf2r_read_register(iot, ioh, sc.tea.offset); freq = sf2r_read_register(iot, ioh, sc.tea.offset);
if (tea5757_decode_freq(freq) == sc.sc_freq) if (tea5757_decode_freq(freq) == sc.freq)
return 1; return 1;
} }
@ -342,10 +240,9 @@ sf2r_find(bus_space_tag_t iot, bus_space_handle_t ioh)
} }
void void
sf2r_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, sf2r_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, int bit)
bus_size_t off, u_char bit)
{ {
u_char data; u_int8_t data;
data = bit ? SF16FMR2_DATA_ON : SF16FMR2_DATA_OFF; data = bit ? SF16FMR2_DATA_ON : SF16FMR2_DATA_OFF;
@ -357,12 +254,11 @@ sf2r_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
SF16FMR2_WREN_ON | SF16FMR2_CLCK_OFF | data); SF16FMR2_WREN_ON | SF16FMR2_CLCK_OFF | data);
} }
u_long u_int32_t
sf2r_read_register(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off) sf2r_read_register(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
{ {
u_char i; u_int32_t res = 0;
u_long res = 0; u_int8_t i, state = 0;
u_char state = 0;
bus_space_write_1(iot, ioh, off, SF16FMR2_READ_CLOCK_LOW); bus_space_write_1(iot, ioh, off, SF16FMR2_READ_CLOCK_LOW);
DELAY(6); DELAY(6);
@ -391,5 +287,52 @@ sf2r_read_register(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
res |= bus_space_read_1(iot, ioh, off) & SF16FMR2_DATA_ON; res |= bus_space_read_1(iot, ioh, off) & SF16FMR2_DATA_ON;
} }
return res | (state<<25); return res | (state << 24);
}
int
sf2r_get_info(void *v, struct radio_info *ri)
{
struct sf2r_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 = SF16FMR2_CAPABILITIES;
ri->rfreq = 0;
ri->lock = tea5757_decode_lock(sc->lock);
buf = sf2r_read_register(sc->tea.iot, sc->tea.ioh, sc->tea.offset);
ri->freq = sc->freq = tea5757_decode_freq(buf);
ri->info = 3 & (buf >> 24);
return (0);
}
int
sf2r_set_info(void *v, struct radio_info *ri)
{
struct sf2r_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);
sf2r_set_mute(sc);
return (0);
}
int
sf2r_search(void *v, int f)
{
struct sf2r_softc *sc = v;
tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
sf2r_set_mute(sc);
return (0);
} }

View File

@ -1,8 +1,9 @@
/* $OpenBSD: maxiradio.c,v 1.1 2001/10/04 20:25:28 gluk Exp $ */ /* $OpenBSD: maxiradio.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: maxiradio.c,v 1.3 2001/10/02 10:45:53 pva Exp $ */ /* $RuOBSD: maxiradio.c,v 1.5 2001/10/18 16:51:36 pva Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>
* Vladimir Popov <jumbo@narod.ru>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,6 +35,7 @@
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/radioio.h>
#include <machine/bus.h> #include <machine/bus.h>
@ -41,29 +43,65 @@
#include <dev/pci/pcivar.h> #include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h> #include <dev/pci/pcidevs.h>
#include <dev/ic/tea5757.h>
#include <dev/radio_if.h> #include <dev/radio_if.h>
int mr_match(struct device *, void *, void *); int mr_match(struct device *, void *, void *);
void mr_attach(struct device *, struct device *, void *); void mr_attach(struct device *, struct device *, void *);
int mr_open(dev_t, int, int, struct proc *);
int mr_close(dev_t, int, int, struct proc *); int mr_get_info(void *, struct radio_info *);
int mr_ioctl(dev_t, u_long, caddr_t, int, struct proc *); int mr_set_info(void *, struct radio_info *);
int mr_search(void *, int);
/* config base I/O address ? */ /* config base I/O address ? */
#define PCI_CBIO 0x6400 #define PCI_CBIO 0x6400
#define MAXIRADIO_CAPS RADIO_CAPS_DETECT_SIGNAL | \
RADIO_CAPS_SET_MONO | \
RADIO_CAPS_HW_SEARCH | \
RADIO_CAPS_HW_AFC | \
RADIO_CAPS_LOCK_SENSITIVITY
#if 0
RADIO_CAPS_DETECT_STEREO |
#endif /* 0 */
#define MAXIRADIO_MUTE 0x00
#define MAXIRADIO_UNMUTE 0x10
#define MAXIRADIO_SIGNAL 0x08
#define MR_WREN_ON (1 << 2)
#define MR_WREN_OFF (0 << 2)
#define MR_DATA_ON (1 << 1)
#define MR_DATA_OFF (0 << 1)
#define MR_CLCK_ON (1 << 0)
#define MR_CLCK_OFF (0 << 0)
#define MR_READ_CLOCK_LOW (MR_WREN_OFF | MR_DATA_ON | MR_CLCK_OFF)
#define MR_READ_CLOCK_HIGH (MR_WREN_OFF | MR_DATA_ON | MR_CLCK_ON)
/* define our interface to the high-level radio driver */ /* define our interface to the high-level radio driver */
struct radio_hw_if mr_hw_if = { struct radio_hw_if mr_hw_if = {
mr_open, NULL, /* open */
mr_close, NULL, /* close */
mr_ioctl mr_get_info,
mr_set_info,
mr_search
}; };
struct mr_softc { struct mr_softc {
struct device sc_dev; struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh; int mute;
u_int8_t vol;
u_int32_t freq;
u_int32_t stereo;
u_int32_t lock;
struct tea5757_t tea;
}; };
struct cfattach mr_ca = { struct cfattach mr_ca = {
@ -74,6 +112,14 @@ struct cfdriver mr_cd = {
NULL, "mr", DV_DULL NULL, "mr", DV_DULL
}; };
void mr_set_mute(struct mr_softc *);
void mr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
void mr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
void mr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
int mr_state(bus_space_tag_t, bus_space_handle_t);
u_int32_t mr_hardware_read(bus_space_tag_t, bus_space_handle_t,
bus_size_t);
int int
mr_match(struct device *parent, void *match, void *aux) mr_match(struct device *parent, void *match, void *aux)
{ {
@ -99,46 +145,143 @@ mr_attach(struct device *parent, struct device *self, void *aux)
return; return;
} }
if (bus_space_map(sc->sc_iot = pa->pa_iot, iobase, iosize, if (bus_space_map(sc->tea.iot = pa->pa_iot, iobase, iosize,
0, &sc->sc_ioh)) { 0, &sc->tea.ioh)) {
printf(": can't map i/o space\n"); printf(": can't map i/o space\n");
return; return;
} }
/* Enable the card */ /* Enable the card */
csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
csr | PCI_COMMAND_MASTER_ENABLE); csr | PCI_COMMAND_MASTER_ENABLE);
sc->freq = MIN_FM_FREQ;
sc->vol = 0;
sc->mute = 0;
sc->stereo = TEA5757_STEREO;
sc->lock = TEA5757_S030;
sc->tea.offset = 0;
sc->tea.init = mr_init;
sc->tea.rset = mr_rset;
sc->tea.write_bit = mr_write_bit;
sc->tea.read = mr_hardware_read;
radio_attach_mi(&mr_hw_if, sc, &sc->sc_dev); radio_attach_mi(&mr_hw_if, sc, &sc->sc_dev);
} }
int int
mr_open(dev_t dev, int flags, int fmt, struct proc *p) mr_get_info(void *v, struct radio_info *ri)
{ {
struct mr_softc *sc; struct mr_softc *sc = v;
return !(sc = mr_cd.cd_devs[0]) ? ENXIO : 0;
ri->mute = sc->mute;
ri->volume = sc->vol ? 255 : 0;
ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
ri->caps = MAXIRADIO_CAPS;
ri->rfreq = 0;
ri->lock = tea5757_decode_lock(sc->lock);
ri->freq = sc->freq = tea5757_decode_freq(mr_hardware_read(sc->tea.iot,
sc->tea.ioh, sc->tea.offset));
ri->info = mr_state(sc->tea.iot, sc->tea.ioh);
return (0);
} }
int int
mr_close(dev_t dev, int flags, int fmt, struct proc *p) mr_set_info(void *v, struct radio_info *ri)
{ {
return 0; struct mr_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);
mr_set_mute(sc);
return (0);
} }
/*
* Handle the ioctl for the device
*/
int int
mr_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) mr_search(void *v, int f)
{ {
int error; struct mr_softc *sc = v;
error = 0; tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
switch (cmd) { mr_set_mute(sc);
default:
error = EINVAL; /* invalid agument */ return (0);
}
void
mr_set_mute(struct mr_softc *sc)
{
int mute;
mute = (sc->mute || !sc->vol) ? MAXIRADIO_MUTE : MAXIRADIO_UNMUTE;
bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
}
void
mr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
int bit)
{
u_int8_t data;
data = bit ? MR_DATA_ON : MR_DATA_OFF;
bus_space_write_1(iot, ioh, off, MR_WREN_ON | MR_CLCK_OFF | data);
DELAY(5);
bus_space_write_1(iot, ioh, off, MR_WREN_ON | MR_CLCK_ON | data);
DELAY(5);
bus_space_write_1(iot, ioh, off, MR_WREN_ON | MR_CLCK_OFF | data);
DELAY(5);
}
void
mr_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{
bus_space_write_1(iot, ioh, off, MR_WREN_ON | MR_DATA_ON | MR_CLCK_OFF);
}
void
mr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
{
bus_space_write_1(iot, ioh, off, MAXIRADIO_UNMUTE);
}
/* COMPLETELY UNTESTED */
u_int32_t
mr_hardware_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
{
u_int32_t reg = 0ul;
int i;
bus_space_write_1(iot, ioh, off, MR_READ_CLOCK_LOW);
DELAY(5);
i = 24;
while (i--) {
bus_space_write_1(iot, ioh, off, MR_READ_CLOCK_HIGH);
DELAY(5);
bus_space_write_1(iot, ioh, off, MR_READ_CLOCK_LOW);
DELAY(5);
reg |= bus_space_read_1(iot, ioh, off) & MR_DATA_ON ? 1 : 0;
reg <<= 1;
} }
return error;
reg >>= 1;
return (reg & (TEA5757_DATA | TEA5757_FREQ));
}
int
mr_state(bus_space_tag_t iot, bus_space_handle_t ioh)
{
/* XXX: where is a stereo bit ? */
return bus_space_read_1(iot, ioh, 0) & MAXIRADIO_SIGNAL ?
(0 << 1) : (1 << 1);
} }

View File

@ -1,4 +1,5 @@
/* $OpenBSD: sf64pcr.c,v 1.1 2001/10/04 20:22:11 gluk Exp $ */ /* $OpenBSD: sf64pcr.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: sf64pcr.c,v 1.11 2001/12/05 10:19:40 mickey Exp $ */
/* /*
* Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru> * Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru>
@ -69,6 +70,9 @@
#define SF64PCR_SIGNAL 0x80 #define SF64PCR_SIGNAL 0x80
#define SF64PCR_STEREO 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_ON (1 << 0)
#define SF64PCR_CLCK_OFF (0 << 0) #define SF64PCR_CLCK_OFF (0 << 0)
@ -108,25 +112,28 @@
int sf64pcr_match(struct device *, void *, void *); int sf64pcr_match(struct device *, void *, void *);
void sf64pcr_attach(struct device *, struct device * self, void *); void sf64pcr_attach(struct device *, struct device * self, void *);
int sf64pcr_open(dev_t, int, int, struct proc *);
int sf64pcr_close(dev_t, int, int, struct proc *); int sf64pcr_get_info(void *, struct radio_info *);
int sf64pcr_ioctl(dev_t, u_long, caddr_t, int, struct proc *); int sf64pcr_set_info(void *, struct radio_info *);
int sf64pcr_search(void *, int);
/* define our interface to the high-level radio driver */ /* define our interface to the high-level radio driver */
struct radio_hw_if sf4r_hw_if = { struct radio_hw_if sf4r_hw_if = {
sf64pcr_open, NULL, /* open */
sf64pcr_close, NULL, /* close */
sf64pcr_ioctl sf64pcr_get_info,
sf64pcr_set_info,
sf64pcr_search
}; };
struct sf64pcr_softc { struct sf64pcr_softc {
struct device dev; struct device dev;
u_char mute; int mute;
u_char vol; u_int8_t vol;
u_long freq; u_int32_t freq;
u_long stereo; u_int32_t stereo;
u_long lock; u_int32_t lock;
struct tea5757_t tea; struct tea5757_t tea;
}; };
@ -144,11 +151,10 @@ struct cfdriver sf4r_cd = {
*/ */
void sf64pcr_set_mute(struct sf64pcr_softc *); void sf64pcr_set_mute(struct sf64pcr_softc *);
void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_long); 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_long); 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, void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
bus_size_t, u_char); u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
u_long sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
/* /*
* PCI initialization stuff * PCI initialization stuff
@ -191,21 +197,9 @@ sf64pcr_attach(struct device *parent, struct device *self, void *aux)
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
csr | PCI_COMMAND_MASTER_ENABLE); csr | PCI_COMMAND_MASTER_ENABLE);
#ifdef RADIO_INIT_VOLU
sc->vol = RADIO_INIT_VOLU;
#else
sc->vol = 0; sc->vol = 0;
#endif /* RADIO_INIT_VOLU */
#ifdef RADIO_INIT_MUTE
sc->mute = RADIO_INIT_MUTE;
#else
sc->mute = 0; sc->mute = 0;
#endif /* RADIO_INIT_MUTE */
#ifdef RADIO_INIT_FREQ
sc->freq = RADIO_INIT_FREQ;
#else
sc->freq = MIN_FM_FREQ; sc->freq = MIN_FM_FREQ;
#endif /* RADIO_INIT_FREQ */
sc->stereo = TEA5757_STEREO; sc->stereo = TEA5757_STEREO;
sc->lock = TEA5757_S030; sc->lock = TEA5757_S030;
sc->tea.offset = SF64PCR_PCI_OFFSET; sc->tea.offset = SF64PCR_PCI_OFFSET;
@ -220,26 +214,13 @@ sf64pcr_attach(struct device *parent, struct device *self, void *aux)
radio_attach_mi(&sf4r_hw_if, sc, &sc->dev); radio_attach_mi(&sf4r_hw_if, sc, &sc->dev);
} }
int
sf64pcr_open(dev_t dev, int flags, int fmt, struct proc *p)
{
struct sf64pcr_softc *sc;
return !(sc = sf4r_cd.cd_devs[0]) ? ENXIO : 0;
}
int
sf64pcr_close(dev_t dev, int flags, int fmt, struct proc *p)
{
return 0;
}
/* /*
* Mute/unmute * Mute/unmute
*/ */
void void
sf64pcr_set_mute(struct sf64pcr_softc *sc) sf64pcr_set_mute(struct sf64pcr_softc *sc)
{ {
u_long mute; u_int16_t mute;
mute = (sc->mute || !sc->vol) ? SF64PCR_MUTE : SF64PCR_UNMUTE; mute = (sc->mute || !sc->vol) ? SF64PCR_MUTE : SF64PCR_UNMUTE;
bus_space_write_2(sc->tea.iot, sc->tea.ioh, sc->tea.offset, mute); bus_space_write_2(sc->tea.iot, sc->tea.ioh, sc->tea.offset, mute);
@ -247,9 +228,9 @@ sf64pcr_set_mute(struct sf64pcr_softc *sc)
void void
sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
bus_size_t off, u_char bit) bus_size_t off, int bit)
{ {
u_int data, wren; u_int16_t data, wren;
wren = SF64PCR_0xF800 | SF64PCR_WREN1_ON | SF64PCR_WREN2_ON; wren = SF64PCR_0xF800 | SF64PCR_WREN1_ON | SF64PCR_WREN2_ON;
data = bit ? SF64PCR_DATA_ON : SF64PCR_DATA_OFF; data = bit ? SF64PCR_DATA_ON : SF64PCR_DATA_OFF;
@ -264,7 +245,7 @@ sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
void void
sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh, sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
bus_size_t offset, u_long d) bus_size_t offset, u_int32_t d)
{ {
d = SF64PCR_WRITE_ONE_CLOCK_LOW; d = SF64PCR_WRITE_ONE_CLOCK_LOW;
@ -274,7 +255,7 @@ sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
void void
sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh, sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
bus_size_t offset, u_long d) bus_size_t offset, u_int32_t d)
{ {
/* Do nothing */ /* Do nothing */
return; return;
@ -283,10 +264,10 @@ sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
/* /*
* Read TEA5757 shift register * Read TEA5757 shift register
*/ */
u_long u_int32_t
sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset) sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
{ {
u_long res = 0ul; u_int32_t res = 0ul;
int rb, ind = 0; int rb, ind = 0;
bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_LOW); bus_space_write_2(iot, ioh, offset, SF64PCR_READ_CLOCK_LOW);
@ -322,75 +303,50 @@ sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
} }
int int
sf64pcr_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr) sf64pcr_get_info(void *v, struct radio_info *ri)
{ {
struct sf64pcr_softc *sc = sf4r_cd.cd_devs[0]; struct sf64pcr_softc *sc = v;
int error = 0; u_int32_t buf;
u_long freq;
switch (cmd) { ri->mute = sc->mute;
case RIOCGINFO: ri->volume = sc->vol ? 255 : 0;
freq = sf64pcr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset); ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
*(u_long *)arg = 0; ri->caps = CARD_RADIO_CAPS;
if (freq & (1 << 24)) ri->rfreq = 0;
*(u_long *)arg |= !RADIO_INFO_STEREO; ri->lock = tea5757_decode_lock(sc->lock);
if (freq & (1 << 25))
*(u_long *)arg |= !RADIO_INFO_SIGNAL; buf = sf64pcr_hw_read(sc->tea.iot, sc->tea.ioh, sc->tea.offset);
break; ri->freq = sc->freq = tea5757_decode_freq(buf);
case RIOCGMONO: ri->info = buf & SF64PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL;
*(u_long *)arg = sc->stereo == TEA5757_STEREO ? 0 : 1; ri->info |= buf & SF64PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO;
break;
case RIOCSMONO: return (0);
sc->stereo = *(u_long *)arg ? TEA5757_MONO : TEA5757_STEREO; }
tea5757_set_freq(&sc->tea, sc->lock, sc->stereo, sc->freq);
sf64pcr_set_mute(sc); int
break; sf64pcr_set_info(void *v, struct radio_info *ri)
case RIOCGCAPS: {
*(u_long *)arg = CARD_RADIO_CAPS;
break; struct sf64pcr_softc *sc = v;
case RIOCGVOLU:
*(u_long *)arg = sc->vol ? 255 : 0; sc->mute = ri->mute ? 1 : 0;
break; sc->vol = ri->volume ? 255 : 0;
case RIOCGMUTE: sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
*(u_long *)arg = sc->mute ? 1 : 0; sc->lock = tea5757_encode_lock(ri->lock);
break; ri->freq = sc->freq = tea5757_set_freq(&sc->tea,
case RIOCSVOLU: sc->lock, sc->stereo, ri->freq);
sc->vol = *(u_long *)arg ? 255 : 0; sf64pcr_set_mute(sc);
sf64pcr_set_mute(sc);
break; return (0);
case RIOCSMUTE: }
sc->mute = *(u_long *)arg ? 1 : 0;
sf64pcr_set_mute(sc); int
break; sf64pcr_search(void *v, int f)
case RIOCGFREQ: {
freq = tea5757_decode_freq(sf64pcr_hw_read(sc->tea.iot, struct sf64pcr_softc *sc = v;
sc->tea.ioh, sc->tea.offset));
*(u_long *)arg = freq; tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
sc->freq = freq; sf64pcr_set_mute(sc);
break;
case RIOCSFREQ: return (0);
sc->freq = tea5757_set_freq(&sc->tea, sc->lock,
sc->stereo, *(u_long *)arg);
sf64pcr_set_mute(sc);
break;
case RIOCGLOCK:
*(u_long *)arg = tea5757_decode_lock(sc->lock);
break;
case RIOCSLOCK:
sc->lock = tea5757_encode_lock(*(u_char *)arg);
tea5757_set_freq(&sc->tea, sc->lock, sc->stereo, sc->freq);
sf64pcr_set_mute(sc);
break;
case RIOCSSRCH:
tea5757_search(&sc->tea, sc->lock, sc->stereo, *(u_long *)arg);
sf64pcr_set_mute(sc);
break;
case RIOCSREFF:
/* FALLTHROUGH */
case RIOCGREFF:
/* FALLTHROUGH */
default:
error = EINVAL; /* not supported */
}
return (error);
} }

View File

@ -1,5 +1,5 @@
/* $OpenBSD: radio.c,v 1.1 2001/10/04 19:18:00 gluk Exp $ */ /* $OpenBSD: radio.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: radio.c,v 1.5 2001/09/30 14:52:49 pva Exp $ */ /* $RuOBSD: radio.c,v 1.7 2001/12/04 06:03:05 tm Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>
@ -35,6 +35,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/device.h> #include <sys/device.h>
#include <sys/radioio.h> #include <sys/radioio.h>
#include <dev/radio_if.h> #include <dev/radio_if.h>
#include <dev/radiovar.h> #include <dev/radiovar.h>
@ -86,8 +87,11 @@ radioopen(dev_t dev, int flags, int fmt, struct proc *p)
(sc = radio_cd.cd_devs[unit]) == NULL || (sc = radio_cd.cd_devs[unit]) == NULL ||
sc->hw_if == NULL) sc->hw_if == NULL)
return (ENXIO); return (ENXIO);
if (sc->hw_if->open != NULL)
return (sc->hw_if->open(sc->hw_hdl, flags, fmt, p));
else else
return (sc->hw_if->open(dev, flags, fmt, p)); return (0);
} }
int int
@ -96,22 +100,46 @@ radioclose(dev_t dev, int flags, int fmt, struct proc *p)
struct radio_softc *sc; struct radio_softc *sc;
sc = radio_cd.cd_devs[RADIOUNIT(dev)]; sc = radio_cd.cd_devs[RADIOUNIT(dev)];
return (sc->hw_if->close(dev, flags, fmt, p));
if (sc->hw_if->close != NULL)
return (sc->hw_if->close(sc->hw_hdl, flags, fmt, p));
else
return (0);
} }
int int
radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{ {
int unit;
struct radio_softc *sc; struct radio_softc *sc;
int unit, error;
unit = RADIOUNIT(dev); unit = RADIOUNIT(dev);
if (unit >= radio_cd.cd_ndevs || if (unit >= radio_cd.cd_ndevs ||
(sc = radio_cd.cd_devs[unit]) == NULL || (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL)
sc->hw_if == NULL)
return (ENXIO); return (ENXIO);
else
return (sc->hw_if->ioctl(dev, cmd, data, flags, p)); error = EOPNOTSUPP;
switch (cmd) {
case RIOCGINFO:
if (sc->hw_if->get_info)
error = (sc->hw_if->get_info)(sc->hw_hdl,
(struct radio_info *)data);
break;
case RIOCSINFO:
if (sc->hw_if->set_info)
error = (sc->hw_if->set_info)(sc->hw_hdl,
(struct radio_info *)data);
break;
case RIOCSSRCH:
if (sc->hw_if->search)
error = (sc->hw_if->search)(sc->hw_hdl,
*(int *)data);
break;
default:
error = EINVAL;
}
return (error);
} }
/* /*

View File

@ -1,5 +1,5 @@
/* $OpenBSD: radio_if.h,v 1.1 2001/10/04 19:17:59 gluk Exp $ */ /* $OpenBSD: radio_if.h,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: radio_if.h,v 1.5 2001/09/29 20:33:02 gluk Exp $ */ /* $RuOBSD: radio_if.h,v 1.6 2001/10/18 16:51:36 pva Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>
@ -37,13 +37,14 @@
struct radio_hw_if { struct radio_hw_if {
/* open hardware */ /* open hardware */
int (*open)(dev_t, int, int, struct proc *); int (*open)(void *, int, int, struct proc *);
/* close hardware */ /* close hardware */
int (*close)(dev_t, int, int, struct proc *); int (*close)(void *, int, int, struct proc *);
/* ioctl hardware */ int (*get_info)(void *, struct radio_info *);
int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc*); int (*set_info)(void *, struct radio_info *);
int (*search)(void *, int);
}; };
struct radio_attach_args { struct radio_attach_args {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: radiovar.h,v 1.1 2001/10/04 19:17:59 gluk Exp $ */ /* $OpenBSD: radiovar.h,v 1.2 2001/12/05 10:27:06 mickey Exp $ */
/* $RuOBSD: radiovar.h,v 1.3 2001/09/29 17:10:16 pva Exp $ */ /* $RuOBSD: radiovar.h,v 1.3 2001/09/29 17:10:16 pva Exp $ */
/* /*

View File

@ -1,5 +1,5 @@
/* $OpenBSD: radioio.h,v 1.1 2001/10/04 19:17:59 gluk Exp $ */ /* $OpenBSD: radioio.h,v 1.2 2001/12/05 10:27:05 mickey Exp $ */
/* $RuOBSD: radioio.h,v 1.3 2001/09/29 17:10:16 pva Exp $ */ /* $RuOBSD: radioio.h,v 1.4 2001/10/18 16:51:36 pva Exp $ */
/* /*
* Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>, * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
@ -30,11 +30,21 @@
#ifndef _SYS_RADIOIO_H_ #ifndef _SYS_RADIOIO_H_
#define _SYS_RADIOIO_H_ #define _SYS_RADIOIO_H_
#include <sys/param.h>
#define MIN_FM_FREQ 87500 #define MIN_FM_FREQ 87500
#define MAX_FM_FREQ 108000 #define MAX_FM_FREQ 108000
#define IF_FREQ 10700 #define IF_FREQ 10700
struct radio_info {
int mute;
int volume;
int stereo;
int rfreq; /* reference frequency */
int lock; /* locking field strength during an automatic search */
u_int32_t freq; /* in kHz */
u_int32_t caps; /* card capabilities */
#define RADIO_CAPS_DETECT_STEREO (1<<0) #define RADIO_CAPS_DETECT_STEREO (1<<0)
#define RADIO_CAPS_DETECT_SIGNAL (1<<1) #define RADIO_CAPS_DETECT_SIGNAL (1<<1)
#define RADIO_CAPS_SET_MONO (1<<2) #define RADIO_CAPS_SET_MONO (1<<2)
@ -45,25 +55,14 @@
#define RADIO_CAPS_RESERVED1 (1<<7) #define RADIO_CAPS_RESERVED1 (1<<7)
#define RADIO_CAPS_RESERVED2 (0xFF<<8) #define RADIO_CAPS_RESERVED2 (0xFF<<8)
#define RADIO_CARD_TYPE (0xFF<<16) #define RADIO_CARD_TYPE (0xFF<<16)
u_int32_t info;
#define RADIO_INFO_STEREO (1<<0) #define RADIO_INFO_STEREO (1<<0)
#define RADIO_INFO_SIGNAL (1<<1) #define RADIO_INFO_SIGNAL (1<<1)
};
/* Radio device operations */ /* Radio device operations */
#define RIOCSMUTE _IOW('R', 21, u_long) /* set mute/unmute */ #define RIOCGINFO _IOR('R', 21, struct radio_info) /* get info */
#define RIOCGMUTE _IOR('R', 21, u_long) /* get mute state */ #define RIOCSINFO _IOWR('R', 22, struct radio_info) /* set info */
#define RIOCGVOLU _IOR('R', 22, u_long) /* get volume */ #define RIOCSSRCH _IOW('R', 23, int) /* search up/down */
#define RIOCSVOLU _IOW('R', 22, u_long) /* set volume */
#define RIOCGMONO _IOR('R', 23, u_long) /* get mono/stereo */
#define RIOCSMONO _IOW('R', 23, u_long) /* toggle mono/stereo */
#define RIOCGFREQ _IOR('R', 24, u_long) /* get frequency (in kHz) */
#define RIOCSFREQ _IOW('R', 24, u_long) /* set frequency (in kHz) */
#define RIOCSSRCH _IOW('R', 25, u_long) /* search up/down */
#define RIOCGCAPS _IOR('R', 26, u_long) /* get card capabilities */
#define RIOCGINFO _IOR('R', 27, u_long) /* get generic information */
#define RIOCSREFF _IOW('R', 28, u_long) /* set reference frequency */
#define RIOCGREFF _IOR('R', 28, u_long) /* get reference frequency */
#define RIOCSLOCK _IOW('R', 29, u_long) /* set lock sensetivity */
#define RIOCGLOCK _IOR('R', 29, u_long) /* get lock sensetivity */
#endif /* _SYS_RADIOIO_H_ */ #endif /* _SYS_RADIOIO_H_ */