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

Cache object: 2c2a6c49562ded57096303e9548f21ca


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