aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-04-16 04:03:36 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-16 04:03:36 -0400
commitd336905e00f208bcb89c719022c11dd3d976597a (patch)
tree6a5e3cf552231abe24df3cfae8f5d3884c7a1b4f /sound
parent0d0fb0f9c5fddef4a10242fe3337f00f528a3099 (diff)
parent8392609969b3b37a4da5cff08161661f7a8c16af (diff)
Merge branch 'fix/asoc' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm2000.c1
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c15
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c55
-rw-r--r--sound/soc/imx/imx-ssi.c3
4 files changed, 45 insertions, 29 deletions
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index a34cbcf7904f..002e289d1255 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -23,7 +23,6 @@
23 23
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
26#include <linux/version.h>
27#include <linux/kernel.h> 26#include <linux/kernel.h>
28#include <linux/init.h> 27#include <linux/init.h>
29#include <linux/firmware.h> 28#include <linux/firmware.h>
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 2e79d7136298..2b31ac673ea4 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -71,7 +71,12 @@ static void imx_ssi_dma_callback(int channel, void *data)
71 71
72static void snd_imx_dma_err_callback(int channel, void *data, int err) 72static void snd_imx_dma_err_callback(int channel, void *data, int err)
73{ 73{
74 pr_err("DMA error callback called\n"); 74 struct snd_pcm_substream *substream = data;
75 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
77 struct snd_pcm_runtime *runtime = substream->runtime;
78 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
79 int ret;
75 80
76 pr_err("DMA timeout on channel %d -%s%s%s%s\n", 81 pr_err("DMA timeout on channel %d -%s%s%s%s\n",
77 channel, 82 channel,
@@ -79,6 +84,14 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
79 err & IMX_DMA_ERR_REQUEST ? " request" : "", 84 err & IMX_DMA_ERR_REQUEST ? " request" : "",
80 err & IMX_DMA_ERR_TRANSFER ? " transfer" : "", 85 err & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
81 err & IMX_DMA_ERR_BUFFER ? " buffer" : ""); 86 err & IMX_DMA_ERR_BUFFER ? " buffer" : "");
87
88 imx_dma_disable(iprtd->dma);
89 ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count,
90 IMX_DMA_LENGTH_LOOP, dma_params->dma_addr,
91 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
92 DMA_MODE_WRITE : DMA_MODE_READ);
93 if (!ret)
94 imx_dma_enable(iprtd->dma);
82} 95}
83 96
84static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) 97static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index f96a373699cf..6b518e07eea9 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -39,23 +39,24 @@ struct imx_pcm_runtime_data {
39 unsigned long offset; 39 unsigned long offset;
40 unsigned long last_offset; 40 unsigned long last_offset;
41 unsigned long size; 41 unsigned long size;
42 struct timer_list timer; 42 struct hrtimer hrt;
43 int poll_time; 43 int poll_time_ns;
44 struct snd_pcm_substream *substream;
45 atomic_t running;
44}; 46};
45 47
46static inline void imx_ssi_set_next_poll(struct imx_pcm_runtime_data *iprtd) 48static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
47{ 49{
48 iprtd->timer.expires = jiffies + iprtd->poll_time; 50 struct imx_pcm_runtime_data *iprtd =
49} 51 container_of(hrt, struct imx_pcm_runtime_data, hrt);
50 52 struct snd_pcm_substream *substream = iprtd->substream;
51static void imx_ssi_timer_callback(unsigned long data)
52{
53 struct snd_pcm_substream *substream = (void *)data;
54 struct snd_pcm_runtime *runtime = substream->runtime; 53 struct snd_pcm_runtime *runtime = substream->runtime;
55 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
56 struct pt_regs regs; 54 struct pt_regs regs;
57 unsigned long delta; 55 unsigned long delta;
58 56
57 if (!atomic_read(&iprtd->running))
58 return HRTIMER_NORESTART;
59
59 get_fiq_regs(&regs); 60 get_fiq_regs(&regs);
60 61
61 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 62 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -72,16 +73,14 @@ static void imx_ssi_timer_callback(unsigned long data)
72 73
73 /* If we've transferred at least a period then report it and 74 /* If we've transferred at least a period then report it and
74 * reset our poll time */ 75 * reset our poll time */
75 if (delta >= runtime->period_size) { 76 if (delta >= iprtd->period) {
76 snd_pcm_period_elapsed(substream); 77 snd_pcm_period_elapsed(substream);
77 iprtd->last_offset = iprtd->offset; 78 iprtd->last_offset = iprtd->offset;
78
79 imx_ssi_set_next_poll(iprtd);
80 } 79 }
81 80
82 /* Restart the timer; if we didn't report we'll run on the next tick */ 81 hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns));
83 add_timer(&iprtd->timer);
84 82
83 return HRTIMER_RESTART;
85} 84}
86 85
87static struct fiq_handler fh = { 86static struct fiq_handler fh = {
@@ -99,8 +98,8 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
99 iprtd->period = params_period_bytes(params) ; 98 iprtd->period = params_period_bytes(params) ;
100 iprtd->offset = 0; 99 iprtd->offset = 0;
101 iprtd->last_offset = 0; 100 iprtd->last_offset = 0;
102 iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params)); 101 iprtd->poll_time_ns = 1000000000 / params_rate(params) *
103 102 params_period_size(params);
104 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 103 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
105 104
106 return 0; 105 return 0;
@@ -135,8 +134,9 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
135 case SNDRV_PCM_TRIGGER_START: 134 case SNDRV_PCM_TRIGGER_START:
136 case SNDRV_PCM_TRIGGER_RESUME: 135 case SNDRV_PCM_TRIGGER_RESUME:
137 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 136 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
138 imx_ssi_set_next_poll(iprtd); 137 atomic_set(&iprtd->running, 1);
139 add_timer(&iprtd->timer); 138 hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns),
139 HRTIMER_MODE_REL);
140 if (++fiq_enable == 1) 140 if (++fiq_enable == 1)
141 enable_fiq(imx_pcm_fiq); 141 enable_fiq(imx_pcm_fiq);
142 142
@@ -145,11 +145,11 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
145 case SNDRV_PCM_TRIGGER_STOP: 145 case SNDRV_PCM_TRIGGER_STOP:
146 case SNDRV_PCM_TRIGGER_SUSPEND: 146 case SNDRV_PCM_TRIGGER_SUSPEND:
147 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 147 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
148 del_timer(&iprtd->timer); 148 atomic_set(&iprtd->running, 0);
149
149 if (--fiq_enable == 0) 150 if (--fiq_enable == 0)
150 disable_fiq(imx_pcm_fiq); 151 disable_fiq(imx_pcm_fiq);
151 152
152
153 break; 153 break;
154 default: 154 default:
155 return -EINVAL; 155 return -EINVAL;
@@ -180,7 +180,7 @@ static struct snd_pcm_hardware snd_imx_hardware = {
180 .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, 180 .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
181 .period_bytes_min = 128, 181 .period_bytes_min = 128,
182 .period_bytes_max = 16 * 1024, 182 .period_bytes_max = 16 * 1024,
183 .periods_min = 2, 183 .periods_min = 4,
184 .periods_max = 255, 184 .periods_max = 255,
185 .fifo_size = 0, 185 .fifo_size = 0,
186}; 186};
@@ -194,9 +194,11 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
194 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); 194 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
195 runtime->private_data = iprtd; 195 runtime->private_data = iprtd;
196 196
197 init_timer(&iprtd->timer); 197 iprtd->substream = substream;
198 iprtd->timer.data = (unsigned long)substream; 198
199 iprtd->timer.function = imx_ssi_timer_callback; 199 atomic_set(&iprtd->running, 0);
200 hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
201 iprtd->hrt.function = snd_hrtimer_callback;
200 202
201 ret = snd_pcm_hw_constraint_integer(substream->runtime, 203 ret = snd_pcm_hw_constraint_integer(substream->runtime,
202 SNDRV_PCM_HW_PARAM_PERIODS); 204 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -212,7 +214,8 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
212 struct snd_pcm_runtime *runtime = substream->runtime; 214 struct snd_pcm_runtime *runtime = substream->runtime;
213 struct imx_pcm_runtime_data *iprtd = runtime->private_data; 215 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
214 216
215 del_timer_sync(&iprtd->timer); 217 hrtimer_cancel(&iprtd->hrt);
218
216 kfree(iprtd); 219 kfree(iprtd);
217 220
218 return 0; 221 return 0;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 0bcc6d7d9471..80b4fee2442b 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -656,7 +656,8 @@ static int imx_ssi_probe(struct platform_device *pdev)
656 dai->private_data = ssi; 656 dai->private_data = ssi;
657 657
658 if ((cpu_is_mx27() || cpu_is_mx21()) && 658 if ((cpu_is_mx27() || cpu_is_mx21()) &&
659 !(ssi->flags & IMX_SSI_USE_AC97)) { 659 !(ssi->flags & IMX_SSI_USE_AC97) &&
660 (ssi->flags & IMX_SSI_DMA)) {
660 ssi->flags |= IMX_SSI_DMA; 661 ssi->flags |= IMX_SSI_DMA;
661 platform = imx_ssi_dma_mx2_init(pdev, ssi); 662 platform = imx_ssi_dma_mx2_init(pdev, ssi);
662 } else 663 } else