Merge branch 'fix/asoc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Fri, 16 Apr 2010 08:03:36 +0000 (10:03 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 16 Apr 2010 08:03:36 +0000 (10:03 +0200)
sound/soc/codecs/wm2000.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-pcm-fiq.c
sound/soc/imx/imx-ssi.c

index a34cbcf..002e289 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/firmware.h>
index 2e79d71..2b31ac6 100644 (file)
@@ -71,7 +71,12 @@ static void imx_ssi_dma_callback(int channel, void *data)
 
 static void snd_imx_dma_err_callback(int channel, void *data, int err)
 {
-       pr_err("DMA error callback called\n");
+       struct snd_pcm_substream *substream = data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+       int ret;
 
        pr_err("DMA timeout on channel %d -%s%s%s%s\n",
                 channel,
@@ -79,6 +84,14 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
                 err & IMX_DMA_ERR_REQUEST ?  " request" : "",
                 err & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
                 err & IMX_DMA_ERR_BUFFER ?   " buffer" : "");
+
+       imx_dma_disable(iprtd->dma);
+       ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
+                       IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
+                       substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+                       DMA_MODE_WRITE : DMA_MODE_READ);
+       if (!ret)
+               imx_dma_enable(iprtd->dma);
 }
 
 static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
index f96a373..6b518e0 100644 (file)
@@ -39,23 +39,24 @@ struct imx_pcm_runtime_data {
        unsigned long offset;
        unsigned long last_offset;
        unsigned long size;
-       struct timer_list timer;
-       int poll_time;
+       struct hrtimer hrt;
+       int poll_time_ns;
+       struct snd_pcm_substream *substream;
+       atomic_t running;
 };
 
-static inline void imx_ssi_set_next_poll(struct imx_pcm_runtime_data *iprtd)
+static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
 {
-       iprtd->timer.expires = jiffies + iprtd->poll_time;
-}
-
-static void imx_ssi_timer_callback(unsigned long data)
-{
-       struct snd_pcm_substream *substream = (void *)data;
+       struct imx_pcm_runtime_data *iprtd =
+               container_of(hrt, struct imx_pcm_runtime_data, hrt);
+       struct snd_pcm_substream *substream = iprtd->substream;
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct imx_pcm_runtime_data *iprtd = runtime->private_data;
        struct pt_regs regs;
        unsigned long delta;
 
+       if (!atomic_read(&iprtd->running))
+               return HRTIMER_NORESTART;
+
        get_fiq_regs(&regs);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -72,16 +73,14 @@ static void imx_ssi_timer_callback(unsigned long data)
 
        /* If we've transferred at least a period then report it and
         * reset our poll time */
-       if (delta >= runtime->period_size) {
+       if (delta >= iprtd->period) {
                snd_pcm_period_elapsed(substream);
                iprtd->last_offset = iprtd->offset;
-
-               imx_ssi_set_next_poll(iprtd);
        }
 
-       /* Restart the timer; if we didn't report we'll run on the next tick */
-       add_timer(&iprtd->timer);
+       hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns));
 
+       return HRTIMER_RESTART;
 }
 
 static struct fiq_handler fh = {
@@ -99,8 +98,8 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
        iprtd->period = params_period_bytes(params) ;
        iprtd->offset = 0;
        iprtd->last_offset = 0;
-       iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params));
-
+       iprtd->poll_time_ns = 1000000000 / params_rate(params) *
+                               params_period_size(params);
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        return 0;
@@ -135,8 +134,9 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               imx_ssi_set_next_poll(iprtd);
-               add_timer(&iprtd->timer);
+               atomic_set(&iprtd->running, 1);
+               hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns),
+                     HRTIMER_MODE_REL);
                if (++fiq_enable == 1)
                        enable_fiq(imx_pcm_fiq);
 
@@ -145,11 +145,11 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               del_timer(&iprtd->timer);
+               atomic_set(&iprtd->running, 0);
+
                if (--fiq_enable == 0)
                        disable_fiq(imx_pcm_fiq);
 
-
                break;
        default:
                return -EINVAL;
@@ -180,7 +180,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
        .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
        .period_bytes_min = 128,
        .period_bytes_max = 16 * 1024,
-       .periods_min = 2,
+       .periods_min = 4,
        .periods_max = 255,
        .fifo_size = 0,
 };
@@ -194,9 +194,11 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
        iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
        runtime->private_data = iprtd;
 
-       init_timer(&iprtd->timer);
-       iprtd->timer.data = (unsigned long)substream;
-       iprtd->timer.function = imx_ssi_timer_callback;
+       iprtd->substream = substream;
+
+       atomic_set(&iprtd->running, 0);
+       hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       iprtd->hrt.function = snd_hrtimer_callback;
 
        ret = snd_pcm_hw_constraint_integer(substream->runtime,
                        SNDRV_PCM_HW_PARAM_PERIODS);
@@ -212,7 +214,8 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 
-       del_timer_sync(&iprtd->timer);
+       hrtimer_cancel(&iprtd->hrt);
+
        kfree(iprtd);
 
        return 0;
index 0bcc6d7..80b4fee 100644 (file)
@@ -656,7 +656,8 @@ static int imx_ssi_probe(struct platform_device *pdev)
        dai->private_data = ssi;
 
        if ((cpu_is_mx27() || cpu_is_mx21()) &&
-                       !(ssi->flags & IMX_SSI_USE_AC97)) {
+                       !(ssi->flags & IMX_SSI_USE_AC97) &&
+                       (ssi->flags & IMX_SSI_DMA)) {
                ssi->flags |= IMX_SSI_DMA;
                platform = imx_ssi_dma_mx2_init(pdev, ssi);
        } else