linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: ppopov@linux-mips.org
Date: Tue, 08 Feb 2005 07:07:57 +0000
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     ppopov@ftp.linux-mips.org       05/02/08 07:07:51

Modified files:
        drivers/sound  : Tag: linux_2_4 au1550_i2s.c 

Log message:
        Bug fixes and updates for au1200.

diff -urN linux/drivers/sound/au1550_i2s.c linux/drivers/sound/au1550_i2s.c
--- linux/drivers/sound/Attic/au1550_i2s.c      2004/10/17 17:20:00     1.1.2.1
+++ linux/drivers/sound/Attic/au1550_i2s.c      2005/02/08 07:07:50     1.1.2.2
@@ -41,6 +41,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -62,7 +63,45 @@
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/au1000.h>
+
+#if defined(CONFIG_SOC_AU1550)
 #include <asm/pb1550.h>
+#endif
+
+#if defined(CONFIG_MIPS_PB1200)
+#define WM8731
+#define WM_MODE_USB
+#include <asm/pb1200.h>
+#endif
+
+#if defined(CONFIG_MIPS_FICMMP)
+#define WM8721
+#define WM_MODE_NORMAL
+#include <asm/ficmmp.h>
+#endif
+
+
+#define WM_VOLUME_MIN  47
+#define WM_VOLUME_SCALE        80
+
+#if defined(WM8731)
+       /* OSS interface to the wm i2s.. */
+       #define CODEC_NAME "Wolfson WM8731 I2S"
+       #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM | SOUND_MASK_LINE)
+       #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK | SOUND_MASK_MIC)
+       #define WM_I2S_RECORD_MASK (SOUND_MASK_MIC | SOUND_MASK_LINE1 | 
SOUND_MASK_LINE)
+#elif defined(WM8721)
+       #define CODEC_NAME "Wolfson WM8721 I2S"
+       #define WM_I2S_STEREO_MASK (SOUND_MASK_PCM)
+       #define WM_I2S_SUPPORTED_MASK (WM_I2S_STEREO_MASK)
+       #define WM_I2S_RECORD_MASK (0)
+#endif
+
+
+#define supported_mixer(FOO) ((FOO >= 0) && \
+                                    (FOO < SOUND_MIXER_NRDEVICES) && \
+                                    WM_I2S_SUPPORTED_MASK & (1<<FOO) )
+
 #include <asm/au1xxx_psc.h>
 #include <asm/au1xxx_dbdma.h>
 
@@ -98,13 +137,51 @@
  * 0 = no VRA, 1 = use VRA if codec supports it
  * The framework is here, but we currently force no VRA.
  */
+#if defined(CONFIG_MIPS_PB1200) | defined(CONFIG_MIPS_PB1550)
 static int      vra = 0;
+#elif defined(CONFIG_MIPS_FICMMP)
+static int vra = 1;
+#endif
+
+#define WM_REG_L_HEADPHONE_OUT                 0x02
+#define WM_REG_R_HEADPHONE_OUT                 0x03
+#define WM_REG_ANALOGUE_AUDIO_PATH_CTRL                0x04
+#define WM_REG_DIGITAL_AUDIO_PATH_CTRL         0x05
+#define WM_REG_POWER_DOWN_CTRL                 0x06
+#define WM_REG_DIGITAL_AUDIO_IF                        0x07
+#define WM_REG_SAMPLING_CONTROL                0x08
+#define WM_REG_ACTIVE_CTRL                     0x09
+#define WM_REG_RESET                           0x0F
+#define WM_SC_SR_96000         (0x7<<2)
+#define WM_SC_SR_88200         (0xF<<2)
+#define WM_SC_SR_48000         (0x0<<2)
+#define WM_SC_SR_44100         (0x8<<2)
+#define WM_SC_SR_32000         (0x6<<2)
+#define WM_SC_SR_8018          (0x9<<2)
+#define WM_SC_SR_8000          (0x1<<2)
+#define WM_SC_MODE_USB         1
+#define WM_SC_MODE_NORMAL      0
+#define WM_SC_BOSR_250FS       (0<<1)
+#define WM_SC_BOSR_272FS       (1<<1)
+#define WM_SC_BOSR_256FS       (0<<1)
+#define WM_SC_BOSR_128FS       (0<<1)
+#define WM_SC_BOSR_384FS       (1<<1)
+#define WM_SC_BOSR_192FS       (1<<1)
+
+#define WS_64FS                        31
+#define WS_96FS                        47
+#define WS_128FS               63
+#define WS_192FS               95
+
+#define MIN_Q_COUNT            2
+
 MODULE_PARM(vra, "i");
 MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
 
 static struct au1550_state {
        /* soundcore stuff */
        int             dev_audio;
+       int                             dev_mixer;
 
        spinlock_t              lock;
        struct semaphore        open_sem;
@@ -114,6 +191,11 @@
        int                     no_vra;
        volatile psc_i2s_t      *psc_addr;
 
+       int level_line;
+       int level_mic;
+       int level_left;
+       int level_right;
+
        struct dmabuf {
                u32             dmanr;
                unsigned        sample_rate;
@@ -195,60 +277,224 @@
        }
 }
 
