ACPI: thermal: fix units in debug output
[powerpc.git] / sound / sparc / dbri.c
index cdca8e4..4ceb09d 100644 (file)
@@ -635,10 +635,16 @@ to send them to the DBRI.
 static void dbri_cmdwait(struct snd_dbri *dbri)
 {
        int maxloops = MAXLOOPS;
+       unsigned long flags;
 
        /* Delay if previous commands are still being processed */
-       while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P))
+       spin_lock_irqsave(&dbri->lock, flags);
+       while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) {
+               spin_unlock_irqrestore(&dbri->lock, flags);
                msleep_interruptible(1);
+               spin_lock_irqsave(&dbri->lock, flags);
+       }
+       spin_unlock_irqrestore(&dbri->lock, flags);
 
        if (maxloops == 0) {
                printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
@@ -663,7 +669,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
        else
                printk(KERN_ERR "DBRI: no space for commands.");
 
-       return 0;
+       return NULL;
 }
 
 /*
@@ -671,11 +677,12 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
  * the last WAIT cmd and force DBRI to reread the cmd.
  * The JUMP cmd points to the new cmd string.
  * It also releases the cmdlock spinlock.
+ *
+ * Lock must not be held before calling this.
  */
 static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
 {
        s32 tmp, addr;
-       unsigned long flags;
        static int wait_id = 0;
 
        wait_id++;
@@ -706,12 +713,10 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
        }
 #endif
 
-       spin_lock_irqsave(&dbri->lock, flags);
        /* Reread the last command */
        tmp = sbus_readl(dbri->regs + REG0);
        tmp |= D_P;
        sbus_writel(tmp, dbri->regs + REG0);
-       spin_unlock_irqrestore(&dbri->lock, flags);
 
        dbri->cmdptr = cmd;
        spin_unlock(&dbri->cmdlock);
@@ -777,9 +782,9 @@ static void dbri_initialize(struct snd_dbri * dbri)
        dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0);
        sbus_writel(dma_addr, dbri->regs + REG8);
        spin_unlock(&dbri->cmdlock);
-       dbri_cmdwait(dbri);
 
        spin_unlock_irqrestore(&dbri->lock, flags);
+       dbri_cmdwait(dbri);
 }
 
 /*
@@ -840,6 +845,9 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe)
        dbri->pipes[pipe].first_desc = -1;
 }
 
+/*
+ * Lock must be held before calling this.
+ */
 static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
 {
        if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
@@ -866,6 +874,9 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
        reset_pipe(dbri, pipe);
 }
 
+/*
+ * Lock must be held before calling this.
+ */
 static void link_time_slot(struct snd_dbri * dbri, int pipe,
                           int prevpipe, int nextpipe,
                           int length, int cycle)
@@ -920,6 +931,10 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe,
        dbri_cmdsend(dbri, cmd, 4);
 }
 
+#if 0
+/*
+ * Lock must be held before calling this.
+ */
 static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
                             enum in_or_out direction, int prevpipe,
                             int nextpipe)
@@ -952,6 +967,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
 
        dbri_cmdsend(dbri, cmd, 4);
 }
+#endif
 
 /* xmit_fixed() / recv_fixed()
  *
@@ -965,11 +981,14 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
  * the actual time slot is.  The interrupt handler takes care of bit
  * ordering and alignment.  An 8-bit time slot will always end up
  * in the low-order 8 bits, filled either MSB-first or LSB-first,
- * depending on the settings passed to setup_pipe()
+ * depending on the settings passed to setup_pipe().
+ *
+ * Lock must not be held before calling it.
  */
 static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
 {
        s32 *cmd;
+       unsigned long flags;
 
        if (pipe < 16 || pipe > DBRI_MAX_PIPE) {
                printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
@@ -1002,8 +1021,11 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
        *(cmd++) = data;
        *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
 
+       spin_lock_irqsave(&dbri->lock, flags);
        dbri_cmdsend(dbri, cmd, 3);
+       spin_unlock_irqrestore(&dbri->lock, flags);
        dbri_cmdwait(dbri);
+
 }
 
 static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
@@ -1039,12 +1061,14 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
  * be spread across multiple descriptors.
  *
  * All descriptors create a ring buffer.
+ *
+ * Lock must be held before calling this.
  */
 static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period)
 {
        struct dbri_streaminfo *info = &dbri->stream_info[streamno];
        __u32 dvma_buffer;
-       int desc = 0;
+       int desc;
        int len;
        int first_desc = -1;
        int last_desc = -1;
@@ -1087,6 +1111,18 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period
                len &= ~3;
        }
 
