root/dev/pci/fmsradio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fmsradio_attach
  2. sf256pcs_probe
  3. sf256pcs_hw_read
  4. sf256pcs_write_bit
  5. sf256pcs_init
  6. sf256pcs_rset
  7. sf256pcpr_probe
  8. sf256pcpr_hw_read
  9. sf256pcpr_write_bit
  10. sf256pcpr_init
  11. sf256pcpr_rset
  12. sf64pcr_probe
  13. sf64pcr_hw_read
  14. sf64pcr_write_bit
  15. sf64pcr_init
  16. sf64pcr_rset
  17. fmsradio_set_mute
  18. fmsradio_get_info
  19. fmsradio_set_info
  20. fmsradio_search

    1 /*      $OpenBSD: fmsradio.c,v 1.6 2002/06/06 16:29:37 mickey Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2002 Vladimir Popov <jumbo@narod.ru>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /* Device Driver for FM Tuners attached to FM801 */
   30 
   31 /* Currently supported tuners:
   32  *  o SoundForte RadioLink SF64-PCR PCI Radio Card
   33  *  o SoundForte Quad X-treme SF256-PCP-R PCI Sound Card with FM Radio
   34  *  o SoundForte Theatre X-treme 5.1 SF256-PCS-R PCI Sound Card with FM Radio
   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  * Function prototypes
  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,   /* open */
  141         NULL,   /* close */
  142         fmsradio_get_info,
  143         fmsradio_set_info,
  144         fmsradio_search
  145 };
  146 
  147 struct fmsradio_if {
  148         int                     type; /* Card 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 /* SF256-PCS specific routines */
  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         /* Now read data in */
  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         /* Read the register */
  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 /* SF256-PCP-R specific routines */
  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         /* Now read data in */
  316         d |= PCPR_WREN_OFF | PCPR_DATA_ON;
  317 
  318         bus_space_write_2(iot, ioh, offset, d | PCPR_CLOCK_OFF);
  319 
  320         /* Read the register */
  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 /* SF64-PCR specific routines */
  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         /* Now read data in */
  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         /* Read the register */
  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); /* Tuning */
  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); /* Mono */
  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         /* Do nothing */
  467         return;
  468 }
  469 
  470 
  471 /* Common tuner routines */
  472 /*
  473  * Mute/unmute
  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; /* UNSUPPORTED */
  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         /* UNSUPPORTED */
  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 }

/* [<][>][^][v][top][bottom][index][help] */