-/* Just a place holder.  The Wolfson codec is a write only device,
- * so we would have to keep a local copy of the data.
- */
-#if 0
-static u8
-rdcodec(u8 addr)
-{
-       return 0  /* data */;
-}
-#endif
-
-
 static void
-wrcodec(u8 ctlreg, u8 val)
+wrcodec(u8 ctlreg, u16 val)
 {
        int     rcnt;
        extern int pb1550_wm_codec_write(u8 addr, u8 reg, u8 val);
-
        /* The codec is a write only device, with a 16-bit control/data
         * word.  Although it is written as two bytes on the I2C, the
         * format is actually 7 bits of register and 9 bits of data.
         * The ls bit of the first byte is the ms bit of the data.
         */
        rcnt = 0;
-       while ((pb1550_wm_codec_write((0x36 >> 1), ctlreg, val) != 1) 
-                                                       && (rcnt < 50)) {
+       while ((pb1550_wm_codec_write((0x36 >> 1), 
+                                       (ctlreg << 1) | ((val >> 8) & 0x01), 
+                                       (u8) (val & 0x00FF)) != 1) && 
+                       (rcnt < 50)) {
                rcnt++;
-#if 0
-               printk("Codec write retry %02x %02x\n", ctlreg, val);
-#endif
        }
+
+       au1550_delay(10);
+}
+
+static int
+au1550_open_mixdev(struct inode *inode, struct file *file)
+{
+       file->private_data = &au1550_state;
+       return 0;
+}
+
+static int
+au1550_release_mixdev(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+static int wm_i2s_read_mixer(struct au1550_state *s, int oss_channel)
+{
+       int ret = 0;
+
+       if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
+               /* nice stereo mixers .. */
+
+               ret = s->level_left | (s->level_right << 8);
+       } else if (oss_channel == SOUND_MIXER_MIC) {
+               ret = 0;
+               /* TODO: Implement read mixer for input/output codecs */
+       }
+
+       return ret;
 }
 
+static void wm_i2s_write_mixer(struct au1550_state *s, int oss_channel, 
unsigned int left, unsigned int right)
+{
+       if (WM_I2S_STEREO_MASK & (1 << oss_channel)) {
+               /* stereo mixers */
+               s->level_left = left;
+               s->level_right = right;
+
+               right = (right * WM_VOLUME_SCALE) / 100;
+               left  = (left  * WM_VOLUME_SCALE) / 100;
+               if (right > WM_VOLUME_SCALE)
+                       right = WM_VOLUME_SCALE;
+               if (left > WM_VOLUME_SCALE)
+                       left = WM_VOLUME_SCALE;
+
+               right += WM_VOLUME_MIN;
+               left  += WM_VOLUME_MIN;
+
+               wrcodec(WM_REG_L_HEADPHONE_OUT, left);
+               wrcodec(WM_REG_R_HEADPHONE_OUT, right);
+
+       }else if (oss_channel == SOUND_MIXER_MIC) {
+               /* TODO: implement write mixer for input/output codecs */
+       }
+}
+
+/* a thin wrapper for write_mixer */
+static void wm_i2s_set_mixer(struct au1550_state *s, unsigned int oss_mixer, 
unsigned int val )
+{
+       unsigned int left,right;
+
+       /* cleanse input a little */
+       right = ((val >> 8)  & 0xff) ;
+       left = (val  & 0xff) ;
+
+       if (right > 100) right = 100;
+       if (left > 100) left = 100;
+
+       wm_i2s_write_mixer(s, oss_mixer, left, right);
+}
+
+static int
+au1550_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, 
unsigned long arg)
+{
+       struct au1550_state *s = (struct au1550_state *)file->private_data;
+
+       int i, val = 0;
+
+       if (cmd == SOUND_MIXER_INFO) {
+               mixer_info info;
+               strncpy(info.id, CODEC_NAME, sizeof(info.id));
+               strncpy(info.name, CODEC_NAME, sizeof(info.name));
+               info.modify_counter = 0;
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       if (cmd == SOUND_OLD_MIXER_INFO) {
+               _old_mixer_info info;
+               strncpy(info.id, CODEC_NAME, sizeof(info.id));
+               strncpy(info.name, CODEC_NAME, sizeof(info.name));
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+
+       if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
+               return -EINVAL;
+
+       if (cmd == OSS_GETVERSION)
+               return put_user(SOUND_VERSION, (int *)arg);
+
+       if (_SIOC_DIR(cmd) == _SIOC_READ) {
+               switch (_IOC_NR(cmd)) {
+               case SOUND_MIXER_RECSRC: /* give them the current record src */
+                       val = 0;
+                       /*
+                       if (!codec->recmask_io) {
+                               val = 0;
+                       } else {
+                               val = codec->recmask_io(codec, 1, 0);
+                       }*/
+                       break;
+
+               case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
+                       val = WM_I2S_SUPPORTED_MASK;
+                       break;
+
+               case SOUND_MIXER_RECMASK: 
+                       /* Arg contains a bit for each supported recording 
+                        * source */
+                       val = WM_I2S_RECORD_MASK;
+                       break;
+
+               case SOUND_MIXER_STEREODEVS: 
+                       /* Mixer channels supporting stereo */
+                       val = WM_I2S_STEREO_MASK;
+                       break;
+
+               case SOUND_MIXER_CAPS:
+                       val = SOUND_CAP_EXCL_INPUT;
+                       break;
+
+               default: /* read a specific mixer */
+                       i = _IOC_NR(cmd);
+
+                       if (!supported_mixer(i))
+                               return -EINVAL;
+
+                       val = wm_i2s_read_mixer(s, i);
+                       break;
+               }
+               return put_user(val, (int *)arg);
+       }
+
+       if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+
+               switch (_IOC_NR(cmd)) {
+               case SOUND_MIXER_RECSRC: 
+                       /* Arg contains a bit for each recording source */
+                       if (!WM_I2S_RECORD_MASK)
+                               return -EINVAL;
+                       if (!val)
+                               return 0;
+                       if (!(val &= WM_I2S_RECORD_MASK))
+                               return -EINVAL;
+
+                       return 0;
+               default: /* write a specific mixer */
+                       i = _IOC_NR(cmd);
+
+                       if (!supported_mixer(i))
+                               return -EINVAL;
+
+                       wm_i2s_set_mixer(s, i, val);
+
+                       return 0;
+       }
+}
+       return -EINVAL;
+}
+
+static loff_t
+au1550_llseek(struct file *file, loff_t offset, int origin)
+{
+       return -ESPIPE;
+}
+
+static /*const */ struct file_operations au1550_mixer_fops = {
+       owner:THIS_MODULE,
+       llseek:au1550_llseek,
+       ioctl:au1550_ioctl_mixdev,
+       open:au1550_open_mixdev,
+       release:au1550_release_mixdev,
+};
+
 void
-codec_init(void)
+codec_init(struct au1550_state *s)
 {
-       wrcodec(0x1e, 0x00);    /* Reset */
-       au1550_delay(200);
-       wrcodec(0x0c, 0x00);    /* Power up everything */
-       au1550_delay(10);
-       wrcodec(0x12, 0x00);    /* Deactivate codec */
-       au1550_delay(10);
-       wrcodec(0x08, 0x10);    /* Select DAC outputs to line out */
-       au1550_delay(10);
-       wrcodec(0x0a, 0x00);    /* Disable output mute */
-       au1550_delay(10);
-       wrcodec(0x05, 0x70);    /* lower output volume on headphone */
-       au1550_delay(10);
-       wrcodec(0x0e, 0x02);    /* Set slave, 16-bit, I2S modes */
-       au1550_delay(10);
-       wrcodec(0x10, 0x01);    /* 12MHz (USB), 250fs */
-       au1550_delay(10);
-       wrcodec(0x12, 0x01);    /* Activate codec */
-       au1550_delay(10);
+       wrcodec(WM_REG_RESET, 0x00);    /* Reset */
+       wrcodec(WM_REG_POWER_DOWN_CTRL, 0x00);  /* Power up everything */
+       wrcodec(WM_REG_ACTIVE_CTRL, 0x00);      /* Deactivate codec */
+       wrcodec(WM_REG_ANALOGUE_AUDIO_PATH_CTRL, 0x10); /* Select DAC outputs 
to line out */
+       wrcodec(WM_REG_DIGITAL_AUDIO_PATH_CTRL, 0x00);  /* Disable output mute 
*/
+       wm_i2s_write_mixer(s, SOUND_MIXER_PCM, 74, 74);
+       wrcodec(WM_REG_DIGITAL_AUDIO_IF, 0x02); /* Set slave, 16-bit, I2S modes 
*/
+       wrcodec(WM_REG_ACTIVE_CTRL, 0x01);      /* Activate codec */
 }
 
 /* stop the ADC before calling */
@@ -256,27 +502,16 @@
 set_adc_rate(struct au1550_state *s, unsigned rate)
 {
        struct dmabuf  *adc = &s->dma_adc;
-       struct dmabuf  *dac = &s->dma_dac;
 
-       if (s->no_vra) {
-               /* calc SRC factor
-               */
+       #if defined(WM_MODE_USB)
                adc->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
                adc->sample_rate = SAMP_RATE / adc->src_factor;
                return;
-       }
+       #else
+       //TODO: Need code for normal mode
+       #endif
 
        adc->src_factor = 1;
-
-
-#if 0
-       rate = rate > SAMP_RATE ? SAMP_RATE : rate;
-
-       wrcodec(0, 0);  /* I don't yet know what to write here if we vra */
-
-       adc->sample_rate = rate;
-       dac->sample_rate = rate;
-#endif
 }
 
 /* stop the DAC before calling */
@@ -284,26 +519,89 @@
 set_dac_rate(struct au1550_state *s, unsigned rate)
 {
        struct dmabuf  *dac = &s->dma_dac;
-       struct dmabuf  *adc = &s->dma_adc;
 
-       if (s->no_vra) {
-               /* calc SRC factor
-               */
-               dac->src_factor = (((SAMP_RATE*2) / rate) + 1) >> 1;
-               dac->sample_rate = SAMP_RATE / dac->src_factor;
-               return;
+       u16 sr, ws, div, bosr, mode;
+       volatile psc_i2s_t* ip = (volatile psc_i2s_t *)I2S_PSC_BASE;
+       u32 cfg;
+
+       #if defined(CONFIG_MIPS_FICMMP)
+               rate = ficmmp_set_i2s_sample_rate(rate);
+       #endif
+
+       switch(rate)
+       {
+               case 96000: 
+                       sr = WM_SC_SR_96000; 
+                       ws = WS_64FS;  
+                       div = PSC_I2SCFG_DIV2;  
+                       break;
+               case 88200: 
+                       sr = WM_SC_SR_88200; 
+                       ws = WS_64FS;  
+                       div = PSC_I2SCFG_DIV2;  
+                       break;
+               case 44100: 
+                       sr = WM_SC_SR_44100; 
+                       ws = WS_128FS; 
+                       div = PSC_I2SCFG_DIV2;  
+                       break;
+               case 48000: 
+                       sr = WM_SC_SR_48000; 
+                       ws = WS_128FS; 
+                       div = PSC_I2SCFG_DIV2;  
+                       break;
+               case 32000: 
+                       sr = WM_SC_SR_32000; 
+                       ws = WS_96FS;  
+                       div = PSC_I2SCFG_DIV4;  
+                       break;
+               case  8018: 
+                       sr = WM_SC_SR_8018;  
+                       ws = WS_128FS; 
+                       div = PSC_I2SCFG_DIV2;  
+                       break;
+               case  8000:
+               default:    
+                       sr = WM_SC_SR_8000;  
+                       ws = WS_96FS;  
+                       div = PSC_I2SCFG_DIV16; 
+                       break;
        }
 
+       #if defined(WM_MODE_USB)
+               mode = WM_SC_MODE_USB;
+       #else
+               mode = WM_SC_MODE_NORMAL;
+       #endif
+
+       bosr = 0;
+
        dac->src_factor = 1;
+       dac->sample_rate = rate;
 
-#if 0
-       rate = rate > SAMP_RATE ? SAMP_RATE : rate;
+       /* Deactivate codec */
+       wrcodec(WM_REG_ACTIVE_CTRL, 0x00);
 
-       wrcodec(0, 0);  /* I don't yet know what to write here if we vra */
+       /* Disable I2S controller */
+       ip->psc_i2scfg &= ~PSC_I2SCFG_DE_ENABLE;
+       /* Wait for device disabled */
+       while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 1);
+
+       cfg = ip->psc_i2scfg;
+       /* Clear WS and DIVIDER values */
+       cfg &= ~(PSC_I2SCFG_WS_MASK | PSC_I2SCFG_DIV_MASK);     
+       cfg |= PSC_I2SCFG_WS(ws) | div;
+       /* Reconfigure and enable */
+       ip->psc_i2scfg = cfg | PSC_I2SCFG_DE_ENABLE;    
 
-       adc->sample_rate = rate;
-       dac->sample_rate = rate;
-#endif
+       /* Wait for device enabled */
+       while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 0);
+
+       /* Set appropriate sampling rate */
+       wrcodec(WM_REG_SAMPLING_CONTROL, bosr | mode | sr);
+
+       /* Activate codec */
+       wrcodec(WM_REG_ACTIVE_CTRL, 0x01);
 }
 
 static void
