FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/gtp.c
1 /* $NetBSD: gtp.c,v 1.6 2003/07/14 15:47:24 lukem Exp $ */
2 /* $OpenBSD: gtp.c,v 1.1 2002/06/03 16:13:21 mickey Exp $ */
3
4 /*
5 * Copyright (c) 2002 Vladimir Popov <jumbo@narod.ru>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Gemtek PCI Radio Card Device Driver */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: gtp.c,v 1.6 2003/07/14 15:47:24 lukem Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/proc.h>
40 #include <sys/radioio.h>
41
42 #include <machine/bus.h>
43
44 #include <dev/pci/pcireg.h>
45 #include <dev/pci/pcivar.h>
46 #include <dev/pci/pcidevs.h>
47
48 #include <dev/ic/tea5757.h>
49 #include <dev/radio_if.h>
50
51 #define PCI_CBIO 0x10
52
53 int gtp_match(struct device *, struct cfdata *, void *);
54 void gtp_attach(struct device *, struct device *, void *);
55
56 int gtp_get_info(void *, struct radio_info *);
57 int gtp_set_info(void *, struct radio_info *);
58 int gtp_search(void *, int);
59
60 #define GEMTEK_PCI_CAPS RADIO_CAPS_DETECT_SIGNAL | \
61 RADIO_CAPS_DETECT_STEREO | \
62 RADIO_CAPS_SET_MONO | \
63 RADIO_CAPS_HW_SEARCH | \
64 RADIO_CAPS_HW_AFC | \
65 RADIO_CAPS_LOCK_SENSITIVITY
66
67 #define GEMTEK_PCI_MUTE 0x00
68 #define GEMTEK_PCI_RSET 0x10
69
70 #define GEMTEK_PCI_SIGNAL 0x08
71 #define GEMTEK_PCI_STEREO 0x08
72
73 #define GTP_WREN_ON (1 << 2)
74 #define GTP_WREN_OFF (0 << 2)
75
76 #define GTP_DATA_ON (1 << 1)
77 #define GTP_DATA_OFF (0 << 1)
78
79 #define GTP_CLCK_ON (1 << 0)
80 #define GTP_CLCK_OFF (0 << 0)
81
82 #define GTP_READ_CLOCK_LOW (GTP_WREN_OFF | GTP_DATA_ON | GTP_CLCK_OFF)
83 #define GTP_READ_CLOCK_HIGH (GTP_WREN_OFF | GTP_DATA_ON | GTP_CLCK_ON)
84
85 /* define our interface to the high-level radio driver */
86
87 struct radio_hw_if gtp_hw_if = {
88 NULL, /* open */
89 NULL, /* close */
90 gtp_get_info,
91 gtp_set_info,
92 gtp_search
93 };
94
95 struct gtp_softc {
96 struct device sc_dev;
97
98 int mute;
99 u_int8_t vol;
100 u_int32_t freq;
101 u_int32_t stereo;
102 u_int32_t lock;
103
104 struct tea5757_t tea;
105 };
106
107 CFATTACH_DECL(gtp, sizeof(struct gtp_softc),
108 gtp_match, gtp_attach, NULL, NULL);
109
110 void gtp_set_mute(struct gtp_softc *);
111 void gtp_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
112 void gtp_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
113 void gtp_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
114 int gtp_state(bus_space_tag_t, bus_space_handle_t);
115 u_int32_t gtp_hardware_read(bus_space_tag_t, bus_space_handle_t,
116 bus_size_t);
117
118 int
119 gtp_match(struct device *parent, struct cfdata *cf, void *aux)
120 {
121 struct pci_attach_args *pa = aux;
122 /* FIXME:
123 * Guillemot produces the card that
124 * was originally developed by Gemtek
125 */
126 #if 0
127 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_GEMTEK &&
128 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_GEMTEK_PR103)
129 return (1);
130 #else
131 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_GUILLEMOT &&
132 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_GUILLEMOT_MAXIRADIO)
133 return (1);
134 #endif
135 return (0);
136 }
137
138 void
139 gtp_attach(struct device *parent, struct device *self, void *aux)
140 {
141 struct gtp_softc *sc = (struct gtp_softc *) self;
142 struct pci_attach_args *pa = aux;
143 struct cfdata *cf = sc->sc_dev.dv_cfdata;
144 pci_chipset_tag_t pc = pa->pa_pc;
145 bus_size_t iosize;
146 pcireg_t csr;
147 char devinfo[256];
148
149 aprint_naive(": Radio controller\n");
150
151 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
152 aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
153 PCI_REVISION(pa->pa_class));
154
155 /* Map I/O registers */
156 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &sc->tea.iot,
157 &sc->tea.ioh, NULL, &iosize)) {
158 aprint_error(": can't map i/o space\n");
159 return;
160 }
161
162 /* Enable the card */
163 csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
164 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
165 csr | PCI_COMMAND_MASTER_ENABLE);
166
167 sc->vol = 0;
168 sc->mute = 0;
169 sc->freq = MIN_FM_FREQ;
170 sc->stereo = TEA5757_STEREO;
171 sc->lock = TEA5757_S030;
172 sc->tea.offset = 0;
173 sc->tea.flags = cf->cf_flags;
174 sc->tea.init = gtp_init;
175 sc->tea.rset = gtp_rset;
176 sc->tea.write_bit = gtp_write_bit;
177 sc->tea.read = gtp_hardware_read;
178
179 aprint_normal(": Gemtek PR103\n");
180
181 radio_attach_mi(>p_hw_if, sc, &sc->sc_dev);
182 }
183
184 int
185 gtp_get_info(void *v, struct radio_info *ri)
186 {
187 struct gtp_softc *sc = v;
188
189 ri->mute = sc->mute;
190 ri->volume = sc->vol ? 255 : 0;
191 ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
192 ri->caps = GEMTEK_PCI_CAPS;
193 ri->rfreq = 0;
194 ri->lock = tea5757_decode_lock(sc->lock);
195
196 /* Frequency read unsupported */
197 ri->freq = sc->freq;
198
199 ri->info = gtp_state(sc->tea.iot, sc->tea.ioh);
200 gtp_set_mute(sc);
201
202 return (0);
203 }
204
205 int
206 gtp_set_info(void *v, struct radio_info *ri)
207 {
208 struct gtp_softc *sc = v;
209
210 sc->mute = ri->mute ? 1 : 0;
211 sc->vol = ri->volume ? 255 : 0;
212 sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
213 sc->lock = tea5757_encode_lock(ri->lock);
214 ri->freq = sc->freq = tea5757_set_freq(&sc->tea,
215 sc->lock, sc->stereo, ri->freq);
216 gtp_set_mute(sc);
217
218 return (0);
219 }
220
221 int
222 gtp_search(void *v, int f)
223 {
224 struct gtp_softc *sc = v;
225
226 tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
227 gtp_set_mute(sc);
228
229 return (0);
230 }
231
232 void
233 gtp_set_mute(struct gtp_softc *sc)
234 {
235 if (sc->mute || !sc->vol)
236 bus_space_write_2(sc->tea.iot, sc->tea.ioh, 0, GEMTEK_PCI_MUTE);
237 else
238 sc->freq = tea5757_set_freq(&sc->tea,
239 sc->lock, sc->stereo, sc->freq);
240 }
241
242 void
243 gtp_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
244 int bit)
245 {
246 u_int8_t data;
247
248 data = bit ? GTP_DATA_ON : GTP_DATA_OFF;
249 bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_OFF | data);
250 bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_ON | data);
251 bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_CLCK_OFF | data);
252 }
253
254 void
255 gtp_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
256 {
257 bus_space_write_1(iot, ioh, off, GTP_WREN_ON | GTP_DATA_ON | GTP_CLCK_OFF);
258 }
259
260 void
261 gtp_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
262 {
263 bus_space_write_1(iot, ioh, off, GEMTEK_PCI_RSET);
264 }
265
266 u_int32_t
267 gtp_hardware_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
268 {
269 /* UNSUPPORTED */
270 return 0;
271 }
272
273 int
274 gtp_state(bus_space_tag_t iot, bus_space_handle_t ioh)
275 {
276 int ret;
277
278 bus_space_write_2(iot, ioh, 0,
279 GTP_DATA_ON | GTP_WREN_OFF | GTP_CLCK_OFF);
280 ret = bus_space_read_2(iot, ioh, 0) &
281 GEMTEK_PCI_STEREO? 0 : RADIO_INFO_STEREO;
282 bus_space_write_2(iot, ioh, 0,
283 GTP_DATA_ON | GTP_WREN_OFF | GTP_CLCK_ON);
284 ret |= bus_space_read_2(iot, ioh, 0) &
285 GEMTEK_PCI_SIGNAL? 0 : RADIO_INFO_SIGNAL;
286
287 return ret;
288 }
Cache object: e9d09ca30d9e8ebda38c6431cd5a1238
|