This source file includes following definitions.
- az_probe
- az_attach
- az_set_mute
- az_set_freq
- az_state
- az_conv_vol
- az_unconv_vol
- az_find
- az_lm700x_init
- az_lm700x_rset
- az_get_info
- az_set_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/device.h>
46 #include <sys/radioio.h>
47
48 #include <machine/bus.h>
49
50 #include <dev/isa/isavar.h>
51 #include <dev/ic/lm700x.h>
52 #include <dev/radio_if.h>
53
54 #define RF_25K 25
55 #define RF_50K 50
56 #define RF_100K 100
57
58 #define MAX_VOL 3
59 #define VOLUME_RATIO(x) (255 * x / MAX_VOL)
60
61 #define AZ_BASE_VALID(x) ((x == 0x350) || (x == 0x358))
62 #define AZTECH_CAPABILITIES RADIO_CAPS_DETECT_STEREO | \
63 RADIO_CAPS_DETECT_SIGNAL | \
64 RADIO_CAPS_SET_MONO | \
65 RADIO_CAPS_REFERENCE_FREQ
66
67
68 #define AZTECH_STEREO (1 << 0)
69 #define AZTECH_SIGNAL (1 << 1)
70
71 #define AZ_WREN_ON (1 << 1)
72 #define AZ_WREN_OFF (0 << 1)
73
74 #define AZ_CLCK_ON (1 << 6)
75 #define AZ_CLCK_OFF (0 << 6)
76
77 #define AZ_DATA_ON (1 << 7)
78 #define AZ_DATA_OFF (0 << 7)
79
80 int az_probe(struct device *, void *, void *);
81 void az_attach(struct device *, struct device * self, void *);
82
83 int az_get_info(void *, struct radio_info *);
84 int az_set_info(void *, struct radio_info *);
85
86 struct radio_hw_if az_hw_if = {
87 NULL,
88 NULL,
89 az_get_info,
90 az_set_info,
91 NULL
92 };
93
94 struct az_softc {
95 struct device sc_dev;
96
97 int mute;
98 u_int8_t vol;
99 u_int32_t freq;
100 u_int32_t rf;
101 u_int32_t stereo;
102
103 struct lm700x_t lm;
104 };
105
106 struct cfattach az_ca = {
107 sizeof(struct az_softc), az_probe, az_attach
108 };
109
110 struct cfdriver az_cd = {
111 NULL, "az", DV_DULL
112 };
113
114 u_int az_find(bus_space_tag_t, bus_space_handle_t);
115 void az_set_mute(struct az_softc *);
116 void az_set_freq(struct az_softc *, u_int32_t);
117 u_int8_t az_state(bus_space_tag_t, bus_space_handle_t);
118
119 void az_lm700x_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
120 void az_lm700x_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
121
122 u_int8_t az_conv_vol(u_int8_t);
123 u_int8_t az_unconv_vol(u_int8_t);
124
125 int
126 az_probe(struct device *parent, void *self, void *aux)
127 {
128 struct isa_attach_args *ia = aux;
129 bus_space_tag_t iot = ia->ia_iot;
130 bus_space_handle_t ioh;
131
132 int iosize = 1, iobase = ia->ia_iobase;
133
134 if (!AZ_BASE_VALID(iobase)) {
135 printf("az: configured iobase 0x%x invalid\n", iobase);
136 return (0);
137 }
138
139 if (bus_space_map(iot, iobase, iosize, 0, &ioh))
140 return (0);
141
142 if (!az_find(iot, ioh)) {
143 bus_space_unmap(iot, ioh, iosize);
144 return (0);
145 }
146
147 bus_space_unmap(iot, ioh, iosize);
148 ia->ia_iosize = iosize;
149 return (1);
150 }
151
152 void
153 az_attach(struct device *parent, struct device *self, void *aux)
154 {
155 struct az_softc *sc = (void *) self;
156 struct isa_attach_args *ia = aux;
157
158 sc->lm.iot = ia->ia_iot;
159 sc->rf = LM700X_REF_050;
160 sc->stereo = LM700X_STEREO;
161 sc->mute = 0;
162 sc->freq = MIN_FM_FREQ;
163 sc->vol = 0;
164
165
166 if (bus_space_map(sc->lm.iot, ia->ia_iobase, ia->ia_iosize,
167 0, &sc->lm.ioh)) {
168 printf(": bus_space_map() failed\n");
169 return;
170 }
171
172 printf(": Aztech/PackardBell\n");
173
174
175 sc->lm.offset = 0;
176 sc->lm.wzcl = AZ_WREN_ON | AZ_CLCK_OFF | AZ_DATA_OFF;
177 sc->lm.wzch = AZ_WREN_ON | AZ_CLCK_ON | AZ_DATA_OFF;
178 sc->lm.wocl = AZ_WREN_ON | AZ_CLCK_OFF | AZ_DATA_ON;
179 sc->lm.woch = AZ_WREN_ON | AZ_CLCK_ON | AZ_DATA_ON;
180 sc->lm.initdata = 0;
181 sc->lm.rsetdata = AZ_DATA_ON | AZ_CLCK_ON | AZ_WREN_OFF;
182 sc->lm.init = az_lm700x_init;
183 sc->lm.rset = az_lm700x_rset;
184
185 az_set_freq(sc, sc->freq);
186
187 radio_attach_mi(&az_hw_if, sc, &sc->sc_dev);
188 }
189
190
191
192
193 void
194 az_set_mute(struct az_softc *sc)
195 {
196 bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
197 sc->mute ? 0 : sc->vol);
198 DELAY(6);
199 bus_space_write_1(sc->lm.iot, sc->lm.ioh, 0,
200 sc->mute ? 0 : sc->vol);
201 }
202
203 void
204 az_set_freq(struct az_softc *sc, u_int32_t nfreq)
205 {
206 u_int8_t vol;
207 u_int32_t reg;
208
209 vol = sc->mute ? 0 : sc->vol;
210
211 if (nfreq > MAX_FM_FREQ)
212 nfreq = MAX_FM_FREQ;
213 if (nfreq < MIN_FM_FREQ)
214 nfreq = MIN_FM_FREQ;
215
216 sc->freq = nfreq;
217
218 reg = lm700x_encode_freq(nfreq, sc->rf);
219 reg |= sc->stereo | sc->rf | LM700X_DIVIDER_FM;
220
221 lm700x_hardware_write(&sc->lm, reg, vol);
222
223 az_set_mute(sc);
224 }
225
226
227
228
229 u_int8_t
230 az_state(bus_space_tag_t iot, bus_space_handle_t ioh)
231 {
232 u_int8_t info = 0, portdata;
233
234 portdata = bus_space_read_1(iot, ioh, 0);
235
236 info |= portdata & AZTECH_STEREO ? 0 : RADIO_INFO_STEREO;
237 info |= portdata & AZTECH_SIGNAL ? 0 : RADIO_INFO_SIGNAL;
238
239 return info;
240 }
241
242
243
244
245
246 u_int8_t
247 az_conv_vol(u_int8_t vol)
248 {
249 if (vol < VOLUME_RATIO(1))
250 return 0;
251 else if (vol >= VOLUME_RATIO(1) && vol < VOLUME_RATIO(2))
252 return 1;
253 else if (vol >= VOLUME_RATIO(2) && vol < VOLUME_RATIO(3))
254 return 4;
255 else
256 return 5;
257 }
258
259
260
261
262 u_int8_t
263 az_unconv_vol(u_int8_t vol)
264 {
265 switch (vol) {
266 case 0:
267 return VOLUME_RATIO(0);
268 case 1:
269 return VOLUME_RATIO(1);
270 case 4:
271 return VOLUME_RATIO(2);
272 }
273 return VOLUME_RATIO(3);
274 }
275
276 u_int
277 az_find(bus_space_tag_t iot, bus_space_handle_t ioh)
278 {
279 struct az_softc sc;
280 u_int i;
281
282 sc.lm.iot = iot;
283 sc.lm.ioh = ioh;
284 sc.lm.offset = 0;
285 sc.lm.wzcl = AZ_WREN_ON | AZ_CLCK_OFF | AZ_DATA_OFF;
286 sc.lm.wzch = AZ_WREN_ON | AZ_CLCK_ON | AZ_DATA_OFF;
287 sc.lm.wocl = AZ_WREN_ON | AZ_CLCK_OFF | AZ_DATA_ON;
288 sc.lm.woch = AZ_WREN_ON | AZ_CLCK_ON | AZ_DATA_ON;
289 sc.lm.initdata = 0;
290 sc.lm.rsetdata = AZ_DATA_ON | AZ_CLCK_ON | AZ_WREN_OFF;
291 sc.lm.init = az_lm700x_init;
292 sc.lm.rset = az_lm700x_rset;
293 sc.rf = LM700X_REF_050;
294 sc.mute = 0;
295 sc.stereo = LM700X_STEREO;
296 sc.vol = 0;
297
298
299
300
301
302 for (i = MIN_FM_FREQ; i < MAX_FM_FREQ; i += 10) {
303 az_set_freq(&sc, i);
304 if (az_state(iot, ioh))
305 return 1;
306 }
307
308 return 0;
309 }
310
311 void
312 az_lm700x_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
313 u_int32_t data)
314 {
315
316 return;
317 }
318
319 void
320 az_lm700x_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off,
321 u_int32_t data)
322 {
323 bus_space_write_1(iot, ioh, off, data);
324 }
325
326 int
327 az_get_info(void *v, struct radio_info *ri)
328 {
329 struct az_softc *sc = v;
330
331 ri->mute = sc->mute;
332 ri->volume = az_unconv_vol(sc->vol);
333 ri->stereo = sc->stereo == LM700X_STEREO ? 1 : 0;
334 ri->caps = AZTECH_CAPABILITIES;
335 ri->rfreq = lm700x_decode_ref(sc->rf);
336 ri->info = az_state(sc->lm.iot, sc->lm.ioh);
337 ri->freq = sc->freq;
338
339
340 ri->lock = 0;
341
342 return (0);
343 }
344
345 int
346 az_set_info(void *v, struct radio_info *ri)
347 {
348 struct az_softc *sc = v;
349
350 sc->mute = ri->mute ? 1 : 0;
351 sc->vol = az_conv_vol(ri->volume);
352 sc->stereo = ri->stereo ? LM700X_STEREO : LM700X_MONO;
353 sc->rf = lm700x_encode_ref(ri->rfreq);
354
355 az_set_freq(sc, ri->freq);
356 az_set_mute(sc);
357
358 return (0);
359 }