@@ -354,8 +652,7 @@
        ip->psc_i2spcr = PSC_I2SPCR_RP;
        au_sync();
 
-       /* Wait for Receive Busy to show disabled.
-       */
+       /* Wait for Receive Busy to show disabled.  */
        do {
                stat = ip->psc_i2sstat;
                au_sync();
@@ -463,7 +760,6 @@
        if (db->num_channels == 1)
                db->cnt_factor *= 2;
        db->cnt_factor *= db->src_factor;
-
        db->count = 0;
        db->dma_qcount = 0;
        db->nextIn = db->nextOut = db->rawbuf;
@@ -546,12 +842,13 @@
        if (i2s_stat & (PSC_I2SSTAT_TF | PSC_I2SSTAT_TR | PSC_I2SSTAT_TF))
                dbg("I2S status = 0x%08x", i2s_stat);
 #endif
+
        db->dma_qcount--;
 
        if (db->count >= db->fragsize) {
-               if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
-                                                       db->fragsize) == 0) {
-                       err("qcount < 2 and no ring room!");
+               if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut, 
db->fragsize) == 0)
+               {
+                       err("qcount < MIN_Q_COUNT and no ring room!");
                }
                db->nextOut += db->fragsize;
                if (db->nextOut >= db->rawbuf + db->dmasize)
