xref: /openbsd/sys/dev/pci/bktr/bktr_os.c (revision d89ec533)
1 /*	$OpenBSD: bktr_os.c,v 1.34 2021/03/05 12:40:14 jsg 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_audio.h>
89 #include <dev/pci/bktr/bktr_core.h>
90 #include <dev/pci/bktr/bktr_os.h>
91 
92 #define IPL_VIDEO       IPL_BIO         /* XXX */
93 
94 static	int		bktr_intr(void *arg) { return common_bktr_intr(arg); }
95 
96 #define bktr_open       bktropen
97 #define bktr_close      bktrclose
98 #define bktr_read       bktrread
99 #define bktr_write      bktrwrite
100 #define bktr_ioctl      bktrioctl
101 #define bktr_mmap       bktrmmap
102 
103 int	bktr_open(dev_t, int, int, struct proc *);
104 int	bktr_close(dev_t, int, int, struct proc *);
105 int	bktr_read(dev_t, struct uio *, int);
106 int	bktr_write(dev_t, struct uio *, int);
107 int	bktr_ioctl(dev_t, ioctl_cmd_t, caddr_t, int, struct proc *);
108 paddr_t	bktr_mmap(dev_t, off_t, int);
109 
110 static int      bktr_probe(struct device *, void *, void *);
111 static void     bktr_attach(struct device *, struct device *, void *);
112 
113 struct cfattach bktr_ca = {
114         sizeof(struct bktr_softc), bktr_probe, bktr_attach
115 };
116 
117 struct cfdriver bktr_cd = {
118         NULL, "bktr", DV_DULL
119 };
120 
121 #if NRADIO > 0
122 /* for radio(4) */
123 int	bktr_get_info(void *, struct radio_info *);
124 int	bktr_set_info(void *, struct radio_info *);
125 
126 struct radio_hw_if bktr_hw_if = {
127 	NULL,	/* open */
128 	NULL,	/* close */
129 	bktr_get_info,
130 	bktr_set_info,
131 	NULL	/* search */
132 };
133 #endif
134 
135 int
136 bktr_probe(struct device *parent, void *match, void *aux)
137 {
138         struct pci_attach_args *pa = aux;
139 
140         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
141             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
142              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
143              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
144              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
145                 return 1;
146 
147         return 0;
148 }
149 
150 
151 /*
152  * the attach routine.
153  */
154 static void
155 bktr_attach(struct device *parent, struct device *self, void *aux)
156 {
157 	bktr_ptr_t	bktr;
158 	u_int		latency;
159 	u_int		fun;
160 	unsigned int	rev;
161 	struct pci_attach_args *pa = aux;
162 	pci_intr_handle_t ih;
163 	const char *intrstr;
164 	int retval;
165 	int unit;
166 
167 	bktr = (bktr_ptr_t)self;
168 	unit = bktr->bktr_dev.dv_unit;
169         bktr->dmat = pa->pa_dmat;
170 
171 	/* Enable Back-to-Back
172 	   XXX: check if all old DMA is stopped first (e.g. after warm
173 	   boot) */
174 	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
175 	DPR((" fun=%b", fun, PCI_COMMAND_STATUS_BITS));
176 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
177 	    fun | PCI_COMMAND_BACKTOBACK_ENABLE);
178 
179 	/*
180 	 * map memory
181 	 */
182 	retval = pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM |
183 	    PCI_MAPREG_MEM_TYPE_32BIT, 0, &bktr->memt, &bktr->memh, NULL,
184 	    &bktr->obmemsz, 0);
185 	DPR(("pci_mapreg_map: memt %lx, memh %lx, size %x\n",
186 	     bktr->memt, bktr->memh, bktr->obmemsz));
187 	if (retval) {
188 		printf("%s: can't map mem space\n", bktr_name(bktr));
189 		return;
190 	}
191 
192 	/*
193 	 * Disable the brooktree device
194 	 */
195 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
196 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
197 
198 	/*
199 	 * map interrupt
200 	 */
201 	if (pci_intr_map(pa, &ih)) {
202 		printf("%s: can't map interrupt\n",
203 		       bktr_name(bktr));
204 		return;
205 	}
206 	intrstr = pci_intr_string(pa->pa_pc, ih);
207 	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
208 	    bktr_intr, bktr, bktr->bktr_dev.dv_xname);
209 	if (bktr->ih == NULL) {
210 		printf("%s: can't establish interrupt",
211 		       bktr_name(bktr));
212 		if (intrstr != NULL)
213 			printf(" at %s", intrstr);
214 		printf("\n");
215 		return;
216 	}
217 	if (intrstr != NULL)
218 		printf(": %s\n", intrstr);
219 
220 /*
221  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
222  * you have more than four, then 16 would probably be a better value.
223  */
224 #ifndef BROOKTREE_DEF_LATENCY_VALUE
225 #define BROOKTREE_DEF_LATENCY_VALUE	0x10
226 #endif
227 	latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
228 	latency = (latency >> 8) & 0xff;
229 
230 	if (!latency) {
231 		if (bootverbose) {
232 			printf("%s: PCI bus latency was 0 changing to %d",
233 			       bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
234 		}
235 		latency = BROOKTREE_DEF_LATENCY_VALUE;
236 		pci_conf_write(pa->pa_pc, pa->pa_tag,
237 			       PCI_LATENCY_TIMER, latency<<8);
238 	}
239 
240 
241 	/* read the pci id and determine the card type */
242 	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
243         rev = PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG));
244 
245 	common_bktr_attach(bktr, unit, fun, rev);
246 
247 #if NRADIO > 0
248 	if (bktr->card.tuner->pllControl[3] != 0x00)
249 		radio_attach_mi(&bktr_hw_if, bktr, &bktr->bktr_dev);
250 #endif
251 }
252 
253 
254 /*
255  * Special Memory Allocation
256  */
257 vaddr_t
258 get_bktr_mem(bktr_ptr_t bktr, bus_dmamap_t *dmapp, unsigned int size)
259 {
260         bus_dma_tag_t dmat = bktr->dmat;
261         bus_dma_segment_t seg;
262         bus_size_t align;
263         int rseg;
264         caddr_t kva;
265 
266         /*
267          * Allocate a DMA area
268          */
269         align = 1 << 24;
270         if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
271                              &rseg, BUS_DMA_NOWAIT)) {
272                 align = PAGE_SIZE;
273                 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
274                                      &rseg, BUS_DMA_NOWAIT)) {
275                         printf("%s: Unable to dmamem_alloc of %d bytes\n",
276 			       bktr_name(bktr), size);
277                         return 0;
278                 }
279         }
280         if (bus_dmamem_map(dmat, &seg, rseg, size,
281                            &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
282                 printf("%s: Unable to dmamem_map of %d bytes\n",
283                         bktr_name(bktr), size);
284                 bus_dmamem_free(dmat, &seg, rseg);
285                 return 0;
286         }
287         /*
288          * Create and locd the DMA map for the DMA area
289          */
290         if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
291                 printf("%s: Unable to dmamap_create of %d bytes\n",
292                         bktr_name(bktr), size);
293                 bus_dmamem_unmap(dmat, kva, size);
294                 bus_dmamem_free(dmat, &seg, rseg);
295                 return 0;
296         }
297         if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
298                 printf("%s: Unable to dmamap_load of %d bytes\n",
299                         bktr_name(bktr), size);
300                 bus_dmamem_unmap(dmat, kva, size);
301                 bus_dmamem_free(dmat, &seg, rseg);
302                 bus_dmamap_destroy(dmat, *dmapp);
303                 return 0;
304         }
305         return (vaddr_t)kva;
306 }
307 
308 void
309 free_bktr_mem(bktr_ptr_t bktr, bus_dmamap_t dmap, vaddr_t kva)
310 {
311         bus_dma_tag_t dmat = bktr->dmat;
312 
313         bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
314         bus_dmamem_free(dmat, dmap->dm_segs, 1);
315         bus_dmamap_destroy(dmat, dmap);
316 }
317 
318 
319 /*---------------------------------------------------------
320 **
321 **	BrookTree 848 character device driver routines
322 **
323 **---------------------------------------------------------
324 */
325 
326 
327 #define VIDEO_DEV	0x00
328 #define TUNER_DEV	0x01
329 #define VBI_DEV		0x02
330 
331 #define	UNIT(x)		((minor((x)) < 16) ? minor((x)) : ((minor((x)) - 16) / 2))
332 #define	FUNCTION(x)	((minor((x)) < 16) ? VIDEO_DEV : ((minor((x)) & 0x1) ? \
333     VBI_DEV : TUNER_DEV))
334 
335 /*
336  *
337  */
338 int
339 bktr_open(dev_t dev, int flags, int fmt, struct proc *p)
340 {
341 	bktr_ptr_t	bktr;
342 	int		unit;
343 
344 	unit = UNIT(dev);
345 
346 	/* unit out of range */
347 	if ((unit >= bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
348 		return(ENXIO);
349 
350 	bktr = bktr_cd.cd_devs[unit];
351 
352 	if (!(bktr->flags & METEOR_INITIALIZED)) /* device not found */
353 		return(ENXIO);
354 
355 	switch (FUNCTION(dev)) {
356 	case VIDEO_DEV:
357 		return(video_open(bktr));
358 	case TUNER_DEV:
359 		return(tuner_open(bktr));
360 	case VBI_DEV:
361 		return(vbi_open(bktr));
362 	}
363 
364 	return(ENXIO);
365 }
366 
367 
368 /*
369  *
370  */
371 int
372 bktr_close(dev_t dev, int flags, int fmt, struct proc *p)
373 {
374 	bktr_ptr_t	bktr;
375 	int		unit;
376 
377 	unit = UNIT(dev);
378 
379 	bktr = bktr_cd.cd_devs[unit];
380 
381 	switch (FUNCTION(dev)) {
382 	case VIDEO_DEV:
383 		return(video_close(bktr));
384 	case TUNER_DEV:
385 		return(tuner_close(bktr));
386 	case VBI_DEV:
387 		return(vbi_close(bktr));
388 	}
389 
390 	return(ENXIO);
391 }
392 
393 /*
394  *
395  */
396 int
397 bktr_read(dev_t dev, struct uio *uio, int ioflag)
398 {
399 	bktr_ptr_t	bktr;
400 	int		unit;
401 
402 	unit = UNIT(dev);
403 
404 	bktr = bktr_cd.cd_devs[unit];
405 
406 	switch (FUNCTION(dev)) {
407 	case VIDEO_DEV:
408 		return(video_read(bktr, unit, dev, uio));
409 	case VBI_DEV:
410 		return(vbi_read(bktr, uio, ioflag));
411 	}
412 
413         return(ENXIO);
414 }
415 
416 
417 /*
418  *
419  */
420 int
421 bktr_write(dev_t dev, struct uio *uio, int ioflag)
422 {
423 	/* operation not supported */
424 	return(EOPNOTSUPP);
425 }
426 
427 /*
428  *
429  */
430 int
431 bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr)
432 {
433 	bktr_ptr_t	bktr;
434 	int		unit;
435 
436 	unit = UNIT(dev);
437 
438 	bktr = bktr_cd.cd_devs[unit];
439 
440 	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
441 		return(ENOMEM);
442 
443 	switch (FUNCTION(dev)) {
444 	case VIDEO_DEV:
445 		return(video_ioctl(bktr, unit, cmd, arg, pr));
446 	case TUNER_DEV:
447 		return(tuner_ioctl(bktr, unit, cmd, arg, pr));
448 	}
449 
450 	return(ENXIO);
451 }
452 
453 /*
454  *
455  */
456 paddr_t
457 bktr_mmap(dev_t dev, off_t offset, int nprot)
458 {
459 	int		unit;
460 	bktr_ptr_t	bktr;
461 
462 	unit = UNIT(dev);
463 
464 	if (FUNCTION(dev) > 0)	/* only allow mmap on /dev/bktr[n] */
465 		return(-1);
466 
467 	bktr = bktr_cd.cd_devs[unit];
468 
469 	if (offset < 0)
470 		return(-1);
471 
472 	if (offset >= bktr->alloc_pages * PAGE_SIZE)
473 		return(-1);
474 
475 	return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
476 				offset, nprot, BUS_DMA_WAITOK));
477 }
478 
479 #if NRADIO > 0
480 int
481 bktr_set_info(void *v, struct radio_info *ri)
482 {
483 	struct bktr_softc *sc = v;
484 	struct TVTUNER *tv = &sc->tuner;
485 	u_int32_t freq;
486 	u_int32_t chan;
487 
488 	if (ri->mute) {
489 		/* mute the audio stream by switching the mux */
490 		set_audio(sc, AUDIO_MUTE);
491 	} else {
492 		/* unmute the audio stream */
493 		set_audio(sc, AUDIO_UNMUTE);
494 		init_audio_devices(sc);
495 	}
496 
497 	set_audio(sc, AUDIO_INTERN);	/* use internal audio */
498 	temp_mute(sc, TRUE);
499 
500 	if (ri->tuner_mode == RADIO_TUNER_MODE_TV) {
501 		if (ri->chan) {
502 			if (ri->chan < MIN_TV_CHAN)
503 				ri->chan = MIN_TV_CHAN;
504 			if (ri->chan > MAX_TV_CHAN)
505 				ri->chan = MAX_TV_CHAN;
506 
507 			chan = ri->chan;
508 			ri->chan = tv_channel(sc, chan);
509 			tv->tuner_mode = BT848_TUNER_MODE_TV;
510 		} else {
511 			ri->chan = tv->channel;
512 		}
513 	} else {
514 		if (ri->freq) {
515 			if (ri->freq < MIN_FM_FREQ)
516 				ri->freq = MIN_FM_FREQ;
517 			if (ri->freq > MAX_FM_FREQ)
518 				ri->freq = MAX_FM_FREQ;
519 
520 			freq = ri->freq / 10;
521 			ri->freq = tv_freq(sc, freq, FM_RADIO_FREQUENCY) * 10;
522 			tv->tuner_mode = BT848_TUNER_MODE_RADIO;
523 		} else {
524 			ri->freq = tv->frequency;
525 		}
526 	}
527 
528 	if (ri->chnlset >= CHNLSET_MIN && ri->chnlset <= CHNLSET_MAX)
529 		tv->chnlset = ri->chnlset;
530 	else
531 		tv->chnlset = DEFAULT_CHNLSET;
532 
533 	temp_mute(sc, FALSE);
534 
535 	return (0);
536 }
537 
538 int
539 bktr_get_info(void *v, struct radio_info *ri)
540 {
541 	struct bktr_softc *sc = v;
542 	struct TVTUNER *tv = &sc->tuner;
543 	int status;
544 
545 	status = get_tuner_status(sc);
546 
547 #define	STATUSBIT_STEREO	0x10
548 	ri->mute = (int)sc->audio_mute_state ? 1 : 0;
549 	ri->caps = RADIO_CAPS_DETECT_STEREO | RADIO_CAPS_HW_AFC;
550 	ri->info = (status & STATUSBIT_STEREO) ? RADIO_INFO_STEREO : 0;
551 
552 	/* not yet supported */
553 	ri->volume = ri->rfreq = ri->lock = 0;
554 
555 	switch (tv->tuner_mode) {
556 	case BT848_TUNER_MODE_TV:
557 		ri->tuner_mode = RADIO_TUNER_MODE_TV;
558 		ri->freq = tv->frequency * 1000 / 16;
559 		break;
560 	case BT848_TUNER_MODE_RADIO:
561 		ri->tuner_mode = RADIO_TUNER_MODE_RADIO;
562 		ri->freq = tv->frequency * 10;
563 		break;
564 	}
565 
566 	/*
567 	 * The field ri->stereo is used to forcible switch to
568 	 * mono/stereo, not as an indicator of received signal quality.
569 	 * The ri->info is for that purpose.
570 	 */
571 	ri->stereo = 1; /* Can't switch to mono, always stereo */
572 
573 	ri->chan = tv->channel;
574 	ri->chnlset = tv->chnlset;
575 
576 	return (0);
577 }
578 #endif /* NRADIO */
579