~ubuntu-branches/ubuntu/precise/alsa-driver/precise

« back to all changes in this revision

Viewing changes to alsa-kernel/soc/imx/imx-pcm-fiq.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2011-02-21 18:06:40 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20110221180640-a8p2yxtvgf7xbxub
Tags: 1.0.24+dfsg-0ubuntu1
* New upstream release
* Refreshed patches:
  - distinguish_kernel_makefile_and_source_dirs.patch
  - debian_dfsg_configure.patch
* debian/control: Update Vcs-bzr field to point to new branch location

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
        unsigned long offset;
40
40
        unsigned long last_offset;
41
41
        unsigned long size;
42
 
        struct timer_list timer;
43
 
        int poll_time;
 
42
        struct hrtimer hrt;
 
43
        int poll_time_ns;
 
44
        struct snd_pcm_substream *substream;
 
45
        atomic_t running;
44
46
};
45
47
 
46
 
static inline void imx_ssi_set_next_poll(struct imx_pcm_runtime_data *iprtd)
47
 
{
48
 
        iprtd->timer.expires = jiffies + iprtd->poll_time;
49
 
}
50
 
 
51
 
static void imx_ssi_timer_callback(unsigned long data)
52
 
{
53
 
        struct snd_pcm_substream *substream = (void *)data;
 
48
static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
 
49
{
 
50
        struct imx_pcm_runtime_data *iprtd =
 
51
                container_of(hrt, struct imx_pcm_runtime_data, hrt);
 
52
        struct snd_pcm_substream *substream = iprtd->substream;
54
53
        struct snd_pcm_runtime *runtime = substream->runtime;
55
 
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
56
54
        struct pt_regs regs;
57
55
        unsigned long delta;
58
56
 
 
57
        if (!atomic_read(&iprtd->running))
 
58
                return HRTIMER_NORESTART;
 
59
 
59
60
        get_fiq_regs(&regs);
60
61
 
61
62
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
72
73
 
73
74
        /* If we've transferred at least a period then report it and
74
75
         * reset our poll time */
75
 
        if (delta >= runtime->period_size) {
 
76
        if (delta >= iprtd->period) {
76
77
                snd_pcm_period_elapsed(substream);
77
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 */
83
 
        add_timer(&iprtd->timer);
 
81
        hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns));
84
82
 
 
83
        return HRTIMER_RESTART;
85
84
}
86
85
 
87
86
static struct fiq_handler fh = {
99
98
        iprtd->period = params_period_bytes(params) ;
100
99
        iprtd->offset = 0;
101
100
        iprtd->last_offset = 0;
102
 
        iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params));
103
 
 
 
101
        iprtd->poll_time_ns = 1000000000 / params_rate(params) *
 
102
                                params_period_size(params);
104
103
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
105
104
 
106
105
        return 0;
135
134
        case SNDRV_PCM_TRIGGER_START:
136
135
        case SNDRV_PCM_TRIGGER_RESUME:
137
136
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
138
 
                imx_ssi_set_next_poll(iprtd);
139
 
                add_timer(&iprtd->timer);
 
137
                atomic_set(&iprtd->running, 1);
 
138
                hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns),
 
139
                      HRTIMER_MODE_REL);
140
140
                if (++fiq_enable == 1)
141
141
                        enable_fiq(imx_pcm_fiq);
142
142
 
145
145
        case SNDRV_PCM_TRIGGER_STOP:
146
146
        case SNDRV_PCM_TRIGGER_SUSPEND:
147
147
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
148
 
                del_timer(&iprtd->timer);
 
148
                atomic_set(&iprtd->running, 0);
 
149
 
149
150
                if (--fiq_enable == 0)
150
151
                        disable_fiq(imx_pcm_fiq);
151
152
 
152
 
 
153
153
                break;
154
154
        default:
155
155
                return -EINVAL;
180
180
        .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
181
181
        .period_bytes_min = 128,
182
182
        .period_bytes_max = 16 * 1024,
183
 
        .periods_min = 2,
 
183
        .periods_min = 4,
184
184
        .periods_max = 255,
185
185
        .fifo_size = 0,
186
186
};
192
192
        int ret;
193
193
 
194
194
        iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
 
195
        if (iprtd == NULL)
 
196
                return -ENOMEM;
195
197
        runtime->private_data = iprtd;
196
198
 
197
 
        init_timer(&iprtd->timer);
198
 
        iprtd->timer.data = (unsigned long)substream;
199
 
        iprtd->timer.function = imx_ssi_timer_callback;
 
199
        iprtd->substream = substream;
 
200
 
 
201
        atomic_set(&iprtd->running, 0);
 
202
        hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 
203
        iprtd->hrt.function = snd_hrtimer_callback;
200
204
 
