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/ic/tms320av110.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: tms320av110.c,v 1.21 2008/04/28 20:23:51 martin Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Ignatios Souvatzis.
    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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Machine independent part of TMS320AV110 driver.
   34  *
   35  * Currently, only minimum support for audio output. For audio/video
   36  * synchronization, more is needed.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: tms320av110.c,v 1.21 2008/04/28 20:23:51 martin Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/device.h>
   46 #include <sys/proc.h>
   47 
   48 #include <sys/audioio.h>
   49 #include <dev/audio_if.h>
   50 
   51 #include <dev/ic/tms320av110reg.h>
   52 #include <dev/ic/tms320av110var.h>
   53 
   54 #include <sys/bus.h>
   55 
   56 int tav_open(void *, int);
   57 void tav_close(void *);
   58 int tav_drain(void *);
   59 int tav_query_encoding(void *, struct audio_encoding *);
   60 int tav_set_params(void *, int, int, audio_params_t *, audio_params_t *,
   61     stream_filter_list_t *, stream_filter_list_t *);
   62 int tav_round_blocksize(void *, int, int, const audio_params_t *);
   63 int tav_init_output(void *, void *, int);
   64 int tav_start_output(void *, void *, int, void (*)(void *), void *);
   65 int tav_start_input(void *, void *, int, void (*)(void *), void *);
   66 int tav_halt_output(void *);
   67 int tav_halt_input(void *);
   68 int tav_speaker_ctl(void *, int);
   69 int tav_getdev(void *, struct audio_device *);
   70 int tav_setfd(void *, int);
   71 int tav_set_port(void *, mixer_ctrl_t *);
   72 int tav_get_port(void *, mixer_ctrl_t *);
   73 int tav_query_devinfo(void *, mixer_devinfo_t *);
   74 int tav_get_props(void *);
   75 
   76 const struct audio_hw_if tav_audio_if = {
   77         tav_open,
   78         tav_close,
   79         0 /* tav_drain*/,               /* optional */
   80         tav_query_encoding,
   81         tav_set_params,
   82         tav_round_blocksize,
   83         0 /* commit_settings */,        /* optional */
   84         tav_init_output,                /* optional */
   85         0 /* tav_init_input */,         /* optional */
   86         tav_start_output,
   87         tav_start_input,
   88         tav_halt_output,
   89         tav_halt_input,
   90         tav_speaker_ctl,                /* optional */
   91         tav_getdev,
   92         0 /* setfd */,                  /* optional */
   93         tav_set_port,
   94         tav_get_port,
   95         tav_query_devinfo,
   96         0 /* alloc */,                  /* optional */
   97         0 /* free */,                   /* optional */
   98         0 /* round_buffersize */,       /* optional */
   99         0 /* mappage */,                /* optional */
  100         tav_get_props,
  101         0 /* dev_ioctl */               /* optional */
  102 };
  103 
  104 void
  105 tms320av110_attach_mi(struct tav_softc *sc)
  106 {
  107         bus_space_tag_t iot;
  108         bus_space_handle_t ioh;
  109 
  110         iot = sc->sc_iot;
  111         ioh = sc->sc_ioh;
  112         tav_write_byte(iot, ioh, TAV_RESET, 1);
  113         while (tav_read_byte(iot, ioh, TAV_RESET))
  114                 delay(250);
  115 
  116         tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord);
  117         tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18);
  118         tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif);
  119         tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div);
  120 
  121         printf(": chip rev. %d, %d bytes buffer\n",
  122             tav_read_byte(iot, ioh, TAV_VERSION),
  123             TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)));
  124 
  125         tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0);
  126         tav_write_byte(iot, ioh, TAV_SKIP, 0);
  127         tav_write_byte(iot, ioh, TAV_REPEAT, 0);
  128         tav_write_byte(iot, ioh, TAV_MUTE, 0);
  129         tav_write_byte(iot, ioh, TAV_PLAY, 1);
  130         tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0);
  131         tav_write_byte(iot, ioh, TAV_CRC_ECM, 0);
  132         tav_write_byte(iot, ioh, TAV_ATTEN_L, 0);
  133         tav_write_byte(iot, ioh, TAV_ATTEN_R, 0);
  134         tav_write_short(iot, ioh, TAV_FREE_FORM, 0);
  135         tav_write_byte(iot, ioh, TAV_SIN_EN, 0);
  136         tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT);
  137         tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT);
  138 
  139         audio_attach_mi(&tav_audio_if, sc, &sc->sc_dev);
  140 }
  141 
  142 int
  143 tms320av110_intr(void *p)
  144 {
  145         struct tav_softc *sc;
  146         uint16_t intlist;
  147 
  148         sc = p;
  149         intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR)
  150             /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/;
  151 
  152         if (!intlist)
  153                 return 0;
  154 
  155         /* ack now, so that we don't miss later interrupts */
  156         if (sc->sc_intack)
  157                 (sc->sc_intack)(sc);
  158 
  159         if (intlist & TAV_INTR_LOWWATER) {
  160                 (*sc->sc_intr)(sc->sc_intrarg);
  161         }
  162 
  163         if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) {
  164                  wakeup(sc);
  165         }
  166 
  167         return 1;
  168 }
  169 
  170 struct audio_encoding tav_encodings[] = {
  171         {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,},
  172         {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,},
  173         {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,},
  174         {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,},
  175 };
  176 
  177 int
  178 tav_open(void *hdl, int flags)
  179 {
  180 
  181         /* dummy */
  182         return 0;
  183 }
  184 
  185 void
  186 tav_close(void *hdl)
  187 {
  188         struct tav_softc *sc;
  189         bus_space_tag_t iot;
  190         bus_space_handle_t ioh;
  191 
  192         sc = hdl;
  193         iot = sc->sc_iot;
  194         ioh = sc->sc_ioh;
  195 
  196         /* re"start" chip, also clears interrupts and interrupt enable */
  197         tav_write_short(iot, ioh, TAV_INTR_EN, 0);
  198         if (sc->sc_intack)
  199                 (*sc->sc_intack)(sc);
  200 }
  201 
  202 int
  203 tav_drain(void *hdl)
  204 {
  205         struct tav_softc *sc;
  206         bus_space_tag_t iot;
  207         bus_space_handle_t ioh;
  208         u_int16_t mask;
  209 
  210         sc = hdl;
  211         iot = sc->sc_iot;
  212         ioh = sc->sc_ioh;
  213 
  214         /*
  215          * tsleep waiting for underflow interrupt.
  216          */
  217         if (tav_read_short(iot, ioh, TAV_BUFF)) {
  218                 mask = tav_read_short(iot, ioh, TAV_INTR_EN);
  219                 tav_write_short(iot, ioh, TAV_INTR_EN,
  220                     mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW);
  221 
  222                 /* still more than zero? */
  223                 if (tav_read_short(iot, ioh, TAV_BUFF))
  224                         (void)tsleep(sc, PCATCH, "tavdrain", 32*hz);
  225 
  226                 /* can be really that long for mpeg */
  227 
  228                 mask = tav_read_short(iot, ioh, TAV_INTR_EN);
  229                 tav_write_short(iot, ioh, TAV_INTR_EN,
  230                     mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW);
  231         }
  232 
  233         return 0;
  234 }
  235 
  236 int
  237 tav_query_encoding(void *hdl, struct audio_encoding *ae)
  238 {
  239         struct tav_softc *sc;
  240 
  241         sc = hdl;
  242         if (ae->index >= sizeof(tav_encodings)/sizeof(*ae))
  243                 return EINVAL;
  244 
  245         *ae = tav_encodings[ae->index];
  246 
  247         return 0;
  248 }
  249 
  250 int
  251 tav_start_input(void *hdl, void *block, int bsize,
  252     void (*intr)(void *), void *intrarg)
  253 {
  254 
  255         return ENOTTY;
  256 }
  257 
  258 int
  259 tav_halt_input(void *hdl)
  260 {
  261 
  262         return ENOTTY;
  263 }
  264 
  265 int
  266 tav_start_output(void *hdl, void *block, int bsize,
  267     void (*intr)(void *), void *intrarg)
  268 {
  269         struct tav_softc *sc;
  270         bus_space_tag_t iot;
  271         bus_space_handle_t ioh;
  272         uint8_t *ptr;
  273         int count;
  274 
  275         sc = hdl;
  276         iot = sc->sc_iot;
  277         ioh = sc->sc_ioh;
  278         ptr = block;
  279         count = bsize;
  280 
  281         sc->sc_intr = intr;
  282         sc->sc_intrarg = intrarg;
  283 
  284         bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count);
  285         tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER);
  286 
  287         return 0;
  288 }
  289 
  290 int
  291 tav_init_output(void *hdl, void *buffer, int size)
  292 {
  293         struct tav_softc *sc;
  294         bus_space_tag_t iot;
  295         bus_space_handle_t ioh;
  296 
  297         sc = hdl;
  298         iot = sc->sc_iot;
  299         ioh = sc->sc_ioh;
  300 
  301         tav_write_byte(iot, ioh, TAV_PLAY, 1);
  302         tav_write_byte(iot, ioh, TAV_MUTE, 0);
  303 
  304         return 0;
  305 }
  306 
  307 int
  308 tav_halt_output(void *hdl)
  309 {
  310         struct tav_softc *sc;
  311         bus_space_tag_t iot;
  312         bus_space_handle_t ioh;
  313 
  314         sc = hdl;
  315         iot = sc->sc_iot;
  316         ioh = sc->sc_ioh;
  317 
  318         tav_write_byte(iot, ioh, TAV_PLAY, 0);
  319 
  320         return 0;
  321 }
  322 
  323 int
  324 tav_getdev(void *hdl, struct audio_device *ret)
  325 {
  326         struct tav_softc *sc;
  327         bus_space_tag_t iot;
  328         bus_space_handle_t ioh;
  329 
  330         sc = hdl;
  331         iot = sc->sc_iot;
  332         ioh = sc->sc_ioh;
  333 
  334         strlcpy(ret->name, "tms320av110", sizeof(ret->name));
  335         /* guaranteed to be <= 4 in length */
  336         snprintf(ret->version, sizeof(ret->version), "%u",
  337             tav_read_byte(iot, ioh, TAV_VERSION));
  338         strlcpy(ret->config, device_xname(&sc->sc_dev), sizeof(ret->config));
  339 
  340         return 0;
  341 }
  342 
  343 int
  344 tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param)
  345 {
  346         struct tav_softc *sc;
  347         bus_space_tag_t iot;
  348         bus_space_handle_t ioh;
  349         int maxhalf;
  350 
  351         sc = hdl;
  352         iot = sc->sc_iot;
  353         ioh = sc->sc_ioh;
  354 
  355         maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT));
  356         if (size > maxhalf)
  357                 size = maxhalf;
  358 
  359         /* XXX should round to 128 bytes limits for audio bypass */
  360         size &= ~3;
  361 
  362         tav_write_short(iot, ioh, TAV_BALE_LIM, size/8);
  363 
  364         /* the buffer limits are in units of 4 bytes */
  365         return (size);
  366 }
  367 
  368 int
  369 tav_get_props(void *hdl)
  370 {
  371         return 0;
  372 }
  373 
  374 int
  375 tav_set_params(void *hdl, int setmode, int usemode, audio_params_t *p,
  376     audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
  377 {
  378         struct tav_softc *sc;
  379         bus_space_tag_t iot;
  380         bus_space_handle_t ioh;
  381 
  382         sc = hdl;
  383         iot = sc->sc_iot;
  384         ioh = sc->sc_ioh;
  385 
  386         if (!(setmode & AUMODE_PLAY))
  387                 return 0;
  388 
  389         if (p->encoding == AUDIO_ENCODING_ULAW)
  390                 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM;
  391 
  392         switch(p->encoding) {
  393         default:
  394                 return EINVAL;
  395 
  396         case AUDIO_ENCODING_SLINEAR_BE:
  397 
  398                 /* XXX: todo: add 8bit and mono using software */
  399                 p->precision = 16;
  400                 p->channels = 2;
  401 
  402                 /* XXX: this might depend on the specific board.
  403                    should be handled by the backend */
  404 
  405                 p->sample_rate = 44100;
  406 
  407                 bus_space_write_1(iot, ioh, TAV_STR_SEL,
  408                     TAV_STR_SEL_AUDIO_BYPASS);
  409                 break;
  410 
  411         /* XXX: later: add ULINEAR, and LE using software encoding */
  412 
  413         case AUDIO_ENCODING_MPEG_L1_STREAM:
  414                 /* FALLTHROUGH */
  415         case AUDIO_ENCODING_MPEG_L2_STREAM:
  416                 bus_space_write_1(iot, ioh, TAV_STR_SEL,
  417                     TAV_STR_SEL_MPEG_AUDIO_STREAM);
  418                 p->sample_rate = 44100;
  419                 p->precision = 1;
  420                 break;
  421 
  422         case AUDIO_ENCODING_MPEG_L1_PACKETS:
  423                 /* FALLTHROUGH */
  424         case AUDIO_ENCODING_MPEG_L2_PACKETS:
  425                 bus_space_write_1(iot, ioh, TAV_STR_SEL,
  426                     TAV_STR_SEL_MPEG_AUDIO_PACKETS);
  427                 p->sample_rate = 44100;
  428                 p->precision = 1;
  429                 break;
  430 
  431         case AUDIO_ENCODING_MPEG_L1_SYSTEM:
  432                 /* FALLTHROUGH */
  433         case AUDIO_ENCODING_MPEG_L2_SYSTEM:
  434                 bus_space_write_1(iot, ioh, TAV_STR_SEL,
  435                     TAV_STR_SEL_MPEG_SYSTEM_STREAM);
  436                 p->sample_rate = 44100;
  437                 p->precision = 1;
  438                 break;
  439         }
  440         tav_write_byte(iot, ioh, TAV_RESTART, 1);
  441         do {
  442                 delay(10);
  443         } while (tav_read_byte(iot, ioh, TAV_RESTART));
  444 
  445         return 0;
  446 }
  447 
  448 int
  449 tav_set_port(void *hdl, mixer_ctrl_t *mc)
  450 {
  451         struct tav_softc *sc;
  452 
  453         sc = hdl;
  454         /* dummy */
  455         return 0;
  456 }
  457 
  458 int
  459 tav_get_port(void *hdl, mixer_ctrl_t *mc)
  460 {
  461         struct tav_softc *sc;
  462 
  463         sc = hdl;
  464         /* dummy */
  465         return 0;
  466 }
  467 
  468 int
  469 tav_query_devinfo(void *hdl, mixer_devinfo_t *di)
  470 {
  471         return ENXIO;
  472 }
  473 
  474 int
  475 tav_speaker_ctl(void *hdl, int value)
  476 {
  477         struct tav_softc *sc;
  478         bus_space_tag_t iot;
  479         bus_space_handle_t ioh;
  480 
  481         sc = hdl;
  482         iot = sc->sc_iot;
  483         ioh = sc->sc_ioh;
  484 
  485         tav_write_byte(iot, ioh, TAV_MUTE, !value);
  486 
  487         return 0;
  488 }

Cache object: 75a936eb6c4255f0b4873f0a0f1f6931


[ 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.