@@ -606,65 +903,43 @@
 
 }
 
-static loff_t
-au1550_llseek(struct file *file, loff_t offset, int origin)
-{
-       return -ESPIPE;
-}
-
-
-#if 0
-static int
-au1550_open_mixdev(struct inode *inode, struct file *file)
-{
-       file->private_data = &au1550_state;
-       return 0;
-}
-
-static int
-au1550_release_mixdev(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-static int
-mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
-                        unsigned long arg)
-{
-       return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static int
-au1550_ioctl_mixdev(struct inode *inode, struct file *file,
-                              unsigned int cmd, unsigned long arg)
-{
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
-       struct ac97_codec *codec = s->codec;
-
-       return mixdev_ioctl(codec, cmd, arg);
-}
-
-static /*const */ struct file_operations au1550_mixer_fops = {
-       owner:THIS_MODULE,
-       llseek:au1550_llseek,
-       ioctl:au1550_ioctl_mixdev,
-       open:au1550_open_mixdev,
-       release:au1550_release_mixdev,
-};
-#endif
-
 static int
 drain_dac(struct au1550_state *s, int nonblock)
 {
        unsigned long   flags;
        int             count, tmo;
 
+       struct dmabuf  *db = &s->dma_dac;
+
+       //DPRINTF();
        if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped)
                return 0;
 
        for (;;) {
                spin_lock_irqsave(&s->lock, flags);
-               count = s->dma_dac.count;
+               count = db->count;
+
+               /* Pad the ddma buffer with zeros if the amount remaining 
+                * is not a multiple of fragsize */
+               if(count % db->fragsize != 0)
+               {
+                       int pad = db->fragsize - (count % db->fragsize);
+                       char* bufptr = db->nextIn;
+                       char* bufend = db->rawbuf + db->dmasize;
+
+                       if((bufend - bufptr) < pad)
+                               printk("Error!  ddma padding is bigger than 
available ring space!\n");
+                       else
+                       {
+                               memset((void*)bufptr, 0, pad);
+                               count += pad;
+                               db->nextIn += pad;
+                               db->count += pad;
+                               if (db->dma_qcount == 0)
+                                               start_dac(s);
+                               db->dma_qcount++;
+                       }
+               }
                spin_unlock_irqrestore(&s->lock, flags);
                if (count <= 0)
                        break;
@@ -672,9 +947,9 @@
                        break;
                if (nonblock)
                        return -EBUSY;
-               tmo = 1000 * count / (s->no_vra ?
-                                     SAMP_RATE : s->dma_dac.sample_rate);
+               tmo = 1000 * count / s->dma_dac.sample_rate;
                tmo /= s->dma_dac.dma_bytes_per_sample;
+
                au1550_delay(tmo);
        }
        if (signal_pending(current))
@@ -698,8 +973,7 @@
  *     If interpolating (no VRA), duplicate every audio frame src_factor times.
  */
 static int
-translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf,
-                                                              int dmacount)
+translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf, int 
dmacount)
 {
        int             sample, i;
        int             interp_bytes_per_sample;
@@ -737,11 +1011,12 @@
 
                /* duplicate every audio frame src_factor times
                */
-               for (i = 0; i < db->src_factor; i++)
+               for (i = 0; i < db->src_factor; i++) {
                        memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);
+                       dmabuf += interp_bytes_per_sample;
+               }
 
                userbuf += db->user_bytes_per_sample;