201
205
        ret = snd_pcm_hw_constraint_integer(substream->runtime,
202
206
                        SNDRV_PCM_HW_PARAM_PERIODS);
203
 
        if (ret < 0)
 
207
        if (ret < 0) {
 
208
                kfree(iprtd);
204
209
                return ret;
 
210
        }
205
211
 
206
212
        snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
207
213
        return 0;
212
218
        struct snd_pcm_runtime *runtime = substream->runtime;
213
219
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
214
220
 
215
 
        del_timer_sync(&iprtd->timer);
 
221
        hrtimer_cancel(&iprtd->hrt);
 
222
 
216
223
        kfree(iprtd);
217
224
 
218
225
        return 0;
229
236
        .mmap           = snd_imx_pcm_mmap,
230
237
};
231
238
 
 
239
static int ssi_irq = 0;
 
240
 
232
241
static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
233
242
        struct snd_pcm *pcm)
234
243
{
238
247
        if (ret)
239
248
                return ret;
240
249
 
241
 
        if (dai->playback.channels_min) {
 
250
        if (dai->driver->playback.channels_min) {
242
251
                struct snd_pcm_substream *substream =
243
252
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
244
253
                struct snd_dma_buffer *buf = &substream->dma_buffer;
246
255
                imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;
247
256
        }
248
257
 
249
 
        if (dai->capture.channels_min) {
 
258
        if (dai->driver->capture.channels_min) {
250
259
                struct snd_pcm_substream *substream =
251
260
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
252
261
                struct snd_dma_buffer *buf = &substream->dma_buffer;
260
269
        return 0;
261
270
}
262
271
 
263
 
static struct snd_soc_platform imx_soc_platform_fiq = {
264
 
        .pcm_ops        = &imx_pcm_ops,
 
272
static void imx_pcm_fiq_free(struct snd_pcm *pcm)
 
273
{
 
274
        mxc_set_irq_fiq(ssi_irq, 0);
 
275
        release_fiq(&fh);
 
276
        imx_pcm_free(pcm);
 
277
}
 
278
 
 
279
static struct snd_soc_platform_driver imx_soc_platform_fiq = {
 
280
        .ops            = &imx_pcm_ops,
265
281
        .pcm_new        = imx_pcm_fiq_new,
266
 
        .pcm_free       = imx_pcm_free,
 
282
        .pcm_free       = imx_pcm_fiq_free,
267
283
};
268
284
 
269
 
struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
270
 
                struct imx_ssi *ssi)
 
285
static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
271
286
{
272
 
        int ret = 0;
 
287
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
288
        int ret;
273
289
 
274
290
        ret = claim_fiq(&fh);
275
291
        if (ret) {
276
292
                dev_err(&pdev->dev, "failed to claim fiq: %d", ret);
277
 
                return ERR_PTR(ret);
 
293
                return ret;
278
294
        }
279
295
 
280
296
        mxc_set_irq_fiq(ssi->irq, 1);
 
297
        ssi_irq = ssi->irq;
281
298
 
282
299
        imx_pcm_fiq = ssi->irq;
283
300
 
286
303
        ssi->dma_params_tx.burstsize = 4;
287
304
        ssi->dma_params_rx.burstsize = 6;
288
305
 
289
 
        return &imx_soc_platform_fiq;
290
 
}
291
 
 
292
 
void imx_ssi_fiq_exit(struct platform_device *pdev,
293
 
                struct imx_ssi *ssi)
294
 
{
295
 
        mxc_set_irq_fiq(ssi->irq, 0);
 
306
        ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
 
307
        if (ret)
 
308
                goto failed_register;
 
309
 
 
310
        return 0;
 
311
 
 
312
failed_register:
 
313
        mxc_set_irq_fiq(ssi_irq, 0);
296
314
        release_fiq(&fh);
297
 
}
298
 
 
 
315
 
 
316
        return ret;
 
317
}
 
318
 
 
319
static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
 
320
{
 
321
        snd_soc_unregister_platform(&pdev->dev);
 
322
        return 0;
 
323
}
 
324
 
 
325
static struct platform_driver imx_pcm_driver = {
 
326
        .driver = {
 
327
                        .name = "imx-fiq-pcm-audio",
 
328
                        .owner = THIS_MODULE,
 
329
        },
 
330
 
 
331
        .probe = imx_soc_platform_probe,
 
332
        .remove = __devexit_p(imx_soc_platform_remove),
 
333
};
 
334
 
 
335
static int __init snd_imx_pcm_init(void)
 
336
{
 
337
        return platform_driver_register(&imx_pcm_driver);
 
338
}
 
339
module_init(snd_imx_pcm_init);
 
340
 
 
341
static void __exit snd_imx_pcm_exit(void)
 
342
{
 
343
        platform_driver_unregister(&imx_pcm_driver);
 
344
}
 
345
module_exit(snd_imx_pcm_exit);