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