-               dmabuf += interp_bytes_per_sample;
        }
 
        return num_samples * interp_bytes_per_sample;
@@ -996,15 +1271,14 @@
                 * on the dma queue.  If the queue count reaches zero,
                 * we know the dma has stopped.
                 */
-               while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {
+               while ((db->dma_qcount < MIN_Q_COUNT) && (db->count >= 
db->fragsize)) {
                        if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut,
                                                        db->fragsize) == 0) {
-                               err("qcount < 2 and no ring room!");
+                               err("qcount < MIN_Q_COUNT and no ring room!");
                        }
                        db->nextOut += db->fragsize;
                        if (db->nextOut >= db->rawbuf + db->dmasize)
                                db->nextOut -= db->dmasize;
-                       db->count -= db->fragsize;
                        db->total_bytes += db->dma_fragsize;
                        if (db->dma_qcount == 0)
                                start_dac(s);
@@ -1017,7 +1291,6 @@
                buffer += usercnt;
                ret += usercnt;
        }                       /* while (count > 0) */
-
 out:
        up(&s->sem);
 out2:
@@ -1371,9 +1644,6 @@
                        s->dma_dac.cnt_factor;
                abinfo.fragstotal = s->dma_dac.numfrag;
                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
-#ifdef AU1000_VERBOSE_DEBUG
-               dbg("bytes=%d, fragments=%d", abinfo.bytes, abinfo.fragments);
-#endif
                return copy_to_user((void *) arg, &abinfo,
                                    sizeof(abinfo)) ? -EFAULT : 0;
 
