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/bitsy/devuda1341.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 /*
    2  *      SAC/UDA 1341 Audio driver for the Bitsy
    3  *
    4  *      The Philips UDA 1341 sound chip is accessed through the Serial Audio
    5  *      Controller (SAC) of the StrongARM SA-1110.  This is much more a SAC
    6  *      controller than a UDA controller, but we have a devsac.c already.
    7  *
    8  *      The code morphs Nicolas Pitre's <nico@cam.org> Linux controller
    9  *      and Ken's Soundblaster controller.
   10  *
   11  *      The interface should be identical to that of devaudio.c
   12  */
   13 #include        "u.h"
   14 #include        "../port/lib.h"
   15 #include        "mem.h"
   16 #include        "dat.h"
   17 #include        "fns.h"
   18 #include        "../port/error.h"
   19 #include        "io.h"
   20 #include        "sa1110dma.h"
   21 
   22 static int debug = 0;
   23 
   24 /*
   25  * GPIO based L3 bus support.
   26  *
   27  * This provides control of Philips L3 type devices. 
   28  * GPIO lines are used for clock, data and mode pins.
   29  *
   30  * Note: The L3 pins are shared with I2C devices. This should not present
   31  * any problems as long as an I2C start sequence is not generated. This is
   32  * defined as a 1->0 transition on the data lines when the clock is high.
   33  * It is critical this code only allow data transitions when the clock
   34  * is low. This is always legal in L3.
   35  *
   36  * The IIC interface requires the clock and data pin to be LOW when idle. We
   37  * must make sure we leave them in this state.
   38  *
   39  * It appears the read data is generated on the falling edge of the clock
   40  * and should be held stable during the clock high time.
   41  */
   42 
   43 /* 
   44  * L3 setup and hold times (expressed in µs)
   45  */
   46 enum {
   47         L3_AcquireTime =                1,
   48         L3_ReleaseTime =                1,
   49         L3_DataSetupTime =      (190+999)/1000, /* 190 ns */
   50         L3_DataHoldTime =               ( 30+999)/1000,
   51         L3_ModeSetupTime =      (190+999)/1000,
   52         L3_ModeHoldTime =       (190+999)/1000,
   53         L3_ClockHighTime =      (100+999)/1000,
   54         L3_ClockLowTime =               (100+999)/1000,
   55         L3_HaltTime =                   (190+999)/1000,
   56 };
   57 
   58 /* UDA 1341 Registers */
   59 enum {
   60         /* Status0 register */
   61         UdaStatusDC             = 0,    /* 1 bit */
   62         UdaStatusIF             = 1,    /* 3 bits */
   63         UdaStatusSC             = 4,    /* 2 bits */
   64         UdaStatusRST            = 6,    /* 1 bit */
   65 };
   66 
   67 enum {
   68         /* Status1 register */
   69         UdaStatusPC     = 0,    /* 2 bits */
   70         UdaStatusDS     = 2,    /* 1 bit */
   71         UdaStatusPDA    = 3,    /* 1 bit */
   72         UdaStatusPAD    = 4,    /* 1 bit */
   73         UdaStatusIGS    = 5,    /* 1 bit */
   74         UdaStatusOGS    = 6,    /* 1 bit */
   75 };
   76 
   77 /*
   78  * UDA1341 L3 address and command types
   79  */
   80 
   81 enum {
   82         UDA1341_DATA0 = 0,
   83         UDA1341_DATA1,
   84         UDA1341_STATUS,
   85         UDA1341_L3Addr = 0x14,
   86 };
   87 
   88 typedef struct  AQueue  AQueue;
   89 typedef struct  Buf     Buf;
   90 typedef struct  IOstate IOstate;
   91 
   92 enum
   93 {
   94         Qdir            = 0,
   95         Qaudio,
   96         Qvolume,
   97         Qstatus,
   98         Qstats,
   99 
  100         Fmono           = 1,
  101         Fin                     = 2,
  102         Fout                    = 4,
  103 
  104         Aclosed         = 0,
  105         Aread,
  106         Awrite,
  107 
  108         Vaudio          = 0,
  109         Vmic,
  110         Vtreb,
  111         Vbass,
  112         Vspeed,
  113         Vbufsize,
  114         Vfilter,
  115         Vinvert,
  116         Nvol,
  117 
  118         Bufsize         = 4* 1024,      /* 46 ms each */
  119         Nbuf                    = 10,                   /* 1.5 seconds total */
  120 
  121         Speed           = 44100,
  122         Ncmd            = 50,                   /* max volume command words */
  123 };
  124 
  125 enum {
  126         Flushbuf = 0xe0000000,
  127 };
  128 
  129 /* System Clock -- according to the manual, it seems that when the UDA is
  130     configured in non MSB/I2S mode, it uses a divisor of 256 to the 12.288MHz
  131     clock.  The other rates are only supported in MSB mode, which should be 
  132     implemented at some point */
  133 enum {
  134         SC512FS = 0 << 2,
  135         SC384FS = 1 << 2,
  136         SC256FS = 2 << 2,
  137         CLOCKMASK = 3 << 2,
  138 };
  139 
  140 /* Format */
  141 enum {
  142         LSB16 = 1 << 1,
  143         LSB18 = 2 << 1,
  144         LSB20 = 3 << 1,
  145         MSB =   4 << 1,
  146         MSB16 = 5 << 1,
  147         MSB18 = 6 << 1,
  148         MSB20 = 7 << 1,
  149 };
  150 
  151 Dirtab
  152 audiodir[] =
  153 {
  154         ".",                    {Qdir, 0, QTDIR},       0,      DMDIR|0555,
  155         "audio",                {Qaudio},                       0,      0666,
  156         "volume",               {Qvolume},              0,      0666,
  157         "audiostatus",  {Qstatus},                      0,      0444,
  158         "audiostats",   {Qstats},                       0,      0444,
  159 };
  160 
  161 struct  Buf
  162 {
  163         uchar*  virt;
  164         ulong   phys;
  165         uint    nbytes;
  166 };
  167 
  168 struct  IOstate
  169 {
  170         QLock;
  171         Lock                    ilock;
  172         Rendez          vous;
  173         Chan            *chan;          /* chan of open */
  174         int                     dma;                    /* dma chan, alloc on open, free on close */
  175         int                     bufinit;                /* boolean, if buffers allocated */
  176         Buf                     buf[Nbuf];              /* buffers and queues */
  177         volatile Buf    *current;               /* next dma to finish */
  178         volatile Buf    *next;          /* next candidate for dma */
  179         volatile Buf    *filling;               /* buffer being filled */
  180 /* to have defines just like linux — there's a real operating system */
  181 #define emptying filling
  182 };
  183 
  184 static  struct
  185 {
  186         QLock;
  187         int             amode;                  /* Aclosed/Aread/Awrite for /audio */
  188         int             intr;                   /* boolean an interrupt has happened */
  189         int             rivol[Nvol];    /* right/left input/output volumes */
  190         int             livol[Nvol];
  191         int             rovol[Nvol];
  192         int             lovol[Nvol];
  193         ulong   totcount;               /* how many bytes processed since open */
  194         vlong   tottime;                /* time at which totcount bytes were processed */
  195         IOstate i;
  196         IOstate o;
  197 } audio;
  198 
  199 int     zerodma;        /* dma buffer used for sending zero */
  200 
  201 typedef struct Iostats Iostats;
  202 struct Iostats {
  203         ulong   totaldma;
  204         ulong   idledma;
  205         ulong   faildma;
  206         ulong   samedma;
  207         ulong   empties;
  208 };
  209 
  210 static struct
  211 {
  212         ulong   bytes;
  213         Iostats rx, tx;
  214 } iostats;
  215 
  216 static void setaudio(int in, int out, int left, int right, int value);
  217 static void setspeed(int in, int out, int left, int right, int value);
  218 static void setbufsize(int in, int out, int left, int right, int value);
  219 
  220 static  struct
  221 {
  222         char*   name;
  223         int             flag;
  224         int             ilval;          /* initial  values */
  225         int             irval;
  226         void            (*setval)(int, int, int, int, int);
  227 } volumes[] =
  228 {
  229 [Vaudio]        {"audio",               Fout|Fmono,             80,             80,     setaudio },
  230 [Vmic]  {"mic",         Fin|Fmono,                0,              0,    nil },
  231 [Vtreb] {"treb",                Fout|Fmono,             50,             50,     nil },
  232 [Vbass] {"bass",                Fout|Fmono,             50,             50,     nil },
  233 [Vspeed]        {"speed",               Fin|Fout|Fmono, Speed,  Speed,  setspeed },
  234 [Vbufsize]      {"bufsize",     Fin|Fout|Fmono, Bufsize,        Bufsize,        setbufsize },
  235 [Vfilter]       {"filter",              Fout|Fmono,               0,              0,    nil },
  236 [Vinvert]       {"invert",              Fin|Fout|Fmono,   0,              0,    nil },
  237 [Nvol]  {0}
  238 };
  239 
  240 static void     setreg(char *name, int val, int n);
  241 
  242 /*
  243  * Grab control of the IIC/L3 shared pins
  244  */
  245 static void
  246 L3_acquirepins(void)
  247 {
  248         gpioregs->set = (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
  249         gpioregs->direction |=  (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
  250         microdelay(L3_AcquireTime);
  251 }
  252 
  253 /*
  254  * Release control of the IIC/L3 shared pins
  255  */
  256 static void
  257 L3_releasepins(void)
  258 {
  259         gpioregs->direction &= ~(GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
  260         microdelay(L3_ReleaseTime);
  261 }
  262 
  263 /*
  264  * Initialize the interface
  265  */
  266 static void 
  267 L3_init(void)
  268 {
  269         gpioregs->altfunc &= ~(GPIO_L3_SDA_io | GPIO_L3_SCLK_o | GPIO_L3_MODE_o);
  270         L3_releasepins();
  271 }
  272 
  273 /*
  274  * Get a bit. The clock is high on entry and on exit. Data is read after
  275  * the clock low time has expired.
  276  */
  277 static int
  278 L3_getbit(void)
  279 {
  280         int data;
  281 
  282         gpioregs->clear = GPIO_L3_SCLK_o;
  283         microdelay(L3_ClockLowTime);
  284 
  285         data = (gpioregs->level & GPIO_L3_SDA_io) ? 1 : 0;
  286 
  287         gpioregs->set = GPIO_L3_SCLK_o;
  288         microdelay(L3_ClockHighTime);
  289 
  290         return data;
  291 }
  292 
  293 /*
  294  * Send a bit. The clock is high on entry and on exit. Data is sent only
  295  * when the clock is low (I2C compatibility).
  296  */
  297 static void
  298 L3_sendbit(int bit)
  299 {
  300         gpioregs->clear = GPIO_L3_SCLK_o;
  301 
  302         if (bit & 1)
  303                 gpioregs->set = GPIO_L3_SDA_io;
  304         else
  305                 gpioregs->clear = GPIO_L3_SDA_io;
  306 
  307         /* Assumes L3_DataSetupTime < L3_ClockLowTime */
  308         microdelay(L3_ClockLowTime);
  309 
  310         gpioregs->set = GPIO_L3_SCLK_o;
  311         microdelay(L3_ClockHighTime);
  312 }
  313 
  314 /*
  315  * Send a byte. The mode line is set or pulsed based on the mode sequence
  316  * count. The mode line is high on entry and exit. The mod line is pulsed
  317  * before the second data byte and before ech byte thereafter.
  318  */
  319 static void
  320 L3_sendbyte(char data, int mode)
  321 {
  322         int i;
  323 
  324         switch(mode) {
  325         case 0: /* Address mode */
  326                 gpioregs->clear = GPIO_L3_MODE_o;
  327                 break;
  328         case 1: /* First data byte */
  329                 break;
  330         default: /* Subsequent bytes */
  331                 gpioregs->clear = GPIO_L3_MODE_o;
  332                 microdelay(L3_HaltTime);
  333                 gpioregs->set = GPIO_L3_MODE_o;
  334                 break;
  335         }
  336 
  337         microdelay(L3_ModeSetupTime);
  338 
  339         for (i = 0; i < 8; i++)
  340                 L3_sendbit(data >> i);
  341 
  342         if (mode == 0)  /* Address mode */
  343                 gpioregs->set = GPIO_L3_MODE_o;
  344 
  345         microdelay(L3_ModeHoldTime);
  346 }
  347 
  348 /*
  349  * Get a byte. The mode line is set or pulsed based on the mode sequence
  350  * count. The mode line is high on entry and exit. The mod line is pulsed
  351  * before the second data byte and before each byte thereafter. This
  352  * function is never valid with mode == 0 (address cycle) as the address
  353  * is always sent on the bus, not read.
  354  */
  355 static char
  356 L3_getbyte(int mode)
  357 {
  358         char data = 0;
  359         int i;
  360 
  361         switch(mode) {
  362         case 0: /* Address mode - never valid */
  363                 break;
  364         case 1: /* First data byte */
  365                 break;
  366         default: /* Subsequent bytes */
  367                 gpioregs->clear = GPIO_L3_MODE_o;
  368                 microdelay(L3_HaltTime);
  369                 gpioregs->set = GPIO_L3_MODE_o;
  370                 break;
  371         }
  372 
  373         microdelay(L3_ModeSetupTime);
  374 
  375         for (i = 0; i < 8; i++)
  376                 data |= (L3_getbit() << i);
  377 
  378         microdelay(L3_ModeHoldTime);
  379 
  380         return data;
  381 }
  382 
  383 /*
  384  * Write data to a device on the L3 bus. The address is passed as well as
  385  * the data and length. The length written is returned. The register space
  386  * is encoded in the address (low two bits are set and device address is
  387  * in the upper 6 bits).
  388  */
  389 static int
  390 L3_write(uchar addr, uchar *data, int len)
  391 {
  392         int mode = 0;
  393         int bytes = len;
  394 
  395         L3_acquirepins();
  396         L3_sendbyte(addr, mode++);
  397         while(len--)
  398                 L3_sendbyte(*data++, mode++);
  399         L3_releasepins();
  400         return bytes;
  401 }
  402 
  403 /*
  404  * Read data from a device on the L3 bus. The address is passed as well as
  405  * the data and length. The length read is returned. The register space
  406  * is encoded in the address (low two bits are set and device address is
  407  * in the upper 6 bits).
  408 
  409  * Commented out, not used
  410 static int
  411 L3_read(uchar addr, uchar *data, int len)
  412 {
  413         int mode = 0;
  414         int bytes = len;
  415 
  416         L3_acquirepins();
  417         L3_sendbyte(addr, mode++);
  418         gpioregs->direction &= ~(GPIO_L3_SDA_io);
  419         while(len--)
  420                 *data++ = L3_getbyte(mode++);
  421         L3_releasepins();
  422         return bytes;
  423 }
  424  */
  425 
  426 void
  427 audiomute(int on)
  428 {
  429         egpiobits(EGPIO_audio_mute, on);
  430 }
  431 
  432 static  char    Emode[]         = "illegal open mode";
  433 static  char    Evolume[]       = "illegal volume specifier";
  434 
  435 static void
  436 bufinit(IOstate *b)
  437 {
  438         int i;
  439 
  440         if (debug) print("bufinit\n");
  441         for (i = 0; i < Nbuf; i++) {
  442                 b->buf[i].virt = xalloc(Bufsize);
  443                 b->buf[i].phys = PADDR(b->buf[i].virt);
  444                 memset(b->buf[i].virt, 0xAA, Bufsize);
  445         }
  446         b->bufinit = 1;
  447 };
  448 
  449 static void
  450 setempty(IOstate *b)
  451 {
  452         int i;
  453 
  454         if (debug) print("setempty\n");
  455         for (i = 0; i < Nbuf; i++) {
  456                 b->buf[i].nbytes = 0;
  457         }
  458         b->filling = b->buf;
  459         b->current = b->buf;
  460         b->next = b->buf;
  461 }
  462 
  463 static int
  464 audioqnotempty(void *x)
  465 {
  466         IOstate *s = x;
  467 
  468         return dmaidle(s->dma) || s->emptying != s->current;
  469 }
  470 
  471 static int
  472 audioqnotfull(void *x)
  473 {
  474         IOstate *s = x;
  475 
  476         return dmaidle(s->dma) || s->filling != s->current;
  477 }
  478 
  479 SSPregs *sspregs;
  480 MCPregs *mcpregs;
  481 
  482 static void
  483 audioinit(void)
  484 {
  485         /* Turn MCP operations off */
  486         mcpregs = mapspecial(MCPREGS, sizeof(MCPregs));
  487         mcpregs->status &= ~(1<<16);
  488 
  489         sspregs = mapspecial(SSPREGS, sizeof(SSPregs));
  490 
  491 }
  492 
  493 uchar   status0[1]              = {0x02};
  494 uchar   status1[1]              = {0x80};
  495 uchar   data00[1]               = {0x00};               /* volume control, bits 0 – 5 */
  496 uchar   data01[1]               = {0x40};
  497 uchar   data02[1]               = {0x80};
  498 uchar   data0e0[2]      = {0xc0, 0xe0};
  499 uchar   data0e1[2]      = {0xc1, 0xe0};
  500 uchar   data0e2[2]      = {0xc2, 0xf2};
  501 /* there is no data0e3 */
  502 uchar   data0e4[2]      = {0xc4, 0xe0};
  503 uchar   data0e5[2]      = {0xc5, 0xe0};
  504 uchar   data0e6[2]      = {0xc6, 0xe3};
  505 
  506 static void
  507 enable(void)
  508 {
  509         uchar   data[1];
  510 
  511         L3_init();
  512 
  513         /* Setup the uarts */
  514         ppcregs->assignment &= ~(1<<18);
  515 
  516         sspregs->control0 = 0;
  517         sspregs->control0 = 0x031f; /* 16 bits, TI frames, serial clock rate 3 */
  518         sspregs->control1 = 0x0020; /* ext clock */
  519         sspregs->control0 = 0x039f;     /* enable */
  520 
  521         /* Enable the audio power */
  522         audioicpower(1);
  523         egpiobits(EGPIO_codec_reset, 1);
  524 
  525         setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
  526 
  527         data[0] = status0[0] | 1 << UdaStatusRST;
  528         L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1 );
  529         gpioregs->clear = EGPIO_codec_reset;
  530         gpioregs->set = EGPIO_codec_reset;
  531         /* write uda 1341 status[0] */
  532         data[0] = status0[0];
  533         L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1);
  534 
  535         if (debug)
  536                 print("enable:  status0 = 0x%2.2ux\n", data[0]);
  537 
  538         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  539         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
  540         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e2, 2);
  541         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e6, 2 );
  542 
  543         if (debug) {
  544                 print("enable:  status0 = 0x%2.2ux\n", data[0]);
  545                 print("enable:  status1 = 0x%2.2ux\n", status1[0]);
  546                 print("enable:  data02  = 0x%2.2ux\n", data02[0]);
  547                 print("enable:  data0e2 = 0x%4.4ux\n", data0e2[0] | data0e2[1]<<8);
  548                 print("enable:  data0e4 = 0x%4.4ux\n", data0e4[0] | data0e4[1]<<8);
  549                 print("enable:  data0e6 = 0x%4.4ux\n", data0e6[0] | data0e6[1]<<8);
  550                 print("enable:  sspregs->control0 = 0x%lux\n", sspregs->control0);
  551                 print("enable:  sspregs->control1 = 0x%lux\n", sspregs->control1);
  552         }
  553 }
  554 
  555 static  void
  556 resetlevel(void)
  557 {
  558         int i;
  559 
  560         for(i=0; volumes[i].name; i++) {
  561                 audio.lovol[i] = volumes[i].ilval;
  562                 audio.rovol[i] = volumes[i].irval;
  563                 audio.livol[i] = volumes[i].ilval;
  564                 audio.rivol[i] = volumes[i].irval;
  565         }
  566 }
  567 
  568 static void
  569 mxvolume(void) {
  570         int *left, *right;
  571 
  572         setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
  573         if (!dmaidle(audio.i.dma) || !dmaidle(audio.o.dma))
  574                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status0, 1);
  575 
  576         if(audio.amode & Aread){
  577                 left = audio.livol;
  578                 right = audio.rivol;
  579                 if (left[Vmic]+right[Vmic] == 0) {
  580                         /* Turn on automatic gain control (AGC) */
  581                         data0e4[1] |= 0x10;
  582                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
  583                 } else {
  584                         int v;
  585                         /* Turn on manual gain control */
  586                         v = ((left[Vmic]+right[Vmic])*0x7f/200)&0x7f;
  587                         data0e4[1] &= ~0x13;
  588                         data0e5[1] &= ~0x1f;
  589                         data0e4[1] |= v & 0x3;
  590                         data0e5[0] |= (v & 0x7c)<<6;
  591                         data0e5[1] |= (v & 0x7c)>>2;
  592                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
  593                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e5, 2 );
  594                 }
  595                 if (left[Vinvert]+right[Vinvert] == 0)
  596                         status1[0] &= ~0x04;
  597                 else
  598                         status1[0] |= 0x04;
  599                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  600                 if (debug) {
  601                         print("mxvolume:        status1 = 0x%2.2ux\n", status1[0]);
  602                         print("mxvolume:        data0e4 = 0x%4.4ux\n", data0e4[0]|data0e4[0]<<8);
  603                         print("mxvolume:        data0e5 = 0x%4.4ux\n", data0e5[0]|data0e5[0]<<8);
  604                 }
  605         }
  606         if(audio.amode & Awrite){
  607                 left = audio.lovol;
  608                 right = audio.rovol;
  609                 data00[0] &= ~0x3f;
  610                 data00[0] |= ((200-left[Vaudio]-right[Vaudio])*0x3f/200)&0x3f;
  611                 if (left[Vtreb]+right[Vtreb] <= 100
  612                  && left[Vbass]+right[Vbass] <= 100)
  613                         /* settings neutral */
  614                         data02[0] &= ~0x03;
  615                 else {
  616                         data02[0] |= 0x03;
  617                         data01[0] &= ~0x3f;
  618                         data01[0] |= ((left[Vtreb]+right[Vtreb]-100)*0x3/100)&0x03;
  619                         data01[0] |= (((left[Vbass]+right[Vbass]-100)*0xf/100)&0xf)<<2;
  620                 }
  621                 if (left[Vfilter]+right[Vfilter] == 0)
  622                         data02[0] &= ~0x10;
  623                 else
  624                         data02[0]|= 0x10;
  625                 if (left[Vinvert]+right[Vinvert] == 0)
  626                         status1[0] &= ~0x10;
  627                 else
  628                         status1[0] |= 0x10;
  629                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  630                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
  631                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data01, 1);
  632                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
  633                 if (debug) {
  634                         print("mxvolume:        status1 = 0x%2.2ux\n", status1[0]);
  635                         print("mxvolume:        data00  = 0x%2.2ux\n", data00[0]);
  636                         print("mxvolume:        data01  = 0x%2.2ux\n", data01[0]);
  637                         print("mxvolume:        data02  = 0x%2.2ux\n", data02[0]);
  638                 }
  639         }
  640 }
  641 
  642 static void
  643 setreg(char *name, int val, int n)
  644 {
  645         uchar x[2];
  646         int i;
  647 
  648         x[0] = val;
  649         x[1] = val>>8;
  650 
  651         if(strcmp(name, "pause") == 0){
  652                 for(i = 0; i < n; i++)
  653                         microdelay(val);
  654                 return;
  655         }
  656 
  657         switch(n){
  658         case 1:
  659         case 2:
  660                 break;
  661         default:
  662                 error("setreg");
  663         }
  664 
  665         if(strcmp(name, "status") == 0){
  666                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, x, n);
  667         } else if(strcmp(name, "data0") == 0){
  668                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, x, n);
  669         } else if(strcmp(name, "data1") == 0){
  670                 L3_write(UDA1341_L3Addr | UDA1341_DATA1, x, n);
  671         } else
  672                 error("setreg");
  673 }
  674 
  675 static void
  676 outenable(void) {
  677         /* turn on DAC, set output gain switch */
  678         audioamppower(1);
  679         audiomute(0);
  680         status1[0] |= 0x41;
  681         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  682         /* set volume */
  683         data00[0] |= 0xf;
  684         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
  685         if (debug) {
  686                 print("outenable:       status1 = 0x%2.2ux\n", status1[0]);
  687                 print("outenable:       data00  = 0x%2.2ux\n", data00[0]);
  688         }
  689 }
  690 
  691 static void
  692 outdisable(void) {
  693         dmastop(audio.o.dma);
  694         /* turn off DAC, clear output gain switch */
  695         audiomute(1);
  696         status1[0] &= ~0x41;
  697         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  698         if (debug) {
  699                 print("outdisable:      status1 = 0x%2.2ux\n", status1[0]);
  700         }
  701         audioamppower(0);
  702 }
  703 
  704 static void
  705 inenable(void) {
  706         /* turn on ADC, set input gain switch */
  707         status1[0] |= 0x22;
  708         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  709         if (debug) {
  710                 print("inenable:        status1 = 0x%2.2ux\n", status1[0]);
  711         }
  712 }
  713 
  714 static void
  715 indisable(void) {
  716         dmastop(audio.i.dma);
  717         /* turn off ADC, clear input gain switch */
  718         status1[0] &= ~0x22;
  719         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  720         if (debug) {
  721                 print("indisable:       status1 = 0x%2.2ux\n", status1[0]);
  722         }
  723 }
  724 
  725 static void
  726 sendaudio(IOstate *s) {
  727         /* interrupt routine calls this too */
  728         int n;
  729 
  730         if (debug > 1) print("#A: sendaudio\n");
  731         ilock(&s->ilock);
  732         if ((audio.amode &  Aread) && s->next == s->filling && dmaidle(s->dma)) {
  733                 // send an empty buffer to provide an input clock
  734                 zerodma |= dmastart(s->dma, Flushbuf, volumes[Vbufsize].ilval) & 0xff;
  735                 if (zerodma == 0)
  736                         if (debug) print("emptyfail\n");
  737                 iostats.tx.empties++;
  738                 iunlock(&s->ilock);
  739                 return;
  740         }
  741         while (s->next != s->filling) {
  742                 s->next->nbytes &= ~0x3;        /* must be a multiple of 4 */
  743                 if(s->next->nbytes) {
  744                         if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) {
  745                                 iostats.tx.faildma++;
  746                                 break;
  747                         }
  748                         iostats.tx.totaldma++;
  749                         switch (n >> 8) {
  750                         case 1:
  751                                 iostats.tx.idledma++;
  752                                 break;
  753                         case 3:
  754                                 iostats.tx.faildma++;
  755                                 break;
  756                         }
  757                         if (debug) {
  758                                 if (debug > 1)
  759                                         print("dmastart @%p\n", s->next);
  760                                 else
  761                                         iprint("+");
  762                         }
  763                         s->next->nbytes = 0;
  764                 }
  765                 s->next++;
  766                 if (s->next == &s->buf[Nbuf])
  767                         s->next = &s->buf[0];
  768         }
  769         iunlock(&s->ilock);
  770 }
  771 
  772 static void
  773 recvaudio(IOstate *s) {
  774         /* interrupt routine calls this too */
  775         int n;
  776 
  777         if (debug > 1) print("#A: recvaudio\n");
  778         ilock(&s->ilock);
  779         while (s->next != s->emptying) {
  780                 assert(s->next->nbytes == 0);
  781                 if ((n = dmastart(s->dma, s->next->phys, volumes[Vbufsize].ilval)) == 0) {
  782                         iostats.rx.faildma++;
  783                         break;
  784                 }
  785                 iostats.rx.totaldma++;
  786                 switch (n >> 8) {
  787                 case 1:
  788                         iostats.rx.idledma++;
  789                         break;
  790                 case 3:
  791                         iostats.rx.faildma++;
  792                         break;
  793                 }
  794                 if (debug) {
  795                         if (debug > 1)
  796                                 print("dmastart @%p\n", s->next);
  797                         else
  798                                 iprint("+");
  799                 }
  800                 s->next++;
  801                 if (s->next == &s->buf[Nbuf])
  802                         s->next = &s->buf[0];
  803         }
  804         iunlock(&s->ilock);
  805 }
  806 
  807 void
  808 audiopower(int flag) {
  809         IOstate *s;
  810 
  811         if (debug) {
  812                 iprint("audiopower %d\n", flag);
  813         }
  814         if (flag) {
  815                 /* power on only when necessary */
  816                 if (audio.amode) {
  817                         audioamppower(1);
  818                         audioicpower(1);
  819                         egpiobits(EGPIO_codec_reset, 1);
  820                         enable();
  821                         if (audio.amode & Aread) {
  822                                 inenable();
  823                                 s = &audio.i;
  824                                 dmareset(s->dma, 1, 0, 4, 2, SSPRecvDMA, Port4SSP);
  825                                 recvaudio(s);
  826                         }
  827                         if (audio.amode & Awrite) {
  828                                 outenable();
  829                                 s = &audio.o;
  830                                 dmareset(s->dma, 0, 0, 4, 2, SSPXmitDMA, Port4SSP);
  831                                 sendaudio(s);
  832                         }
  833                         mxvolume();
  834                 }
  835         } else {
  836                 /* power off */
  837                 if (audio.amode & Aread)
  838                         indisable();
  839                 if (audio.amode & Awrite)
  840                         outdisable();
  841                 egpiobits(EGPIO_codec_reset, 0);
  842                 audioamppower(0);
  843                 audioicpower(0);
  844         }
  845 }
  846 
  847 static void
  848 audiointr(void *x, ulong ndma) {
  849         IOstate *s = x;
  850 
  851         if (debug) {
  852                 if (debug > 1)
  853                         iprint("#A: audio interrupt @%p\n", s->current);
  854                 else
  855                         iprint("-");
  856         }
  857         if (s == &audio.i || (ndma & ~zerodma)) {
  858                 /* A dma, not of a zero buffer completed, update current
  859                  * Only interrupt routine touches s->current
  860                  */
  861                 s->current->nbytes = (s == &audio.i)? volumes[Vbufsize].ilval: 0;
  862                 s->current++;
  863                 if (s->current == &s->buf[Nbuf])
  864                         s->current = &s->buf[0];
  865         }
  866         if (ndma) {
  867                 if (s == &audio.o) {
  868                         zerodma &= ~ndma;
  869                         sendaudio(s);
  870                 } else if (s == &audio.i)
  871                         recvaudio(s);
  872         }
  873         wakeup(&s->vous);
  874 }
  875 
  876 static Chan*
  877 audioattach(char *param)
  878 {
  879         return devattach('A', param);
  880 }
  881 
  882 static Walkqid*
  883 audiowalk(Chan *c, Chan *nc, char **name, int nname)
  884 {
  885         return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
  886 }
  887 
  888 static int
  889 audiostat(Chan *c, uchar *db, int n)
  890 {
  891         return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
  892 }
  893 
  894 static Chan*
  895 audioopen(Chan *c, int mode)
  896 {
  897         IOstate *s;
  898         int omode = mode;
  899 
  900         switch((ulong)c->qid.path) {
  901         default:
  902                 error(Eperm);
  903                 break;
  904 
  905         case Qstatus:
  906         case Qstats:
  907                 if((omode&7) != OREAD)
  908                         error(Eperm);
  909         case Qvolume:
  910         case Qdir:
  911                 break;
  912 
  913         case Qaudio:
  914                 omode = (omode & 0x7) + 1;
  915                 if (omode & ~(Aread | Awrite))
  916                         error(Ebadarg);
  917                 qlock(&audio);
  918                 if(audio.amode & omode){
  919                         qunlock(&audio);
  920                         error(Einuse);
  921                 }
  922                 enable();
  923                 memset(&iostats, 0, sizeof(iostats));
  924                 if (omode & Aread) {
  925                         inenable();
  926                         s = &audio.i;
  927                         if(s->bufinit == 0)
  928                                 bufinit(s);
  929                         setempty(s);
  930                         s->emptying = &s->buf[Nbuf-1];
  931                         s->chan = c;
  932                         s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
  933                         audio.amode |= Aread;
  934                 }
  935                 if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) {
  936                         s = &audio.o;
  937                         if(s->bufinit == 0)
  938                                 bufinit(s);
  939                         setempty(s);
  940                         s->chan = c;
  941                         s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s);
  942                 }       
  943                 if (omode & Awrite) {
  944                         audio.amode |= Awrite;
  945                         outenable();
  946                 }
  947                 mxvolume();
  948                 if (audio.amode & Aread)
  949                         sendaudio(&audio.o);
  950                 qunlock(&audio);
  951                         
  952                 if (debug) print("open done\n");
  953                 break;
  954         }
  955         c = devopen(c, mode, audiodir, nelem(audiodir), devgen);
  956         c->mode = openmode(mode);
  957         c->flag |= COPEN;
  958         c->offset = 0;
  959 
  960         return c;
  961 }
  962 
  963 static void
  964 audioclose(Chan *c)
  965 {
  966         IOstate *s;
  967 
  968         switch((ulong)c->qid.path) {
  969         default:
  970                 error(Eperm);
  971                 break;
  972 
  973         case Qdir:
  974         case Qvolume:
  975         case Qstatus:
  976         case Qstats:
  977                 break;
  978 
  979         case Qaudio:
  980                 if (debug > 1) print("#A: close\n");
  981                 if(c->flag & COPEN) {
  982                         qlock(&audio);
  983                         if (audio.i.chan == c) {
  984                                 /* closing the read end */
  985                                 audio.amode &= ~Aread;
  986                                 s = &audio.i;
  987                                 qlock(s);
  988                                 indisable();
  989                                 setempty(s);
  990                                 dmafree(s->dma);
  991                                 qunlock(s);
  992                                 if ((audio.amode & Awrite) == 0) {
  993                                         s = &audio.o;
  994                                         qlock(s);
  995                                         while(waserror())
  996                                                 ;
  997                                         dmawait(s->dma);
  998                                         poperror();
  999                                         outdisable();
 1000                                         setempty(s);
 1001                                         dmafree(s->dma);
 1002                                         qunlock(s);
 1003                                 }
 1004                         }
 1005                         if (audio.o.chan == c) {
 1006                                 /* closing the write end */
 1007                                 audio.amode &= ~Awrite;
 1008                                 s = &audio.o;
 1009                                 qlock(s);
 1010                                 if (s->filling->nbytes) {
 1011                                         /* send remaining partial buffer */
 1012                                         s->filling++;
 1013                                         if (s->filling == &s->buf[Nbuf])
 1014                                                 s->filling = &s->buf[0];
 1015                                         sendaudio(s);
 1016                                 }
 1017                                 while(waserror())
 1018                                         ;
 1019                                 dmawait(s->dma);
 1020                                 poperror();
 1021                                 outdisable();
 1022                                 setempty(s);
 1023                                 if ((audio.amode & Aread) == 0)
 1024                                         dmafree(s->dma);
 1025                                 qunlock(s);
 1026                         }
 1027                         if (audio.amode == 0) {
 1028                                 /* turn audio off */
 1029                                 egpiobits(EGPIO_codec_reset, 0);
 1030                                 audioicpower(0);
 1031                         }
 1032                         qunlock(&audio);
 1033                 }
 1034                 break;
 1035         }
 1036 }
 1037 
 1038 static long
 1039 audioread(Chan *c, void *v, long n, vlong off)
 1040 {
 1041         int liv, riv, lov, rov;
 1042         long m, n0;
 1043         char buf[300];
 1044         int j;
 1045         ulong offset = off;
 1046         char *p;
 1047         IOstate *s;
 1048 
 1049         n0 = n;
 1050         p = v;
 1051         switch((ulong)c->qid.path) {
 1052         default:
 1053                 error(Eperm);
 1054                 break;
 1055 
 1056         case Qdir:
 1057                 return devdirread(c, p, n, audiodir, nelem(audiodir), devgen);
 1058 
 1059         case Qaudio:
 1060                 if (debug > 1) print("#A: read %ld\n", n);
 1061                 if((audio.amode & Aread) == 0)
 1062                         error(Emode);
 1063                 s = &audio.i;
 1064                 qlock(s);
 1065                 if(waserror()){
 1066                         qunlock(s);
 1067                         nexterror();
 1068                 }
 1069                 while(n > 0) {
 1070                         if(s->emptying->nbytes == 0) {
 1071                                 if (debug > 1) print("#A: emptied @%p\n", s->emptying);
 1072                                 recvaudio(s);
 1073                                 s->emptying++;
 1074                                 if (s->emptying == &s->buf[Nbuf])
 1075                                         s->emptying = s->buf;
 1076                         }
 1077                         /* wait if dma in progress */
 1078                         while (!dmaidle(s->dma) && s->emptying == s->current) {
 1079                                 if (debug > 1) print("#A: sleep\n");
 1080                                 sleep(&s->vous, audioqnotempty, s);
 1081                         }
 1082 
 1083                         m = (s->emptying->nbytes > n)? n: s->emptying->nbytes;
 1084                         memmove(p, s->emptying->virt + volumes[Vbufsize].ilval - 
 1085                                           s->emptying->nbytes, m);
 1086 
 1087                         s->emptying->nbytes -= m;
 1088                         n -= m;
 1089                         p += m;
 1090                 }
 1091                 poperror();
 1092                 qunlock(s);
 1093                 break;
 1094 
 1095         case Qstatus:
 1096                 buf[0] = 0;
 1097                 snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",
 1098                         audio.totcount, audio.tottime);
 1099                 return readstr(offset, p, n, buf);
 1100 
 1101         case Qstats:
 1102                 buf[0] = 0;
 1103                 snprint(buf, sizeof(buf), 
 1104                             "bytes %lud\nRX dmas %lud, while idle %lud, while busy %lud, "
 1105                             "out-of-order %lud, empty dmas %lud\n"
 1106                             "TX dmas %lud, while idle %lud, while busy %lud, "
 1107                             "out-of-order %lud, empty dmas %lud\n",
 1108                             iostats.bytes, iostats.rx.totaldma, iostats.rx.idledma, 
 1109                             iostats.rx.faildma, iostats.rx.samedma, iostats.rx.empties,
 1110                             iostats.tx.totaldma, iostats.tx.idledma, 
 1111                             iostats.tx.faildma, iostats.tx.samedma, iostats.tx.empties);
 1112 
 1113                 return readstr(offset, p, n, buf);
 1114 
 1115         case Qvolume:
 1116                 j = 0;
 1117                 buf[0] = 0;
 1118                 for(m=0; volumes[m].name; m++){
 1119                         if (m == Vaudio) {
 1120                                 liv = audio.livol[m];
 1121                                 riv = audio.rivol[m];
 1122                                 lov = audio.lovol[m];
 1123                                 rov = audio.rovol[m];
 1124                         }
 1125                         else {
 1126                                 lov = liv = volumes[m].ilval;
 1127                                 rov = riv = volumes[m].irval;
 1128                         }
 1129         
 1130                         j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
 1131                         if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
 1132                                 if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
 1133                                         j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
 1134                                 else{
 1135                                         if(volumes[m].flag & Fin)
 1136                                                 j += snprint(buf+j, sizeof(buf)-j,
 1137                                                         " in %d", liv);
 1138                                         if(volumes[m].flag & Fout)
 1139                                                 j += snprint(buf+j, sizeof(buf)-j,
 1140                                                         " out %d", lov);
 1141                                 }
 1142                         }else{
 1143                                 if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
 1144                                     liv==lov && riv==rov)
 1145                                         j += snprint(buf+j, sizeof(buf)-j,
 1146                                                 " left %d right %d",
 1147                                                 liv, riv);
 1148                                 else{
 1149                                         if(volumes[m].flag & Fin)
 1150                                                 j += snprint(buf+j, sizeof(buf)-j,
 1151                                                         " in left %d right %d",
 1152                                                         liv, riv);
 1153                                         if(volumes[m].flag & Fout)
 1154                                                 j += snprint(buf+j, sizeof(buf)-j,
 1155                                                         " out left %d right %d",
 1156                                                         lov, rov);
 1157                                 }
 1158                         }
 1159                         j += snprint(buf+j, sizeof(buf)-j, "\n");
 1160                 }
 1161                 return readstr(offset, p, n, buf);
 1162         }
 1163         return n0-n;
 1164 }
 1165 
 1166 static void
 1167 setaudio(int in, int out, int left, int right, int value)
 1168 {
 1169         if (value < 0 || value > 100) 
 1170                 error(Evolume);
 1171         if(left && out)
 1172                 audio.lovol[Vaudio] = value;
 1173         if(left && in)
 1174                 audio.livol[Vaudio] = value;
 1175         if(right && out)
 1176                 audio.rovol[Vaudio] = value;
 1177         if(right && in)
 1178                 audio.rivol[Vaudio] = value;
 1179 }
 1180 
 1181 static void 
 1182 setspeed(int, int, int, int, int speed)
 1183 {
 1184         uchar   clock;
 1185 
 1186         /* external clock configured for 44100 samples/sec */
 1187         switch (speed) {
 1188         case 32000:
 1189                 /* 00 */
 1190                 gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
 1191                 clock = SC384FS;        /* Only works in MSB mode! */
 1192                 break;
 1193         case 48000:
 1194                 /* 00 */
 1195                 gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
 1196                 clock = SC256FS;
 1197                 break;
 1198         default:
 1199                 speed = 44100;
 1200         case 44100:
 1201                 /* 01 */
 1202                 gpioregs->set = GPIO_CLK_SET0_o;
 1203                 gpioregs->clear = GPIO_CLK_SET1_o;
 1204                 clock = SC256FS;
 1205                 break;
 1206         case 8000:
 1207                 /* 10 */
 1208                 gpioregs->set = GPIO_CLK_SET1_o;
 1209                 gpioregs->clear = GPIO_CLK_SET0_o;
 1210                 clock = SC512FS;        /* Only works in MSB mode! */
 1211                 break;
 1212         case 16000:
 1213                 /* 10 */
 1214                 gpioregs->set = GPIO_CLK_SET1_o;
 1215                 gpioregs->clear = GPIO_CLK_SET0_o;
 1216                 clock = SC256FS;
 1217                 break;
 1218         case 11025:
 1219                 /* 11 */
 1220                 gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
 1221                 clock = SC512FS;        /* Only works in MSB mode! */
 1222                 break;
 1223         case 22050:
 1224                 /* 11 */
 1225                 gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
 1226                 clock = SC256FS;
 1227                 break;
 1228         }
 1229 
 1230         /* Wait for the UDA1341 to wake up */
 1231         delay(100);
 1232 
 1233         /* Reset the chip */
 1234         status0[0] &= ~CLOCKMASK;
 1235 
 1236         status0[0] |=clock;
 1237         volumes[Vspeed].ilval = speed;
 1238 }
 1239 
 1240 static void
 1241 setbufsize(int, int, int, int, int value)
 1242 {
 1243         if ((value % 8) != 0 || value < 8 || value >= Bufsize)
 1244                 error(Ebadarg);
 1245         volumes[Vbufsize].ilval = value;
 1246 }
 1247 
 1248 static long
 1249 audiowrite(Chan *c, void *vp, long n, vlong)
 1250 {
 1251         long m, n0;
 1252         int i, v, left, right, in, out;
 1253         char *p;
 1254         IOstate *a;
 1255         Cmdbuf *cb;
 1256 
 1257         p = vp;
 1258         n0 = n;
 1259         switch((ulong)c->qid.path) {
 1260         default:
 1261                 error(Eperm);
 1262                 break;
 1263 
 1264         case Qvolume:
 1265                 v = Vaudio;
 1266                 left = 1;
 1267                 right = 1;
 1268                 in = 1;
 1269                 out = 1;
 1270                 cb = parsecmd(p, n);
 1271                 if(waserror()){
 1272                         free(cb);
 1273                         nexterror();
 1274                 }
 1275 
 1276                 for(i = 0; i < cb->nf; i++){
 1277                         /*
 1278                          * a number is volume
 1279                          */
 1280                         if(cb->f[i][0] >= '' && cb->f[i][0] <= '9') {
 1281                                 m = strtoul(cb->f[i], 0, 10);
 1282                                 if (volumes[v].setval)
 1283                                         volumes[v].setval(in, out, left, right, m);
 1284                                 goto cont0;
 1285                         }
 1286 
 1287                         for(m=0; volumes[m].name; m++) {
 1288                                 if(strcmp(cb->f[i], volumes[m].name) == 0) {
 1289                                         v = m;
 1290                                         in = 1;
 1291                                         out = 1;
 1292                                         left = 1;
 1293                                         right = 1;
 1294                                         goto cont0;
 1295                                 }
 1296                         }
 1297 
 1298                         if(strcmp(cb->f[i], "reset") == 0) {
 1299                                 resetlevel();
 1300                                 goto cont0;
 1301                         }
 1302                         if(strcmp(cb->f[i], "debug") == 0) {
 1303                                 debug = debug?0:1;
 1304                                 goto cont0;
 1305                         }
 1306                         if(strcmp(cb->f[i], "in") == 0) {
 1307                                 in = 1;
 1308                                 out = 0;
 1309                                 goto cont0;
 1310                         }
 1311                         if(strcmp(cb->f[i], "out") == 0) {
 1312                                 in = 0;
 1313                                 out = 1;
 1314                                 goto cont0;
 1315                         }
 1316                         if(strcmp(cb->f[i], "left") == 0) {
 1317                                 left = 1;
 1318                                 right = 0;
 1319                                 goto cont0;
 1320                         }
 1321                         if(strcmp(cb->f[i], "right") == 0) {
 1322                                 left = 0;
 1323                                 right = 1;
 1324                                 goto cont0;
 1325                         }
 1326                         if(strcmp(cb->f[i], "reg") == 0) {
 1327                                 if(cb->nf < 3)
 1328                                         error(Evolume);
 1329                                 setreg(cb->f[1], atoi(cb->f[2]), cb->nf == 4 ? atoi(cb->f[3]):1);
 1330                                 return n0;
 1331                         }
 1332                         error(Evolume);
 1333                         break;
 1334                 cont0:;
 1335                 }
 1336                 mxvolume();
 1337                 poperror();
 1338                 free(cb);
 1339                 break;
 1340 
 1341         case Qaudio:
 1342                 if (debug > 1) print("#A: write %ld\n", n);
 1343                 if((audio.amode & Awrite) == 0)
 1344                         error(Emode);
 1345                 a = &audio.o;
 1346                 qlock(a);
 1347                 if(waserror()){
 1348                         qunlock(a);
 1349                         nexterror();
 1350                 }
 1351                 while(n > 0) {
 1352                         /* wait if dma in progress */
 1353                         while (!dmaidle(a->dma) && !zerodma && a->filling == a->current) {
 1354                                 if (debug > 1) print("#A: sleep\n");
 1355                                 sleep(&a->vous, audioqnotfull, a);
 1356                         }
 1357                         m = volumes[Vbufsize].ilval - a->filling->nbytes;
 1358                         if(m > n)
 1359                                 m = n;
 1360                         memmove(a->filling->virt + a->filling->nbytes, p, m);
 1361 
 1362                         a->filling->nbytes += m;
 1363                         n -= m;
 1364                         p += m;
 1365                         if(a->filling->nbytes >= volumes[Vbufsize].ilval) {
 1366                                 if (debug > 1) print("#A: filled @%p\n", a->filling);
 1367                                 a->filling++;
 1368                                 if (a->filling == &a->buf[Nbuf])
 1369                                         a->filling = a->buf;
 1370                                 sendaudio(a);
 1371                         }
 1372                 }
 1373                 poperror();
 1374                 qunlock(a);
 1375                 break;
 1376         }
 1377         return n0 - n;
 1378 }
 1379 
 1380 Dev uda1341devtab = {
 1381         'A',
 1382         "audio",
 1383 
 1384         devreset,
 1385         audioinit,
 1386         devshutdown,
 1387         audioattach,
 1388         audiowalk,
 1389         audiostat,
 1390         audioopen,
 1391         devcreate,
 1392         audioclose,
 1393         audioread,
 1394         devbread,
 1395         audiowrite,
 1396         devbwrite,
 1397         devremove,
 1398         devwstat,
 1399         audiopower,
 1400 };

Cache object: 4833402264601168382b8543f7fecbcd


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