+       /* Free descriptors if pipe has any */
+       desc = dbri->pipes[info->pipe].first_desc;
+       if ( desc >= 0)
+               do {
+                       dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0;
+                       desc = dbri->next_desc[desc];
+               } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc);
+
+       dbri->pipes[info->pipe].desc = -1;
+       dbri->pipes[info->pipe].first_desc = -1;
+
+       desc = 0;
        while (len > 0) {
                int mylen;
 
@@ -1174,6 +1210,9 @@ multiplexed serial interface which the DBRI can operate in either master
 
 enum master_or_slave { CHImaster, CHIslave };
 
+/*
+ * Lock must not be held before calling it.
+ */
 static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave,
                      int bits_per_frame)
 {
@@ -1246,9 +1285,14 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla
 In the standard SPARC audio configuration, the CS4215 codec is attached
 to the DBRI via the CHI interface and few of the DBRI's PIO pins.
 
+ * Lock must not be held before calling it.
+
 */
 static void cs4215_setup_pipes(struct snd_dbri * dbri)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&dbri->lock, flags);
        /*
         * Data mode:
         * Pipe  4: Send timeslots 1-4 (audio data)
@@ -1272,6 +1316,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri)
        setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB);
        setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
        setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
+       spin_unlock_irqrestore(&dbri->lock, flags);
 
        dbri_cmdwait(dbri);
 }
@@ -1346,6 +1391,7 @@ static void cs4215_open(struct snd_dbri * dbri)
 {
        int data_width;
        u32 tmp;
+       unsigned long flags;
 
        dprintk(D_MM, "cs4215_open: %d channels, %d bits\n",
                dbri->mm.channels, dbri->mm.precision);
@@ -1370,6 +1416,7 @@ static void cs4215_open(struct snd_dbri * dbri)
         * bits.  The CS4215, it seems, observes TSIN (the delayed signal)
         * even if it's the CHI master.  Don't ask me...
         */
+       spin_lock_irqsave(&dbri->lock, flags);
        tmp = sbus_readl(dbri->regs + REG0);
        tmp &= ~(D_C);          /* Disable CHI */
        sbus_writel(tmp, dbri->regs + REG0);
@@ -1397,6 +1444,7 @@ static void cs4215_open(struct snd_dbri * dbri)
        tmp = sbus_readl(dbri->regs + REG0);
        tmp |= D_C;             /* Enable CHI */
        sbus_writel(tmp, dbri->regs + REG0);
+       spin_unlock_irqrestore(&dbri->lock, flags);
 
        cs4215_setdata(dbri, 0);
 }
@@ -1408,6 +1456,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
 {
        int i, val;
        u32 tmp;
+       unsigned long flags;
 
        /* FIXME - let the CPU do something useful during these delays */
 
@@ -1444,6 +1493,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
         * done in hardware by a TI 248 that delays the DBRI->4215
         * frame sync signal by eight clock cycles.  Anybody know why?
         */
+       spin_lock_irqsave(&dbri->lock, flags);
        tmp = sbus_readl(dbri->regs + REG0);
        tmp &= ~D_C;            /* Disable CHI */
        sbus_writel(tmp, dbri->regs + REG0);
@@ -1460,14 +1510,17 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
        link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset);
        link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset);
        link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48);
+       spin_unlock_irqrestore(&dbri->lock, flags);
 
        /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */
        dbri->mm.ctrl[0] &= ~CS4215_CLB;
        xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
 
+       spin_lock_irqsave(&dbri->lock, flags);
        tmp = sbus_readl(dbri->regs + REG0);
        tmp |= D_C;             /* Enable CHI */
        sbus_writel(tmp, dbri->regs + REG0);