@@ -1536,13 +1806,9 @@
        case SNDCTL_DSP_SETSYNCRO:
        case SOUND_PCM_READ_FILTER:
                return -EINVAL;
+       default: break;
        }
-
-#if 0
-       return mixdev_ioctl(s->codec, cmd, arg);
-#else
        return 0;
-#endif
 }
 
 
@@ -1664,15 +1930,15 @@
 MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
 MODULE_DESCRIPTION("Au1550 Audio Driver");
 
+#if defined(WM_MODE_USB)
 /* Set up an internal clock for the PSC3.  This will then get
  * driven out of the Au1550 as the master.
  */
 static void
 intclk_setup(void)
 {
-       uint    clk, rate, stat;
-
-       /* Wire up Freq4 as a clock for the PSC3.
+       uint    clk, rate;
+       /* Wire up Freq4 as a clock for the PSC.
         * We know SMBus uses Freq3.
         * By making changes to this rate, plus the word strobe
         * size, we can make fine adjustments to the actual data rate.
@@ -1700,11 +1966,17 @@
        */
        clk = au_readl(SYS_CLKSRC);
        au_sync();
+#if defined(CONFIG_SOC_AU1550)
        clk &= ~0x01f00000;
        clk |= (6 << 22);
+#elif defined(CONFIG_SOC_AU1200)
+       clk &= ~0x3e000000;
+       clk |= (6 << 27);
+#endif
        au_writel(clk, SYS_CLKSRC);
        au_sync();
 }
