The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/radiotrack2.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: radiotrack2.c,v 1.9 2003/07/14 15:47:16 lukem Exp $ */
    2 /* $OpenBSD: radiotrack2.c,v 1.1 2001/12/05 10:27:06 mickey Exp $ */
    3 /* $RuOBSD: radiotrack2.c,v 1.2 2001/10/18 16:51:36 pva Exp $ */
    4 
    5 /*
    6  * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net>,
    7  *                    Vladimir Popov <jumbo@narod.ru>
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /* AIMS Lab Radiotrack II FM Radio Card device driver */
   32 
   33 /*
   34  * Philips TEA5757H AM/FM Self Tuned Radio:
   35  *      http://www.semiconductors.philips.com/pip/TEA5757H
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: radiotrack2.c,v 1.9 2003/07/14 15:47:16 lukem Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/proc.h>
   44 #include <sys/errno.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/device.h>
   47 #include <sys/radioio.h>
   48 
   49 #include <dev/isa/isavar.h>
   50 #include <dev/radio_if.h>
   51 #include <dev/ic/tea5757.h>
   52 
   53 #define RTII_BASE_VALID(x)      ((x == 0x20C) || (x == 0x30C))
   54 #define RTII_CAPABILITIES       RADIO_CAPS_DETECT_STEREO |              \
   55                                 RADIO_CAPS_DETECT_SIGNAL |              \
   56                                 RADIO_CAPS_SET_MONO |                   \
   57                                 RADIO_CAPS_LOCK_SENSITIVITY |           \
   58                                 RADIO_CAPS_HW_AFC |                     \
   59                                 RADIO_CAPS_HW_SEARCH
   60 
   61 #if 0
   62 #define RTII_SIGNAL             (1 << 3)
   63 #define RTII_STEREO             (1 << 3)
   64 #endif /* 0 */
   65 
   66 #define RTII_MUTE               0x01
   67 #define RTII_UNMUTE             0x00
   68 
   69 #define RTII_RESET              0xC8
   70 
   71 #define RTII_DATA_ON            (1 << 2)
   72 #define RTII_DATA_OFF           (0 << 2)
   73 
   74 #define RTII_CLCK_ON            (1 << 1)
   75 #define RTII_CLCK_OFF           (0 << 1)
   76 
   77 #define RTII_WREN_ON            (0 << 0)
   78 #define RTII_WREN_OFF           (1 << 0)
   79 
   80 #define RTII_READ_CLOCK_LOW     (RTII_DATA_ON | RTII_CLCK_OFF | RTII_WREN_OFF)
   81 #define RTII_READ_CLOCK_HIGH    (RTII_DATA_ON | RTII_CLCK_ON | RTII_WREN_OFF)
   82 
   83 int     rtii_probe(struct device *, struct cfdata *, void *);
   84 void    rtii_attach(struct device *, struct device * self, void *);
   85 
   86 int     rtii_get_info(void *, struct radio_info *);
   87 int     rtii_set_info(void *, struct radio_info *);
   88 int     rtii_search(void *, int);
   89 
   90 /* define our interface to the higher level radio driver */
   91 struct radio_hw_if rtii_hw_if = {
   92         NULL,   /* open */
   93         NULL,   /* close */
   94         rtii_get_info,
   95         rtii_set_info,
   96         rtii_search
   97 };
   98 
   99 struct rtii_softc {
  100         struct device   dev;
  101 
  102         u_int32_t       freq;
  103         u_int32_t       stereo;
  104         u_int32_t       lock;
  105         u_int8_t        vol;
  106         int     mute;
  107 
  108         struct tea5757_t        tea;
  109 };
  110 
  111 CFATTACH_DECL(rtii, sizeof(struct rtii_softc),
  112     rtii_probe, rtii_attach, NULL, NULL);
  113 
  114 void    rtii_set_mute(struct rtii_softc *);
  115 int     rtii_find(bus_space_tag_t, bus_space_handle_t);
  116 
  117 u_int32_t       rtii_hw_read(bus_space_tag_t, bus_space_handle_t, bus_size_t);
  118 
  119 void    rtii_init(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
  120 void    rtii_rset(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
  121 void    rtii_write_bit(bus_space_tag_t, bus_space_handle_t, bus_size_t, int);
  122 
  123 int
  124 rtii_probe(struct device *parent, struct cfdata *cf, void *aux)
  125 {
  126         struct isa_attach_args *ia = aux;
  127         bus_space_tag_t iot = ia->ia_iot;
  128         bus_space_handle_t ioh;
  129         u_int r;
  130         int iosize = 1, iobase;
  131 
  132         if (ISA_DIRECT_CONFIG(ia))
  133                 return 0;
  134 
  135         if (ia->ia_nio < 1)
  136                 return 0;
  137 
  138         iobase = ia->ia_io[0].ir_addr;
  139 
  140         if (!RTII_BASE_VALID(iobase)) {
  141                 printf("rtii: configured iobase 0x%x invalid\n", iobase);
  142                 return 0;
  143         }
  144 
  145         if (bus_space_map(iot, iobase, iosize, 0, &ioh))
  146                 return 0;
  147 
  148         r = rtii_find(iot, ioh);
  149 
  150         bus_space_unmap(iot, ioh, iosize);
  151 
  152         if (r != 0) {
  153                 ia->ia_nio = 1;
  154                 ia->ia_io[0].ir_size = iosize;
  155 
  156                 ia->ia_niomem = 0;
  157                 ia->ia_nirq = 0;
  158                 ia->ia_ndrq = 0;
  159 
  160                 return (1);
  161         }
  162 
  163         return (0);
  164 }
  165 
  166 void
  167 rtii_attach(struct device *parent, struct device *self, void *aux)
  168 {
  169         struct rtii_softc *sc = (void *) self;
  170         struct isa_attach_args *ia = aux;
  171 
  172         sc->tea.iot = ia->ia_iot;
  173         sc->tea.flags = 0;
  174         sc->mute = 0;
  175         sc->vol = 0;
  176         sc->freq = MIN_FM_FREQ;
  177         sc->stereo = TEA5757_STEREO;
  178         sc->lock = TEA5757_S030;
  179 
  180         /* remap I/O */
  181         if (bus_space_map(sc->tea.iot, ia->ia_io[0].ir_addr,
  182             ia->ia_io[0].ir_size, 0, &sc->tea.ioh))
  183                 panic("rtiiattach: bus_space_map() failed");
  184 
  185         sc->tea.offset = 0;
  186 
  187         sc->tea.init = rtii_init;
  188         sc->tea.rset = rtii_rset;
  189         sc->tea.write_bit = rtii_write_bit;
  190         sc->tea.read = rtii_hw_read;
  191 
  192         printf(": AIMS Lab Radiotrack II\n");
  193         tea5757_set_freq(&sc->tea, sc->stereo, sc->lock, sc->freq);
  194         rtii_set_mute(sc);
  195 
  196         radio_attach_mi(&rtii_hw_if, sc, &sc->dev);
  197 }
  198 
  199 /*
  200  * Mute/unmute the card
  201  */
  202 void
  203 rtii_set_mute(struct rtii_softc *sc)
  204 {
  205         u_int8_t mute;
  206 
  207         mute = (sc->mute || !sc->vol) ? RTII_MUTE : RTII_UNMUTE;
  208         bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
  209         DELAY(6);
  210         bus_space_write_1(sc->tea.iot, sc->tea.ioh, 0, mute);
  211 }
  212 
  213 void
  214 rtii_init(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
  215 {
  216         bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
  217         bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
  218         bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_ON);
  219 }
  220 
  221 void
  222 rtii_rset(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, u_int32_t d)
  223 {
  224         bus_space_write_1(iot, ioh, off, RTII_RESET | RTII_WREN_OFF);
  225 }
  226 
  227 int
  228 rtii_find(bus_space_tag_t iot, bus_space_handle_t ioh)
  229 {
  230         struct rtii_softc sc;
  231         u_int32_t freq;
  232 
  233         sc.tea.iot = iot;
  234         sc.tea.ioh = ioh;
  235         sc.tea.offset = 0;
  236         sc.tea.init = rtii_init;
  237         sc.tea.rset = rtii_rset;
  238         sc.tea.write_bit = rtii_write_bit;
  239         sc.tea.read = rtii_hw_read;
  240         sc.lock = TEA5757_S030;
  241         sc.stereo = TEA5757_STEREO;
  242 
  243         /*
  244          * Let's try to write and read a frequency.
  245          * If the written and read frequencies are
  246          * the same then success.
  247          */
  248         sc.freq = MIN_FM_FREQ;
  249         tea5757_set_freq(&sc.tea, sc.stereo, sc.lock, sc.freq);
  250         rtii_set_mute(&sc);
  251         freq = rtii_hw_read(iot, ioh, sc.tea.offset);
  252         if (tea5757_decode_freq(freq, 0) == sc.freq)
  253                 return 1;
  254 
  255         return 0;
  256 }
  257 
  258 void
  259 rtii_write_bit(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off, int bit)
  260 {
  261         u_int8_t data;
  262 
  263         data = bit ? RTII_DATA_ON : RTII_DATA_OFF;
  264 
  265         bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
  266         bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_ON  | data);
  267         bus_space_write_1(iot, ioh, off, RTII_WREN_ON | RTII_CLCK_OFF | data);
  268 }
  269 
  270 u_int32_t
  271 rtii_hw_read(bus_space_tag_t iot, bus_space_handle_t ioh, bus_size_t off)
  272 {
  273         u_int8_t i;
  274         u_int32_t res = 0;
  275 
  276         bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
  277         DELAY(6);
  278 
  279         i = 24;
  280         while ( i-- ) {
  281                 bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_HIGH);
  282                 DELAY(6);
  283                 bus_space_write_1(iot, ioh, off, RTII_READ_CLOCK_LOW);
  284                 res |= bus_space_read_1(iot, ioh, off) & RTII_DATA_ON ? 1 : 0;
  285                 DELAY(6);
  286                 res <<= 1;
  287         }
  288 
  289         return (res & (TEA5757_DATA | TEA5757_FREQ)) >> 1;
  290 }
  291 
  292 int
  293 rtii_get_info(void *v, struct radio_info *ri)
  294 {
  295         struct rtii_softc *sc = v;
  296 
  297         ri->mute = sc->mute;
  298         ri->volume = sc->vol ? 255 : 0;
  299         ri->stereo = sc->stereo == TEA5757_STEREO ? 1 : 0;
  300         ri->caps = RTII_CAPABILITIES;
  301         ri->rfreq = 0;
  302         ri->lock = tea5757_decode_lock(sc->lock);
  303 
  304         ri->freq  = sc->freq = tea5757_decode_freq(rtii_hw_read(sc->tea.iot,
  305                                 sc->tea.ioh, sc->tea.offset), 0);
  306 
  307         switch (bus_space_read_1(sc->tea.iot, sc->tea.ioh, 0)) {
  308         case 0xFD:
  309                 ri->info = RADIO_INFO_SIGNAL | RADIO_INFO_STEREO;
  310                 break;
  311         case 0xFF:
  312                 ri->info = 0;
  313                 break;
  314         default:
  315                 ri->info = RADIO_INFO_SIGNAL;
  316         }
  317 
  318         return (0);
  319 }
  320 
  321 int
  322 rtii_set_info(void *v, struct radio_info *ri)
  323 {
  324         struct rtii_softc *sc = v;
  325 
  326         sc->mute = ri->mute ? 1 : 0;
  327         sc->vol = ri->volume ? 255 : 0;
  328         sc->stereo = ri->stereo ? TEA5757_STEREO: TEA5757_MONO;
  329         sc->lock = tea5757_encode_lock(ri->lock);
  330         ri->freq = sc->freq = tea5757_set_freq(&sc->tea,
  331                         sc->lock, sc->stereo, ri->freq);
  332         rtii_set_mute(sc);
  333 
  334         return (0);
  335 }
  336 
  337 int
  338 rtii_search(void *v, int f)
  339 {
  340         struct rtii_softc *sc = v;
  341 
  342         tea5757_search(&sc->tea, sc->lock, sc->stereo, f);
  343         rtii_set_mute(sc);
  344 
  345         return (0);
  346 }

Cache object: 68ca92fd0c982ef7440577effe0d8c14


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.