xref: /openbsd/sys/dev/pci/bktr/bktr_os.c (revision 404b540a)
1 /*	$OpenBSD: bktr_os.c,v 1.30 2009/03/29 21:53:53 sthen Exp $	*/
2 /* $FreeBSD: src/sys/dev/bktr/bktr_os.c,v 1.20 2000/10/20 08:16:53 roger Exp $ */
3 
4 /*
5  * This is part of the Driver for Video Capture Cards (Frame grabbers)
6  * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
7  * chipset.
8  * Copyright Roger Hardiman and Amancio Hasty.
9  *
10  * bktr_os : This has all the Operating System dependant code,
11  *             probe/attach and open/close/ioctl/read/mmap
12  *             memory allocation
13  *             PCI bus interfacing
14  *
15  *
16  */
17 
18 /*
19  * 1. Redistributions of source code must retain the
20  * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *	This product includes software developed by Amancio Hasty and
34  *      Roger Hardiman
35  * 4. The name of the author may not be used to endorse or promote products
36  *    derived from this software without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41  * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
47  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #define FIFO_RISC_DISABLED      0
52 #define ALL_INTS_DISABLED       0
53 
54 #include "radio.h"
55 
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/conf.h>
59 #include <sys/uio.h>
60 #include <sys/kernel.h>
61 #include <sys/signalvar.h>
62 #include <sys/mman.h>
63 #include <sys/poll.h>
64 #include <sys/selinfo.h>
65 #include <sys/vnode.h>
66 #if NRADIO > 0
67 #include <sys/radioio.h>
68 #include <dev/radio_if.h>
69 #endif
70 
71 #include <uvm/uvm_extern.h>
72 
73 #include <sys/device.h>
74 #include <dev/pci/pcivar.h>
75 #include <dev/pci/pcireg.h>
76 #include <dev/pci/pcidevs.h>
77 
78 #ifdef BKTR_DEBUG
79 int bktr_debug = 1;
80 #define DPR(x)	(bktr_debug ? printf x : 0)
81 #else
82 #define DPR(x)
83 #endif
84 
85 #include <dev/ic/bt8xx.h>	/* OpenBSD location for .h files */
86 #include <dev/pci/bktr/bktr_reg.h>
87 #include <dev/pci/bktr/bktr_tuner.h>
88 #include <dev/pci/bktr/bktr_card.h>
89 #include <dev/pci/bktr/bktr_audio.h>
90 #include <dev/pci/bktr/bktr_core.h>
91 #include <dev/pci/bktr/bktr_os.h>
92 
93 #define IPL_VIDEO       IPL_BIO         /* XXX */
94 
95 static	int		bktr_intr(void *arg) { return common_bktr_intr(arg); }
96 
97 #define bktr_open       bktropen
98 #define bktr_close      bktrclose
99 #define bktr_read       bktrread
100 #define bktr_write      bktrwrite
101 #define bktr_ioctl      bktrioctl
102 #define bktr_mmap       bktrmmap
103 
104 int	bktr_open(dev_t, int, int, struct proc *);
105 int	bktr_close(dev_t, int, int, struct proc *);
106 int	bktr_read(dev_t, struct uio *, int);
107 int	bktr_write(dev_t, struct uio *, int);
108 int	bktr_ioctl(dev_t, ioctl_cmd_t, caddr_t, int, struct proc *);
109 paddr_t	bktr_mmap(dev_t, off_t, int);
110 
111 static int      bktr_probe(struct device *, void *, void *);
112 static void     bktr_attach(struct device *, struct device *, void *);
113 
114 struct cfattach bktr_ca = {
115         sizeof(struct bktr_softc), bktr_probe, bktr_attach
116 };
117 
118 struct cfdriver bktr_cd = {
119         NULL, "bktr", DV_DULL
120 };
121 
122 #if NRADIO > 0
123 /* for radio(4) */
124 int	bktr_get_info(void *, struct radio_info *);
125 int	bktr_set_info(void *, struct radio_info *);
126 
127 struct radio_hw_if bktr_hw_if = {
128 	NULL,	/* open */
129 	NULL,	/* close */
130 	bktr_get_info,
131 	bktr_set_info,
132 	NULL	/* search */
133 };
134 #endif
135 
136 int
137 bktr_probe(parent, match, aux)
138 	struct device *parent;
139         void *match;
140         void *aux;
141 {
142         struct pci_attach_args *pa = aux;
143 
144         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
145             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
146              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
147              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
148              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
149                 return 1;
150 
151         return 0;
152 }
153 
154 
155 /*
156  * the attach routine.
157  */
158 static void
159 bktr_attach(struct device *parent, struct device *self, void *aux)
160 {
161 	bktr_ptr_t	bktr;
162 	u_int		latency;
163 	u_int		fun;
164 	unsigned int	rev;
165 	struct pci_attach_args *pa = aux;
166 	pci_intr_handle_t ih;
167 	const char *intrstr;
168 	int retval;
169 	int unit;
170 
171 	bktr = (bktr_ptr_t)self;
172 	unit = bktr->bktr_dev.dv_unit;
173         bktr->dmat = pa->pa_dmat;
174 
175 	/* Enable Back-to-Back
176 	   XXX: check if all old DMA is stopped first (e.g. after warm
177 	   boot) */
178 	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
179 	DPR((" fun=%b", fun, PCI_COMMAND_STATUS_BITS));
180 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
181 	    fun | PCI_COMMAND_BACKTOBACK_ENABLE);
182 
183 	/*
184 	 * map memory
185 	 */
186 	retval = pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM |
187 	    PCI_MAPREG_MEM_TYPE_32BIT, 0, &bktr->memt, &bktr->memh, NULL,
188 	    &bktr->obmemsz, 0);
189 	DPR(("pci_mapreg_map: memt %lx, memh %lx, size %x\n",
190 	     bktr->memt, bktr->memh, bktr->obmemsz));
191 	if (retval) {
192 		printf("%s: can't map mem space\n", bktr_name(bktr));
193 		return;
194 	}
195 
196 	/*
197 	 * Disable the brooktree device
198 	 */
199 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
200 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
201 
202 	/*
203 	 * map interrupt
204 	 */
205 	if (pci_intr_map(pa, &ih)) {
206 		printf("%s: can't map interrupt\n",
207 		       bktr_name(bktr));
208 		return;
209 	}
210 	intrstr = pci_intr_string(pa->pa_pc, ih);
211 	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
212 	    bktr_intr, bktr, bktr->bktr_dev.dv_xname);
213 	if (bktr->ih == NULL) {
214 		printf("%s: can't establish interrupt",
215 		       bktr_name(bktr));
216 		if (intrstr != NULL)
217 			printf(" at %s", intrstr);
218 		printf("\n");
219 		return;
220 	}
221 	if (intrstr != NULL)
222 		printf(": %s\n", intrstr);
223 
224 /*
225  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
226  * you have more than four, then 16 would probably be a better value.
227  */
228 #ifndef BROOKTREE_DEF_LATENCY_VALUE
229 #define BROOKTREE_DEF_LATENCY_VALUE	0x10
230 #endif
231 	latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
232 	latency = (latency >> 8) & 0xff;
233 
234 	if (!latency) {
235 		if (bootverbose) {
236 			printf("%s: PCI bus latency was 0 changing to %d",
237 			       bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
238 		}
239 		latency = BROOKTREE_DEF_LATENCY_VALUE;
240 		pci_conf_write(pa->pa_pc, pa->pa_tag,
241 			       PCI_LATENCY_TIMER, latency<<8);
242 	}
243 
244 
245 	/* read the pci id and determine the card type */
246 	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
247         rev = PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG));
248 
249 	common_bktr_attach(bktr, unit, fun, rev);
250 
251 #if NRADIO > 0
252 	if (bktr->card.tuner->pllControl[3] != 0x00)
253 		radio_attach_mi(&bktr_hw_if, bktr, &bktr->bktr_dev);
254 #endif
255 }
256 
257 
258 /*
259  * Special Memory Allocation
260  */
261 vaddr_t
262 get_bktr_mem(bktr, dmapp, size)
263         bktr_ptr_t bktr;
264         bus_dmamap_t *dmapp;
265         unsigned int size;
266 {
267         bus_dma_tag_t dmat = bktr->dmat;
268         bus_dma_segment_t seg;
269         bus_size_t align;
270         int rseg;
271         caddr_t kva;
272 
273         /*
274          * Allocate a DMA area
275          */
276         align = 1 << 24;
277         if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
278                              &rseg, BUS_DMA_NOWAIT)) {
279                 align = PAGE_SIZE;
280                 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
281                                      &rseg, BUS_DMA_NOWAIT)) {
282                         printf("%s: Unable to dmamem_alloc of %d bytes\n",
283 			       bktr_name(bktr), size);
284                         return 0;
285                 }
286         }
287         if (bus_dmamem_map(dmat, &seg, rseg, size,
288                            &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
289                 printf("%s: Unable to dmamem_map of %d bytes\n",
290                         bktr_name(bktr), size);
291                 bus_dmamem_free(dmat, &seg, rseg);
292                 return 0;
293         }
294         /*
295          * Create and locd the DMA map for the DMA area
296          */
297         if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
298                 printf("%s: Unable to dmamap_create of %d bytes\n",
299                         bktr_name(bktr), size);
300                 bus_dmamem_unmap(dmat, kva, size);
301                 bus_dmamem_free(dmat, &seg, rseg);
302                 return 0;
303         }
304         if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
305                 printf("%s: Unable to dmamap_load of %d bytes\n",
306                         bktr_name(bktr), size);
307                 bus_dmamem_unmap(dmat, kva, size);
308                 bus_dmamem_free(dmat, &seg, rseg);
309                 bus_dmamap_destroy(dmat, *dmapp);
310                 return 0;
311         }
312         return (vaddr_t)kva;
313 }
314 
315 void
316 free_bktr_mem(bktr, dmap, kva)
317         bktr_ptr_t bktr;
318         bus_dmamap_t dmap;
319         vaddr_t kva;
320 {
321         bus_dma_tag_t dmat = bktr->dmat;
322 
323         bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
324         bus_dmamem_free(dmat, dmap->dm_segs, 1);
325         bus_dmamap_destroy(dmat, dmap);
326 }
327 
328 
329 /*---------------------------------------------------------
330 **
331 **	BrookTree 848 character device driver routines
332 **
333 **---------------------------------------------------------
334 */
335 
336 
337 #define VIDEO_DEV	0x00
338 #define TUNER_DEV	0x01
339 #define VBI_DEV		0x02
340 
341 #define UNIT(x)         (minor((x) & 0x0f))
342 #define FUNCTION(x)     (minor((x >> 4) & 0x0f))
343 
344 /*
345  *
346  */
347 int
348 bktr_open(dev_t dev, int flags, int fmt, struct proc *p)
349 {
350 	bktr_ptr_t	bktr;
351 	int		unit;
352 
353 	unit = UNIT(dev);
354 
355 	/* unit out of range */
356 	if ((unit >= bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
357 		return(ENXIO);
358 
359 	bktr = bktr_cd.cd_devs[unit];
360 
361 	if (!(bktr->flags & METEOR_INITIALIZED)) /* device not found */
362 		return(ENXIO);
363 
364 	switch (FUNCTION(dev)) {
365 	case VIDEO_DEV:
366 		return(video_open(bktr));
367 	case TUNER_DEV:
368 		return(tuner_open(bktr));
369 	case VBI_DEV:
370 		return(vbi_open(bktr));
371 	}
372 
373 	return(ENXIO);
374 }
375 
376 
377 /*
378  *
379  */
380 int
381 bktr_close(dev_t dev, int flags, int fmt, struct proc *p)
382 {
383 	bktr_ptr_t	bktr;
384 	int		unit;
385 
386 	unit = UNIT(dev);
387 
388 	bktr = bktr_cd.cd_devs[unit];
389 
390 	switch (FUNCTION(dev)) {
391 	case VIDEO_DEV:
392 		return(video_close(bktr));
393 	case TUNER_DEV:
394 		return(tuner_close(bktr));
395 	case VBI_DEV:
396 		return(vbi_close(bktr));
397 	}
398 
399 	return(ENXIO);
400 }
401 
402 /*
403  *
404  */
405 int
406 bktr_read(dev_t dev, struct uio *uio, int ioflag)
407 {
408 	bktr_ptr_t	bktr;
409 	int		unit;
410 
411 	unit = UNIT(dev);
412 
413 	bktr = bktr_cd.cd_devs[unit];
414 
415 	switch (FUNCTION(dev)) {
416 	case VIDEO_DEV:
417 		return(video_read(bktr, unit, dev, uio));
418 	case VBI_DEV:
419 		return(vbi_read(bktr, uio, ioflag));
420 	}
421 
422         return(ENXIO);
423 }
424 
425 
426 /*
427  *
428  */
429 int
430 bktr_write(dev_t dev, struct uio *uio, int ioflag)
431 {
432 	/* operation not supported */
433 	return(EOPNOTSUPP);
434 }
435 
436 /*
437  *
438  */
439 int
440 bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr)
441 {
442 	bktr_ptr_t	bktr;
443 	int		unit;
444 
445 	unit = UNIT(dev);
446 
447 	bktr = bktr_cd.cd_devs[unit];
448 
449 	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
450 		return(ENOMEM);
451 
452 	switch (FUNCTION(dev)) {
453 	case VIDEO_DEV:
454 		return(video_ioctl(bktr, unit, cmd, arg, pr));
455 	case TUNER_DEV:
456 		return(tuner_ioctl(bktr, unit, cmd, arg, pr));
457 	}
458 
459 	return(ENXIO);
460 }
461 
462 /*
463  *
464  */
465 paddr_t
466 bktr_mmap(dev_t dev, off_t offset, int nprot)
467 {
468 	int		unit;
469 	bktr_ptr_t	bktr;
470 
471 	unit = UNIT(dev);
472 
473 	if (FUNCTION(dev) > 0)	/* only allow mmap on /dev/bktr[n] */
474 		return(-1);
475 
476 	bktr = bktr_cd.cd_devs[unit];
477 
478 	if ((vaddr_t)offset < 0)
479 		return(-1);
480 
481 	if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
482 		return(-1);
483 
484 	return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
485 				(vaddr_t)offset, nprot, BUS_DMA_WAITOK));
486 }
487 
488 #if NRADIO > 0
489 int
490 bktr_set_info(void *v, struct radio_info *ri)
491 {
492 	struct bktr_softc *sc = v;
493 	struct TVTUNER *tv = &sc->tuner;
494 	u_int32_t freq;
495 	u_int32_t chan;
496 
497 	if (ri->mute) {
498 		/* mute the audio stream by switching the mux */
499 		set_audio(sc, AUDIO_MUTE);
500 	} else {
501 		/* unmute the audio stream */
502 		set_audio(sc, AUDIO_UNMUTE);
503 		init_audio_devices(sc);
504 	}
505 
506 	set_audio(sc, AUDIO_INTERN);	/* use internal audio */
507 	temp_mute(sc, TRUE);
508 
509 	if (ri->tuner_mode == RADIO_TUNER_MODE_TV) {
510 		if (ri->chan) {
511 			if (ri->chan < MIN_TV_CHAN)
512 				ri->chan = MIN_TV_CHAN;
513 			if (ri->chan > MAX_TV_CHAN)
514 				ri->chan = MAX_TV_CHAN;
515 
516 			chan = ri->chan;
517 			ri->chan = tv_channel(sc, chan);
518 			tv->tuner_mode = BT848_TUNER_MODE_TV;
519 		} else {
520 			ri->chan = tv->channel;
521 		}
522 	} else {
523 		if (ri->freq) {
524 			if (ri->freq < MIN_FM_FREQ)
525 				ri->freq = MIN_FM_FREQ;
526 			if (ri->freq > MAX_FM_FREQ)
527 				ri->freq = MAX_FM_FREQ;
528 
529 			freq = ri->freq / 10;
530 			ri->freq = tv_freq(sc, freq, FM_RADIO_FREQUENCY) * 10;
531 			tv->tuner_mode = BT848_TUNER_MODE_RADIO;
532 		} else {
533 			ri->freq = tv->frequency;
534 		}
535 	}
536 
537 	if (ri->chnlset >= CHNLSET_MIN && ri->chnlset <= CHNLSET_MAX)
538 		tv->chnlset = ri->chnlset;
539 	else
540 		tv->chnlset = DEFAULT_CHNLSET;
541 
542 	temp_mute(sc, FALSE);
543 
544 	return (0);
545 }
546 
547 int
548 bktr_get_info(void *v, struct radio_info *ri)
549 {
550 	struct bktr_softc *sc = v;
551 	struct TVTUNER *tv = &sc->tuner;
552 	int status;
553 
554 	status = get_tuner_status(sc);
555 
556 #define	STATUSBIT_STEREO	0x10
557 	ri->mute = (int)sc->audio_mute_state ? 1 : 0;
558 	ri->caps = RADIO_CAPS_DETECT_STEREO | RADIO_CAPS_HW_AFC;
559 	ri->info = (status & STATUSBIT_STEREO) ? RADIO_INFO_STEREO : 0;
560 
561 	/* not yet supported */
562 	ri->volume = ri->rfreq = ri->lock = 0;
563 
564 	switch (tv->tuner_mode) {
565 	case BT848_TUNER_MODE_TV:
566 		ri->tuner_mode = RADIO_TUNER_MODE_TV;
567 		ri->freq = tv->frequency * 1000 / 16;
568 		break;
569 	case BT848_TUNER_MODE_RADIO:
570 		ri->tuner_mode = RADIO_TUNER_MODE_RADIO;
571 		ri->freq = tv->frequency * 10;
572 		break;
573 	}
574 
575 	/*
576 	 * The field ri->stereo is used to forcible switch to
577 	 * mono/stereo, not as an indicator of received signal quality.
578 	 * The ri->info is for that purpose.
579 	 */
580 	ri->stereo = 1; /* Can't switch to mono, always stereo */
581 
582 	ri->chan = tv->channel;
583 	ri->chnlset = tv->chnlset;
584 
585 	return (0);
586 }
587 #endif /* NRADIO */
588