+#endif
 
 static int __devinit
 au1550_probe(void)
@@ -1724,6 +1996,11 @@
        init_MUTEX(&s->open_sem);
        spin_lock_init(&s->lock);
 
+       /* CPLD Mux for I2s */
+
+#if defined(CONFIG_MIPS_PB1200)
+       bcsr->resets |= BCSR_RESETS_PCS1MUX;
+#endif
 
        s->psc_addr = (volatile psc_i2s_t *)I2S_PSC_BASE;
        ip = s->psc_addr;
@@ -1765,9 +2042,8 @@
 
        if ((s->dev_audio = register_sound_dsp(&au1550_audio_fops, -1)) < 0)
                goto err_dev1;
-#if 0
-       if ((s->codec->dev_mixer =
-            register_sound_mixer(&au1550_mixer_fops, -1)) < 0)
+#if 1
+       if ((s->dev_mixer = register_sound_mixer(&au1550_mixer_fops, -1)) < 0)
                goto err_dev2;
 #endif
 
@@ -1777,7 +2053,6 @@
                                       proc_au1550_dump, NULL);
 #endif /* AU1550_DEBUG */
 
-       intclk_setup();
 
        /* The GPIO for the appropriate PSC was configured by the
         * board specific start up.
@@ -1786,7 +2061,12 @@
         */
        ip->psc_ctrl = PSC_CTRL_DISABLE;        /* Disable PSC */
        au_sync();
+#if defined(WM_MODE_USB)
+       intclk_setup();
        ip->psc_sel = (PSC_SEL_CLK_INTCLK | PSC_SEL_PS_I2SMODE);
+#else
+       ip->psc_sel = (PSC_SEL_CLK_EXTCLK | PSC_SEL_PS_I2SMODE);
+#endif
        au_sync();
 
        /* Enable PSC
@@ -1806,42 +2086,18 @@
         * Actual I2S mode (first bit delayed by one clock).
         * Master mode (We provide the clock from the PSC).
         */
-       val = PSC_I2SCFG_SET_LEN(16);
-#ifdef TRY_441KHz
-       /* This really should be 250, but it appears that all of the
-        * PLLs, dividers and so on in the chain shift it.  That's the
-        * problem with sourceing the clock instead of letting the very
-        * stable codec provide it.  But, the PSC doesn't appear to want
-        * to work in slave mode, so this is what we get.  It's  not
-        * studio quality timing, but it's good enough for listening
-        * to mp3s.
-        */
-       val |= PSC_I2SCFG_SET_WS(252);
-#else
-       val |= PSC_I2SCFG_SET_WS(250);
-#endif
-       val |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8 | \
+
+       val = PSC_I2SCFG_SET_LEN(16) | PSC_I2SCFG_WS(WS_128FS) | 
PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8 | \
                                        PSC_I2SCFG_BI | PSC_I2SCFG_XM;
 
-       ip->psc_i2scfg = val;
-       au_sync();
-       val |= PSC_I2SCFG_DE_ENABLE;
-       ip->psc_i2scfg = val;
-       au_sync();
+       ip->psc_i2scfg = val | PSC_I2SCFG_DE_ENABLE;
 
-       /* Wait for Device ready.
-       */
-       do {
-               val = ip->psc_i2sstat;
-               au_sync();
-       } while ((val & PSC_I2SSTAT_DR) == 0);
+       set_dac_rate(s, 8000);  //Set default rate
 
-       val = ip->psc_i2scfg;
-       au_sync();
+       codec_init(s);
 
-       codec_init();
+       s->no_vra = vra ? 0 : 1;
 
-       s->no_vra = 1;
        if (s->no_vra)
                info("no VRA, interpolating and decimating");
 
@@ -1866,6 +2122,8 @@
  err_dev2:
        unregister_sound_dsp(s->dev_audio);
 #endif
+ err_dev2:
+       unregister_sound_dsp(s->dev_audio);
  err_dev1:
        au1xxx_dbdma_chan_free(s->dma_adc.dmanr);
  err_dma2:

<Prev in Thread] Current Thread [Next in Thread>