[BACK]Return to bktr_os.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci / bktr

Annotation of sys/dev/pci/bktr/bktr_os.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bktr_os.c,v 1.27 2007/06/18 07:31:14 jakemsr 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:        /* Enabled Bus Master
        !           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_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE |
        !           182:            PCI_COMMAND_BACKTOBACK_ENABLE);
        !           183:
        !           184:        /*
        !           185:         * map memory
        !           186:         */
        !           187:        retval = pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM |
        !           188:            PCI_MAPREG_MEM_TYPE_32BIT, 0, &bktr->memt, &bktr->memh, NULL,
        !           189:            &bktr->obmemsz, 0);
        !           190:        DPR(("pci_mapreg_map: memt %lx, memh %lx, size %x\n",
        !           191:             bktr->memt, bktr->memh, bktr->obmemsz));
        !           192:        if (retval) {
        !           193:                printf("%s: couldn't map memory\n", bktr_name(bktr));
        !           194:                return;
        !           195:        }
        !           196:
        !           197:        /*
        !           198:         * Disable the brooktree device
        !           199:         */
        !           200:        OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
        !           201:        OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
        !           202:
        !           203:        /*
        !           204:         * map interrupt
        !           205:         */
        !           206:        if (pci_intr_map(pa, &ih)) {
        !           207:                printf("%s: couldn't map interrupt\n",
        !           208:                       bktr_name(bktr));
        !           209:                return;
        !           210:        }
        !           211:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           212:        bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
        !           213:            bktr_intr, bktr, bktr->bktr_dev.dv_xname);
        !           214:        if (bktr->ih == NULL) {
        !           215:                printf("%s: couldn't establish interrupt",
        !           216:                       bktr_name(bktr));
        !           217:                if (intrstr != NULL)
        !           218:                        printf(" at %s", intrstr);
        !           219:                printf("\n");
        !           220:                return;
        !           221:        }
        !           222:        if (intrstr != NULL)
        !           223:                printf(": %s\n", intrstr);
        !           224:
        !           225: /*
        !           226:  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
        !           227:  * you have more than four, then 16 would probably be a better value.
        !           228:  */
        !           229: #ifndef BROOKTREE_DEF_LATENCY_VALUE
        !           230: #define BROOKTREE_DEF_LATENCY_VALUE    0x10
        !           231: #endif
        !           232:        latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
        !           233:        latency = (latency >> 8) & 0xff;
        !           234:
        !           235:        if (!latency) {
        !           236:                if (bootverbose) {
        !           237:                        printf("%s: PCI bus latency was 0 changing to %d",
        !           238:                               bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
        !           239:                }
        !           240:                latency = BROOKTREE_DEF_LATENCY_VALUE;
        !           241:                pci_conf_write(pa->pa_pc, pa->pa_tag,
        !           242:                               PCI_LATENCY_TIMER, latency<<8);
        !           243:        }
        !           244:
        !           245:
        !           246:        /* read the pci id and determine the card type */
        !           247:        fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
        !           248:         rev = PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG));
        !           249:
        !           250:        common_bktr_attach(bktr, unit, fun, rev);
        !           251:
        !           252: #if NRADIO > 0
        !           253:        if (bktr->card.tuner->pllControl[3] != 0x00)
        !           254:                radio_attach_mi(&bktr_hw_if, bktr, &bktr->bktr_dev);
        !           255: #endif
        !           256: }
        !           257:
        !           258:
        !           259: /*
        !           260:  * Special Memory Allocation
        !           261:  */
        !           262: vaddr_t
        !           263: get_bktr_mem(bktr, dmapp, size)
        !           264:         bktr_ptr_t bktr;
        !           265:         bus_dmamap_t *dmapp;
        !           266:         unsigned int size;
        !           267: {
        !           268:         bus_dma_tag_t dmat = bktr->dmat;
        !           269:         bus_dma_segment_t seg;
        !           270:         bus_size_t align;
        !           271:         int rseg;
        !           272:         caddr_t kva;
        !           273:
        !           274:         /*
        !           275:          * Allocate a DMA area
        !           276:          */
        !           277:         align = 1 << 24;
        !           278:         if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
        !           279:                              &rseg, BUS_DMA_NOWAIT)) {
        !           280:                 align = PAGE_SIZE;
        !           281:                 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
        !           282:                                      &rseg, BUS_DMA_NOWAIT)) {
        !           283:                         printf("%s: Unable to dmamem_alloc of %d bytes\n",
        !           284:                               bktr_name(bktr), size);
        !           285:                         return 0;
        !           286:                 }
        !           287:         }
        !           288:         if (bus_dmamem_map(dmat, &seg, rseg, size,
        !           289:                            &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
        !           290:                 printf("%s: Unable to dmamem_map of %d bytes\n",
        !           291:                         bktr_name(bktr), size);
        !           292:                 bus_dmamem_free(dmat, &seg, rseg);
        !           293:                 return 0;
        !           294:         }
        !           295:         /*
        !           296:          * Create and locd the DMA map for the DMA area
        !           297:          */
        !           298:         if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
        !           299:                 printf("%s: Unable to dmamap_create of %d bytes\n",
        !           300:                         bktr_name(bktr), size);
        !           301:                 bus_dmamem_unmap(dmat, kva, size);
        !           302:                 bus_dmamem_free(dmat, &seg, rseg);
        !           303:                 return 0;
        !           304:         }
        !           305:         if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
        !           306:                 printf("%s: Unable to dmamap_load of %d bytes\n",
        !           307:                         bktr_name(bktr), size);
        !           308:                 bus_dmamem_unmap(dmat, kva, size);
        !           309:                 bus_dmamem_free(dmat, &seg, rseg);
        !           310:                 bus_dmamap_destroy(dmat, *dmapp);
        !           311:                 return 0;
        !           312:         }
        !           313:         return (vaddr_t)kva;
        !           314: }
        !           315:
        !           316: void
        !           317: free_bktr_mem(bktr, dmap, kva)
        !           318:         bktr_ptr_t bktr;
        !           319:         bus_dmamap_t dmap;
        !           320:         vaddr_t kva;
        !           321: {
        !           322:         bus_dma_tag_t dmat = bktr->dmat;
        !           323:
        !           324:         bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
        !           325:         bus_dmamem_free(dmat, dmap->dm_segs, 1);
        !           326:         bus_dmamap_destroy(dmat, dmap);
        !           327: }
        !           328:
        !           329:
        !           330: /*---------------------------------------------------------
        !           331: **
        !           332: **     BrookTree 848 character device driver routines
        !           333: **
        !           334: **---------------------------------------------------------
        !           335: */
        !           336:
        !           337:
        !           338: #define VIDEO_DEV      0x00
        !           339: #define TUNER_DEV      0x01
        !           340: #define VBI_DEV                0x02
        !           341:
        !           342: #define UNIT(x)         (minor((x) & 0x0f))
        !           343: #define FUNCTION(x)     (minor((x >> 4) & 0x0f))
        !           344:
        !           345: /*
        !           346:  *
        !           347:  */
        !           348: int
        !           349: bktr_open(dev_t dev, int flags, int fmt, struct proc *p)
        !           350: {
        !           351:        bktr_ptr_t      bktr;
        !           352:        int             unit;
        !           353:
        !           354:        unit = UNIT(dev);
        !           355:
        !           356:        /* unit out of range */
        !           357:        if ((unit >= bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
        !           358:                return(ENXIO);
        !           359:
        !           360:        bktr = bktr_cd.cd_devs[unit];
        !           361:
        !           362:        if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
        !           363:                return(ENXIO);
        !           364:
        !           365:        switch (FUNCTION(dev)) {
        !           366:        case VIDEO_DEV:
        !           367:                return(video_open(bktr));
        !           368:        case TUNER_DEV:
        !           369:                return(tuner_open(bktr));
        !           370:        case VBI_DEV:
        !           371:                return(vbi_open(bktr));
        !           372:        }
        !           373:
        !           374:        return(ENXIO);
        !           375: }
        !           376:
        !           377:
        !           378: /*
        !           379:  *
        !           380:  */
        !           381: int
        !           382: bktr_close(dev_t dev, int flags, int fmt, struct proc *p)
        !           383: {
        !           384:        bktr_ptr_t      bktr;
        !           385:        int             unit;
        !           386:
        !           387:        unit = UNIT(dev);
        !           388:
        !           389:        bktr = bktr_cd.cd_devs[unit];
        !           390:
        !           391:        switch (FUNCTION(dev)) {
        !           392:        case VIDEO_DEV:
        !           393:                return(video_close(bktr));
        !           394:        case TUNER_DEV:
        !           395:                return(tuner_close(bktr));
        !           396:        case VBI_DEV:
        !           397:                return(vbi_close(bktr));
        !           398:        }
        !           399:
        !           400:        return(ENXIO);
        !           401: }
        !           402:
        !           403: /*
        !           404:  *
        !           405:  */
        !           406: int
        !           407: bktr_read(dev_t dev, struct uio *uio, int ioflag)
        !           408: {
        !           409:        bktr_ptr_t      bktr;
        !           410:        int             unit;
        !           411:
        !           412:        unit = UNIT(dev);
        !           413:
        !           414:        bktr = bktr_cd.cd_devs[unit];
        !           415:
        !           416:        switch (FUNCTION(dev)) {
        !           417:        case VIDEO_DEV:
        !           418:                return(video_read(bktr, unit, dev, uio));
        !           419:        case VBI_DEV:
        !           420:                return(vbi_read(bktr, uio, ioflag));
        !           421:        }
        !           422:
        !           423:         return(ENXIO);
        !           424: }
        !           425:
        !           426:
        !           427: /*
        !           428:  *
        !           429:  */
        !           430: int
        !           431: bktr_write(dev_t dev, struct uio *uio, int ioflag)
        !           432: {
        !           433:        /* operation not supported */
        !           434:        return(EOPNOTSUPP);
        !           435: }
        !           436:
        !           437: /*
        !           438:  *
        !           439:  */
        !           440: int
        !           441: bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr)
        !           442: {
        !           443:        bktr_ptr_t      bktr;
        !           444:        int             unit;
        !           445:
        !           446:        unit = UNIT(dev);
        !           447:
        !           448:        bktr = bktr_cd.cd_devs[unit];
        !           449:
        !           450:        if (bktr->bigbuf == 0)  /* no frame buffer allocated (ioctl failed) */
        !           451:                return(ENOMEM);
        !           452:
        !           453:        switch (FUNCTION(dev)) {
        !           454:        case VIDEO_DEV:
        !           455:                return(video_ioctl(bktr, unit, cmd, arg, pr));
        !           456:        case TUNER_DEV:
        !           457:                return(tuner_ioctl(bktr, unit, cmd, arg, pr));
        !           458:        }
        !           459:
        !           460:        return(ENXIO);
        !           461: }
        !           462:
        !           463: /*
        !           464:  *
        !           465:  */
        !           466: paddr_t
        !           467: bktr_mmap(dev_t dev, off_t offset, int nprot)
        !           468: {
        !           469:        int             unit;
        !           470:        bktr_ptr_t      bktr;
        !           471:
        !           472:        unit = UNIT(dev);
        !           473:
        !           474:        if (FUNCTION(dev) > 0)  /* only allow mmap on /dev/bktr[n] */
        !           475:                return(-1);
        !           476:
        !           477:        bktr = bktr_cd.cd_devs[unit];
        !           478:
        !           479:        if ((vaddr_t)offset < 0)
        !           480:                return(-1);
        !           481:
        !           482:        if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
        !           483:                return(-1);
        !           484:
        !           485:        return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
        !           486:                                (vaddr_t)offset, nprot, BUS_DMA_WAITOK));
        !           487: }
        !           488:
        !           489: #if NRADIO > 0
        !           490: int
        !           491: bktr_set_info(void *v, struct radio_info *ri)
        !           492: {
        !           493:        struct bktr_softc *sc = v;
        !           494:        struct TVTUNER *tv = &sc->tuner;
        !           495:        u_int32_t freq;
        !           496:        u_int32_t chan;
        !           497:
        !           498:        if (ri->mute) {
        !           499:                /* mute the audio stream by switching the mux */
        !           500:                set_audio(sc, AUDIO_MUTE);
        !           501:        } else {
        !           502:                /* unmute the audio stream */
        !           503:                set_audio(sc, AUDIO_UNMUTE);
        !           504:                init_audio_devices(sc);
        !           505:        }
        !           506:
        !           507:        set_audio(sc, AUDIO_INTERN);    /* use internal audio */
        !           508:        temp_mute(sc, TRUE);
        !           509:
        !           510:        if (ri->tuner_mode == RADIO_TUNER_MODE_TV) {
        !           511:                if (ri->chan) {
        !           512:                        if (ri->chan < MIN_TV_CHAN)
        !           513:                                ri->chan = MIN_TV_CHAN;
        !           514:                        if (ri->chan > MAX_TV_CHAN)
        !           515:                                ri->chan = MAX_TV_CHAN;
        !           516:
        !           517:                        chan = ri->chan;
        !           518:                        ri->chan = tv_channel(sc, chan);
        !           519:                        tv->tuner_mode = BT848_TUNER_MODE_TV;
        !           520:                } else {
        !           521:                        ri->chan = tv->channel;
        !           522:                }
        !           523:        } else {
        !           524:                if (ri->freq) {
        !           525:                        if (ri->freq < MIN_FM_FREQ)
        !           526:                                ri->freq = MIN_FM_FREQ;
        !           527:                        if (ri->freq > MAX_FM_FREQ)
        !           528:                                ri->freq = MAX_FM_FREQ;
        !           529:
        !           530:                        freq = ri->freq / 10;
        !           531:                        ri->freq = tv_freq(sc, freq, FM_RADIO_FREQUENCY) * 10;
        !           532:                        tv->tuner_mode = BT848_TUNER_MODE_RADIO;
        !           533:                } else {
        !           534:                        ri->freq = tv->frequency;
        !           535:                }
        !           536:        }
        !           537:
        !           538:        if (ri->chnlset >= CHNLSET_MIN && ri->chnlset <= CHNLSET_MAX)
        !           539:                tv->chnlset = ri->chnlset;
        !           540:        else
        !           541:                tv->chnlset = DEFAULT_CHNLSET;
        !           542:
        !           543:        temp_mute(sc, FALSE);
        !           544:
        !           545:        return (0);
        !           546: }
        !           547:
        !           548: int
        !           549: bktr_get_info(void *v, struct radio_info *ri)
        !           550: {
        !           551:        struct bktr_softc *sc = v;
        !           552:        struct TVTUNER *tv = &sc->tuner;
        !           553:        int status;
        !           554:
        !           555:        status = get_tuner_status(sc);
        !           556:
        !           557: #define        STATUSBIT_STEREO        0x10
        !           558:        ri->mute = (int)sc->audio_mute_state ? 1 : 0;
        !           559:        ri->caps = RADIO_CAPS_DETECT_STEREO | RADIO_CAPS_HW_AFC;
        !           560:        ri->info = (status & STATUSBIT_STEREO) ? RADIO_INFO_STEREO : 0;
        !           561:
        !           562:        /* not yet supported */
        !           563:        ri->volume = ri->rfreq = ri->lock = 0;
        !           564:
        !           565:        switch (tv->tuner_mode) {
        !           566:        case BT848_TUNER_MODE_TV:
        !           567:                ri->tuner_mode = RADIO_TUNER_MODE_TV;
        !           568:                ri->freq = tv->frequency * 1000 / 16;
        !           569:                break;
        !           570:        case BT848_TUNER_MODE_RADIO:
        !           571:                ri->tuner_mode = RADIO_TUNER_MODE_RADIO;
        !           572:                ri->freq = tv->frequency * 10;
        !           573:                break;
        !           574:        }
        !           575:
        !           576:        /*
        !           577:         * The field ri->stereo is used to forcible switch to
        !           578:         * mono/stereo, not as an indicator of received signal quality.
        !           579:         * The ri->info is for that purpose.
        !           580:         */
        !           581:        ri->stereo = 1; /* Can't switch to mono, always stereo */
        !           582:
        !           583:        ri->chan = tv->channel;
        !           584:        ri->chnlset = tv->chnlset;
        !           585:
        !           586:        return (0);
        !           587: }
        !           588: #endif /* NRADIO */

CVSweb