This source file includes following definitions.
- fmsradio_attach
- sf256pcs_probe
- sf256pcs_hw_read
- sf256pcs_write_bit
- sf256pcs_init
- sf256pcs_rset
- sf256pcpr_probe
- sf256pcpr_hw_read
- sf256pcpr_write_bit
- sf256pcpr_init
- sf256pcpr_rset
- sf64pcr_probe
- sf64pcr_hw_read
- sf64pcr_write_bit
- sf64pcr_init
- sf64pcr_rset
- fmsradio_set_mute
- fmsradio_get_info
- fmsradio_set_info
- fmsradio_search
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 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/device.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/audioio.h>
44 #include <sys/radioio.h>
45
46 #include <machine/bus.h>
47
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
51
52 #include <dev/audio_if.h>
53 #include <dev/radio_if.h>
54
55 #include <dev/ic/ac97.h>
56
57 #include <dev/pci/fmsreg.h>
58 #include <dev/pci/fmsvar.h>
59
60 #include <dev/ic/tea5757.h>
61
62 #define TUNER_UNKNOWN 0
63 #define TUNER_SF256PCPR 1
64 #define TUNER_SF64PCR 2
65 #define TUNER_SF256PCS 3
66
67 #define SF64PCR_CAPS RADIO_CAPS_DETECT_STEREO | \
68 RADIO_CAPS_DETECT_SIGNAL | \
69 RADIO_CAPS_SET_MONO | \
70 RADIO_CAPS_HW_SEARCH | \
71 RADIO_CAPS_HW_AFC | \
72 RADIO_CAPS_LOCK_SENSITIVITY
73
74 #define SF256PCPR_CAPS RADIO_CAPS_DETECT_STEREO | \
75 RADIO_CAPS_SET_MONO | \
76 RADIO_CAPS_HW_SEARCH | \
77 RADIO_CAPS_HW_AFC | \
78 RADIO_CAPS_LOCK_SENSITIVITY
79
80 #define SF256PCS_CAPS RADIO_CAPS_SET_MONO | \
81 RADIO_CAPS_HW_SEARCH | \
82 RADIO_CAPS_HW_AFC | \
83 RADIO_CAPS_LOCK_SENSITIVITY
84
85 #define PCR_WREN_ON 0
86 #define PCR_WREN_OFF FM_IO_PIN1
87 #define PCR_CLOCK_ON FM_IO_PIN0
88 #define PCR_CLOCK_OFF 0
89 #define PCR_DATA_ON FM_IO_PIN2
90 #define PCR_DATA_OFF 0
91
92 #define PCR_SIGNAL 0x80
93 #define PCR_STEREO 0x80
94 #define PCR_INFO_SIGNAL (1 << 24)
95 #define PCR_INFO_STEREO (1 << 25)
96
97 #define PCPR_WREN_ON 0
98 #define PCPR_WREN_OFF FM_IO_PIN2
99 #define PCPR_CLOCK_ON FM_IO_PIN0
100 #define PCPR_CLOCK_OFF 0
101 #define PCPR_DATA_ON FM_IO_PIN1
102 #define PCPR_DATA_OFF 0
103 #define PCPR_INFO_STEREO 0x04
104
105 #define PCS_WREN_ON 0
106 #define PCS_WREN_OFF FM_IO_PIN2
107 #define PCS_CLOCK_ON FM_IO_PIN3
108 #define PCS_CLOCK_OFF 0
109 #define PCS_DATA_ON FM_IO_PIN1
110 #define PCS_DATA_OFF 0
111
112
113
114
115 void fmsradio_set_mute(struct fms_softc *);
116
117 void sf64pcr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
118 void sf64pcr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
119 void sf64pcr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
120 u_int32_t sf64pcr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
121 int sf64pcr_probe(struct fms_softc *);
122
123 void sf256pcpr_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
124 void sf256pcpr_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
125 void sf256pcpr_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
126 u_int32_t sf256pcpr_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
127 int sf256pcpr_probe(struct fms_softc *);
128
129 void sf256pcs_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
130 void sf256pcs_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
131 void sf256pcs_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
132 u_int32_t sf256pcs_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
133 int sf256pcs_probe(struct fms_softc *);
134
135 int fmsradio_get_info(void *, struct radio_info *);
136 int fmsradio_set_info(void *, struct radio_info *);
137 int fmsradio_search(void *, int);
138
139 struct radio_hw_if fmsradio_hw_if = {
140 NULL,
141 NULL,
142 fmsradio_get_info,
143 fmsradio_set_info,
144 fmsradio_search
145 };
146
147 struct fmsradio_if {
148 int type;
149
150 int mute;
151 u_int8_t vol;
152 u_int32_t freq;
153 u_int32_t stereo;
154 u_int32_t lock;
155
156 struct tea5757_t tea;
157 };
158
159 int
160 fmsradio_attach(struct fms_softc *sc)
161 {
162 struct fmsradio_if *r;
163
164 r = malloc(sizeof(struct fmsradio_if), M_DEVBUF, M_NOWAIT);
165 if (r == NULL) {
166 printf("%s: cannot allocate memory for FM tuner config\n",
167 sc->sc_dev.dv_xname);
168 return TUNER_UNKNOWN;
169 }
170
171 sc->radio = r;
172 r->tea.iot = sc->sc_iot;
173 r->tea.ioh = sc->sc_ioh;
174 r->tea.offset = FM_IO_CTL;
175 r->tea.flags = sc->sc_dev.dv_cfdata->cf_flags;
176 r->vol = 0;
177 r->mute = 0;
178 r->freq = MIN_FM_FREQ;
179 r->stereo = TEA5757_STEREO;
180 r->lock = TEA5757_S030;
181
182 r->type = TUNER_UNKNOWN;
183 if ((r->type = sf64pcr_probe(sc)) == TUNER_SF64PCR)
184 printf("%s: SF64-PCR FM Radio\n", sc->sc_dev.dv_xname);
185 else if ((r->type = sf256pcpr_probe(sc)) == TUNER_SF256PCPR)
186 printf("%s: SF256-PCP-R FM Radio\n", sc->sc_dev.dv_xname);
187 else if ((r->type = sf256pcs_probe(sc)) == TUNER_SF256PCS)
188 printf("%s: SF256-PCS-R FM Radio\n", sc->sc_dev.dv_xname);
189 else
190 return TUNER_UNKNOWN;
191
192 fmsradio_set_mute(sc);
193 radio_attach_mi(&fmsradio_hw_if, sc, &sc->sc_dev);
194 return r->type;
195 }
196
197
198 int
199 sf256pcs_probe(struct fms_softc *sc)
200 {
201 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
202 u_int32_t freq;
203
204 radio->tea.init = sf256pcs_init;
205 radio->tea.rset = sf256pcs_rset;
206 radio->tea.write_bit = sf256pcs_write_bit;
207 radio->tea.read = sf256pcs_hw_read;
208
209 tea5757_set_freq(&radio->tea, radio->stereo,
210 radio->lock, radio->freq);
211 freq = tea5757_decode_freq(sf256pcs_hw_read(radio->tea.iot,
212 radio->tea.ioh, radio->tea.offset),
213 radio->tea.flags & TEA5757_TEA5759);
214 if (freq != radio->freq)
215 return TUNER_UNKNOWN;
216
217 return TUNER_SF256PCS;
218 }
219
220 u_int32_t
221 sf256pcs_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
222 {
223 u_int32_t res = 0ul;
224 u_int16_t i, d;
225
226 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3) | PCS_WREN_OFF;
227
228
229 d |= FM_IO_GPIO_IN(PCS_DATA_ON) | PCS_DATA_ON;
230
231 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF);
232
233
234 i = 24;
235 while (i--) {
236 res <<= 1;
237 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_ON);
238 bus_space_write_2(iot, ioh, offset, d | PCS_CLOCK_OFF);
239 res |= bus_space_read_2(iot, ioh, offset) &
240 PCS_DATA_ON ? 1 : 0;
241 }
242
243 return (res & (TEA5757_DATA | TEA5757_FREQ));
244 }
245
246 void
247 sf256pcs_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
248 bus_size_t off, int bit)
249 {
250 u_int16_t data, wren;
251
252 wren = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
253 wren |= PCS_WREN_ON;
254 data = bit ? PCPR_DATA_ON : PCS_DATA_OFF;
255
256 bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data);
257 bus_space_write_2(iot, ioh, off, PCS_CLOCK_ON | wren | data);
258 bus_space_write_2(iot, ioh, off, PCS_CLOCK_OFF | wren | data);
259 }
260
261 void
262 sf256pcs_init(bus_space_tag_t iot, bus_space_handle_t ioh,
263 bus_size_t offset, u_int32_t d)
264 {
265 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
266 d |= PCS_WREN_ON | PCS_DATA_OFF | PCS_CLOCK_OFF;
267
268 bus_space_write_2(iot, ioh, offset, d);
269 bus_space_write_2(iot, ioh, offset, d);
270 }
271
272 void
273 sf256pcs_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
274 bus_size_t offset, u_int32_t d)
275 {
276 d = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
277 d |= PCS_WREN_OFF | PCS_DATA_OFF | PCS_CLOCK_OFF;
278
279 bus_space_write_2(iot, ioh, offset, d);
280 bus_space_write_2(iot, ioh, offset, d);
281 }
282
283
284 int
285 sf256pcpr_probe(struct fms_softc *sc)
286 {
287 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
288 u_int32_t freq;
289
290 radio->tea.init = sf256pcpr_init;
291 radio->tea.rset = sf256pcpr_rset;
292 radio->tea.write_bit = sf256pcpr_write_bit;
293 radio->tea.read = sf256pcpr_hw_read;
294
295 tea5757_set_freq(&radio->tea, radio->stereo,
296 radio->lock, radio->freq);
297 freq = tea5757_decode_freq(sf256pcpr_hw_read(radio->tea.iot,
298 radio->tea.ioh, radio->tea.offset),
299 radio->tea.flags & TEA5757_TEA5759);
300 if (freq != radio->freq)
301 return TUNER_UNKNOWN;
302
303 return TUNER_SF256PCPR;
304 }
305
306 u_int32_t
307 sf256pcpr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh,
308 bus_size_t offset)
309 {
310 u_int32_t res = 0ul;
311 u_int16_t i, d;
312
313 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCPR_DATA_ON | FM_IO_PIN3);
314
315
316 d |= PCPR_WREN_OFF | PCPR_DATA_ON;
317
318 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF);
319
320
321 i = 24;
322 while (i--) {
323 res <<= 1;
324 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_ON);
325 bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF);
326 res |= bus_space_read_2(iot, ioh, offset) &
327 PCPR_DATA_ON ? 1 : 0;
328 }
329
330 return (res & (TEA5757_DATA | TEA5757_FREQ));
331 }
332
333 void
334 sf256pcpr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
335 bus_size_t off, int bit)
336 {
337 u_int16_t data, wren;
338
339 wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCPR_WREN_ON;
340 data = bit ? PCPR_DATA_ON : PCPR_DATA_OFF;
341
342 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data);
343 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_ON | wren | data);
344 bus_space_write_2(iot, ioh, off, PCPR_CLOCK_OFF | wren | data);
345 }
346
347 void
348 sf256pcpr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
349 bus_size_t offset, u_int32_t d)
350 {
351 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
352 d |= PCPR_WREN_ON | PCPR_DATA_OFF | PCPR_CLOCK_OFF;
353
354 bus_space_write_2(iot, ioh, offset, d);
355 bus_space_write_2(iot, ioh, offset, d);
356 }
357
358 void
359 sf256pcpr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
360 bus_size_t offset, u_int32_t d)
361 {
362 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
363 d |= PCPR_WREN_OFF | PCPR_DATA_OFF | PCPR_CLOCK_OFF;
364
365 bus_space_write_2(iot, ioh, offset, d);
366 bus_space_write_2(iot, ioh, offset, d);
367 }
368
369
370 int
371 sf64pcr_probe(struct fms_softc *sc)
372 {
373 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
374 u_int32_t freq;
375
376 radio->tea.init = sf64pcr_init;
377 radio->tea.rset = sf64pcr_rset;
378 radio->tea.write_bit = sf64pcr_write_bit;
379 radio->tea.read = sf64pcr_hw_read;
380
381 tea5757_set_freq(&radio->tea, radio->stereo,
382 radio->lock, radio->freq);
383 freq = tea5757_decode_freq(sf64pcr_hw_read(radio->tea.iot,
384 radio->tea.ioh, radio->tea.offset),
385 radio->tea.flags & TEA5757_TEA5759);
386 if (freq != radio->freq)
387 return TUNER_UNKNOWN;
388
389 return TUNER_SF64PCR;
390 }
391
392 u_int32_t
393 sf64pcr_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t offset)
394 {
395 u_int32_t res = 0ul;
396 u_int16_t d, i, ind = 0;
397
398 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(PCR_DATA_ON | FM_IO_PIN3);
399
400
401 d |= PCR_WREN_OFF | PCR_DATA_ON;
402
403 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
404 DELAY(4);
405
406
407 i = 23;
408 while (i--) {
409 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON);
410 DELAY(4);
411
412 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
413 DELAY(4);
414
415 res |= bus_space_read_2(iot, ioh, offset) & PCR_DATA_ON ? 1 : 0;
416 res <<= 1;
417 }
418
419 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_ON);
420 DELAY(4);
421
422 i = bus_space_read_1(iot, ioh, offset);
423 ind = i & PCR_SIGNAL ? (1 << 1) : (0 << 1);
424
425 bus_space_write_2(iot, ioh, offset, d | PCR_CLOCK_OFF);
426
427 i = bus_space_read_2(iot, ioh, offset);
428 ind |= i & PCR_STEREO ? (1 << 0) : (0 << 0);
429 res |= i & PCR_DATA_ON ? (1 << 0) : (0 << 0);
430
431 return (res & (TEA5757_DATA | TEA5757_FREQ)) | (ind << 24);
432 }
433
434 void
435 sf64pcr_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh,
436 bus_size_t off, int bit)
437 {
438 u_int16_t data, wren;
439
440 wren = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3) | PCR_WREN_ON;
441 data = bit ? PCR_DATA_ON : PCR_DATA_OFF;
442
443 bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data);
444 DELAY(4);
445 bus_space_write_2(iot, ioh, off, PCR_CLOCK_ON | wren | data);
446 DELAY(4);
447 bus_space_write_2(iot, ioh, off, PCR_CLOCK_OFF | wren | data);
448 DELAY(4);
449 }
450
451 void
452 sf64pcr_init(bus_space_tag_t iot, bus_space_handle_t ioh,
453 bus_size_t offset, u_int32_t d)
454 {
455 d = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
456 d |= PCR_WREN_ON | PCR_DATA_ON | PCR_CLOCK_OFF;
457
458 bus_space_write_2(iot, ioh, offset, d);
459 DELAY(4);
460 }
461
462 void
463 sf64pcr_rset(bus_space_tag_t iot, bus_space_handle_t ioh,
464 bus_size_t offset, u_int32_t d)
465 {
466
467 return;
468 }
469
470
471
472
473
474
475 void
476 fmsradio_set_mute(struct fms_softc *sc)
477 {
478 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
479 u_int16_t v, mute, unmute;
480
481 switch (radio->type) {
482 case TUNER_SF256PCS:
483 mute = FM_IO_GPIO(FM_IO_PIN1 | FM_IO_PIN2 | FM_IO_PIN3);
484 unmute = mute | PCS_WREN_OFF;
485 break;
486 case TUNER_SF256PCPR:
487 mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
488 unmute = mute | PCPR_WREN_OFF;
489 break;
490 case TUNER_SF64PCR:
491 mute = FM_IO_GPIO_ALL | FM_IO_GPIO_IN(FM_IO_PIN3);
492 unmute = mute | PCR_WREN_OFF;
493 break;
494 default:
495 return;
496 }
497 v = (radio->mute || !radio->vol) ? mute : unmute;
498 bus_space_write_2(radio->tea.iot, radio->tea.ioh,
499 radio->tea.offset, v);
500 DELAY(64);
501 bus_space_write_2(radio->tea.iot, radio->tea.ioh,
502 radio->tea.offset, v);
503 }
504
505 int
506 fmsradio_get_info(void *v, struct radio_info *ri)
507 {
508 struct fms_softc *sc = v;
509 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
510 u_int32_t buf;
511
512 ri->mute = radio->mute;
513 ri->volume = radio->vol ? 255 : 0;
514 ri->stereo = radio->stereo == TEA5757_STEREO ? 1 : 0;
515 ri->lock = tea5757_decode_lock(radio->lock);
516
517 switch (radio->type) {
518 case TUNER_SF256PCS:
519 ri->caps = SF256PCS_CAPS;
520 buf = sf256pcs_hw_read(radio->tea.iot, radio->tea.ioh,
521 radio->tea.offset);
522 ri->info = 0;
523 break;
524 case TUNER_SF256PCPR:
525 ri->caps = SF256PCPR_CAPS;
526 buf = sf256pcpr_hw_read(radio->tea.iot, radio->tea.ioh,
527 radio->tea.offset);
528 ri->info = bus_space_read_2(radio->tea.iot, radio->tea.ioh,
529 FM_VOLUME) == PCPR_INFO_STEREO ?
530 RADIO_INFO_STEREO : 0;
531 break;
532 case TUNER_SF64PCR:
533 ri->caps = SF64PCR_CAPS;
534 buf = sf64pcr_hw_read(radio->tea.iot, radio->tea.ioh,
535 radio->tea.offset);
536 ri->info = buf & PCR_INFO_SIGNAL ? 0 : RADIO_INFO_SIGNAL;
537 ri->info |= buf & PCR_INFO_STEREO ? 0 : RADIO_INFO_STEREO;
538 break;
539 default:
540 break;
541 }
542
543 ri->freq = radio->freq = tea5757_decode_freq(buf,
544 sc->sc_dev.dv_cfdata->cf_flags & TEA5757_TEA5759);
545
546 fmsradio_set_mute(sc);
547
548
549 ri->rfreq = 0;
550
551 return (0);
552 }
553
554 int
555 fmsradio_set_info(void *v, struct radio_info *ri)
556 {
557 struct fms_softc *sc = v;
558 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
559
560 radio->mute = ri->mute ? 1 : 0;
561 radio->vol = ri->volume ? 255 : 0;
562 radio->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
563 radio->lock = tea5757_encode_lock(ri->lock);
564 ri->freq = radio->freq = tea5757_set_freq(&radio->tea,
565 radio->lock, radio->stereo, ri->freq);
566 fmsradio_set_mute(sc);
567
568 return (0);
569 }
570
571 int
572 fmsradio_search(void *v, int f)
573 {
574 struct fms_softc *sc = v;
575 struct fmsradio_if *radio = (struct fmsradio_if *)sc->radio;
576
577 tea5757_search(&radio->tea, radio->lock,
578 radio->stereo, f);
579 fmsradio_set_mute(sc);
580
581 return (0);
582 }