+       spin_unlock_irqrestore(&dbri->lock, flags);
 
        for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
                msleep_interruptible(1);
@@ -1676,6 +1729,7 @@ static void xmit_descs(struct snd_dbri *dbri)
                        dbri->pipes[info->pipe].desc = first_td;
                }
        }
+
        spin_unlock_irqrestore(&dbri->lock, flags);
 }
 
@@ -1849,8 +1903,7 @@ static void dbri_process_interrupt_buffer(struct snd_dbri * dbri)
        }
 }
 
-static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
-                                     struct pt_regs *regs)
+static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id)
 {
        struct snd_dbri *dbri = dev_id;
        static int errcnt = 0;
@@ -1983,10 +2036,10 @@ static int snd_dbri_open(struct snd_pcm_substream *substream)
        spin_unlock_irqrestore(&dbri->lock, flags);
 
        snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS,
-                           snd_hw_rule_format, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                           snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT,
                            -1);
        snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT,
-                           snd_hw_rule_channels, 0
+                           snd_hw_rule_channels, NULL
                            SNDRV_PCM_HW_PARAM_CHANNELS,
                            -1);
                                
@@ -2054,6 +2107,7 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
        struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
        struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
        int direction;
+
        dprintk(D_USR, "hw_free.\n");
 
        /* hw_free can get called multiple times. Only unmap the DMA once.
@@ -2068,7 +2122,10 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
                                  substream->runtime->buffer_size, direction);
                info->dvma_buffer = 0;
        }
-       info->pipe = -1;
+       if (info->pipe != -1) {
+               reset_pipe(dbri, info->pipe);
+               info->pipe = -1;
+       }
 
        return snd_pcm_lib_free_pages(substream);
 }
@@ -2077,7 +2134,6 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
        struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
 
        info->size = snd_pcm_lib_buffer_bytes(substream);
@@ -2095,8 +2151,6 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream)
        ret = setup_descs(dbri, DBRI_STREAMNO(substream),
                          snd_pcm_lib_period_bytes(substream));
 
-       runtime->stop_threshold = DBRI_TD_MAXCNT / runtime->channels;
-
        spin_unlock_irq(&dbri->lock);
 
        dprintk(D_USR, "prepare audio output. %d bytes\n", info->size);
@@ -2218,7 +2272,6 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
 {
        struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
        struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value];
-       unsigned long flags;
        int changed = 0;
 
        if (info->left_gain != ucontrol->value.integer.value[0]) {
@@ -2233,13 +2286,9 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
                /* First mute outputs, and wait 1/8000 sec (125 us)
                 * to make sure this takes.  This avoids clicking noises.
                 */
-               spin_lock_irqsave(&dbri->lock, flags);
-
                cs4215_setdata(dbri, 1);
                udelay(125);
                cs4215_setdata(dbri, 0);
-
-               spin_unlock_irqrestore(&dbri->lock, flags);
        }
        return changed;
 }
@@ -2286,7 +2335,6 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
        int elem = kcontrol->private_value & 0xff;
        int shift = (kcontrol->private_value >> 8) & 0xff;
        int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -2319,13 +2367,9 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
                /* First mute outputs, and wait 1/8000 sec (125 us)
                 * to make sure this takes.  This avoids clicking noises.
                 */
-               spin_lock_irqsave(&dbri->lock, flags);
-
                cs4215_setdata(dbri, 1);
                udelay(125);
                cs4215_setdata(dbri, 0);
-
-               spin_unlock_irqrestore(&dbri->lock, flags);
        }
        return changed;
 }
@@ -2367,8 +2411,6 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
        CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
 };
 
-#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new))
-
 static int __init snd_dbri_mixer(struct snd_dbri * dbri)
 {
        struct snd_card *card;
@@ -2379,7 +2421,7 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri)
        card = dbri->card;
        strcpy(card->mixername, card->shortname);
 
-       for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
                if ((err = snd_ctl_add(card,
                                snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
                        return err;