Root/target/linux/ubicom32/files/sound/ubicom32/ubi32-pcm.c

1/*
2 * sound/ubicom32/ubi32-pcm.c
3 * Interface to ubicom32 virtual audio peripheral
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28
29#include <linux/interrupt.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <asm/ip5000.h>
34#include <asm/ubi32-pcm.h>
35#include <linux/dma-mapping.h>
36#include <linux/delay.h>
37#include "ubi32.h"
38
39struct ubi32_snd_runtime_data {
40    dma_addr_t dma_buffer; /* Physical address of DMA buffer */
41    dma_addr_t dma_buffer_end; /* First address beyond end of DMA buffer */
42    size_t period_size;
43    dma_addr_t period_ptr; /* Physical address of next period */
44    unsigned int flags;
45};
46
47static void snd_ubi32_vp_int_set(struct snd_pcm *pcm)
48{
49    struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
50    ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx);
51    ubicom32_set_interrupt(ubi32_priv->tx_irq);
52}
53
54static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream)
55{
56
57    struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58    struct audio_dev_regs *adr = ubi32_priv->adr;
59    struct snd_pcm_runtime *runtime = substream->runtime;
60    struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
61
62    dma_addr_t read_pos;
63
64    snd_pcm_uframes_t frames;
65    if (!adr->primary_os_buffer_ptr) {
66        /*
67         * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or
68         * when the HW is stopped), then handle this case separately.
69         */
70        return 0;
71    }
72
73    read_pos = (dma_addr_t)adr->primary_os_buffer_ptr;
74    frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer);
75    if (frames == runtime->buffer_size) {
76        frames = 0;
77    }
78    return frames;
79}
80
81/*
82 * Audio trigger
83 */
84static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
85{
86    struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
87    struct audio_dev_regs *adr = ubi32_priv->adr;
88    struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
89    int ret = 0;
90
91#ifdef CONFIG_SND_DEBUG
92    snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd);
93#endif
94
95    if (adr->command != AUDIO_CMD_NONE) {
96        snd_printk(KERN_WARNING "Can't send command to audio device at this time\n");
97        // Set a timer to call this function back later. How to do this?
98        return 0;
99    }
100
101    /*
102     * Set interrupt flag to indicate that we interrupted audio device
103     * to send a command
104     */
105
106    switch (cmd) {
107    case SNDRV_PCM_TRIGGER_START:
108
109#ifdef CONFIG_SND_DEBUG
110        snd_printk(KERN_INFO "START\n");
111#endif
112        /*
113         * Ready the DMA transfer
114         */
115        ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
116
117#ifdef CONFIG_SND_DEBUG
118        snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr);
119#endif
120        adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr;
121        adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size;
122        adr->dma_xfer_requests[0].active = 1;
123
124#ifdef CONFIG_SND_DEBUG
125        snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
126#endif
127
128        ubi32_rd->period_ptr += ubi32_rd->period_size;
129        adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr;
130        adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size;
131        adr->dma_xfer_requests[1].active = 1;
132
133#ifdef CONFIG_SND_DEBUG
134        snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
135#endif
136
137        /*
138         * Tell the VP that we want to begin playback by filling in the
139         * command field and then interrupting the audio VP
140         */
141        adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
142        adr->command = AUDIO_CMD_START;
143        snd_ubi32_vp_int_set(substream->pcm);
144        break;
145
146    case SNDRV_PCM_TRIGGER_STOP:
147
148#ifdef CONFIG_SND_DEBUG
149        snd_printk(KERN_INFO "STOP\n");
150#endif
151
152        /*
153         * Tell the VP that we want to stop playback by filling in the
154         * command field and then interrupting the audio VP
155         */
156        adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
157        adr->command = AUDIO_CMD_STOP;
158        snd_ubi32_vp_int_set(substream->pcm);
159        break;
160
161    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
162
163#ifdef CONFIG_SND_DEBUG
164        snd_printk(KERN_INFO "PAUSE_PUSH\n");
165#endif
166
167        /*
168         * Tell the VP that we want to pause playback by filling in the
169         * command field and then interrupting the audio VP
170         */
171        adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
172        adr->command = AUDIO_CMD_PAUSE;
173        snd_ubi32_vp_int_set(substream->pcm);
174        break;
175
176    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
177
178#ifdef CONFIG_SND_DEBUG
179        snd_printk(KERN_INFO "PAUSE_RELEASE\n");
180#endif
181        /*
182         * Tell the VP that we want to resume paused playback by filling
183         * in the command field and then interrupting the audio VP
184         */
185        adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
186        adr->command = AUDIO_CMD_RESUME;
187        snd_ubi32_vp_int_set(substream->pcm);
188        break;
189
190    default:
191        snd_printk(KERN_WARNING "Unhandled trigger\n");
192        ret = -EINVAL;
193        break;
194    }
195
196    return ret;
197}
198
199/*
200 * Prepare to transfer an audio stream to the codec
201 */
202static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream)
203{
204    /*
205     * Configure registers and setup the runtime instance for DMA transfers
206     */
207    struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
208    struct audio_dev_regs *adr = ubi32_priv->adr;
209
210#ifdef CONFIG_SND_DEBUG
211    snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n");
212#endif
213
214    /*
215     * Make sure the audio device is stopped
216     */
217
218    /*
219     * Set interrupt flag to indicate that we interrupted audio device
220     * to send a command
221     */
222    adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
223    adr->command = AUDIO_CMD_STOP;
224    snd_ubi32_vp_int_set(substream->pcm);
225
226    return 0;
227}
228
229/*
230 * Allocate DMA buffers from preallocated memory.
231 * Preallocation was done in snd_ubi32_pcm_new()
232 */
233static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream,
234                    struct snd_pcm_hw_params *hw_params)
235{
236    struct snd_pcm_runtime *runtime = substream->runtime;
237    struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
238    struct audio_dev_regs *adr = ubi32_priv->adr;
239    struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
240
241    /*
242     * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy
243     * this memory request.
244     */
245    int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
246    if (ret < 0) {
247        return ret;
248    }
249
250#ifdef CONFIG_SND_DEBUG
251    snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n");
252#endif
253
254    if (!(adr->channel_mask & (1 << params_channels(hw_params)))) {
255        snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask);
256        return -EINVAL;
257    }
258
259    if (ubi32_priv->set_channels) {
260        int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params));
261        if (ret) {
262            snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret);
263            return ret;
264        }
265    }
266
267    if (ubi32_priv->set_rate) {
268        int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params));
269        if (ret) {
270            snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
271            return ret;
272        }
273    }
274
275    if (ubi32_priv->pdata->set_rate) {
276        int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params));
277        if (ret) {
278            snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
279            return ret;
280        }
281    }
282
283    if (adr->command != AUDIO_CMD_NONE) {
284        snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n");
285        return -EAGAIN;
286    }
287
288    if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) {
289        adr->flags |= CMD_START_FLAG_LE;
290    } else {
291        adr->flags &= ~CMD_START_FLAG_LE;
292    }
293    adr->channels = params_channels(hw_params);
294    adr->sample_rate = params_rate(hw_params);
295    adr->command = AUDIO_CMD_SETUP;
296    adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
297    snd_ubi32_vp_int_set(substream->pcm);
298
299    /*
300     * Wait for the command to complete
301     */
302    while (adr->command != AUDIO_CMD_NONE) {
303        udelay(1);
304    }
305
306    /*
307     * Put the DMA info into the DMA descriptor that we will
308     * use to do transfers to our audio VP "hardware"
309     */
310
311    /*
312     * Mark both DMA transfers as not ready/inactive
313     */
314    adr->dma_xfer_requests[0].active = 0;
315    adr->dma_xfer_requests[1].active = 0;
316
317    /*
318     * Put the location of the buffer into the runtime data instance
319     */
320    ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area;
321    ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes);
322
323    /*
324     * Get the period size
325     */
326    ubi32_rd->period_size = params_period_bytes(hw_params);
327
328#ifdef CONFIG_SND_DEBUG
329    snd_printk(KERN_INFO "DMA for ubi32 audio initialized dma_area=0x%x dma_bytes=%d, period_size=%d\n", (unsigned int)runtime->dma_area, (unsigned int)runtime->dma_bytes, ubi32_rd->period_size);
330    snd_printk(KERN_INFO "Private buffer ubi32_rd: dma_buffer=0x%x dma_buffer_end=0x%x ret=%d\n", ubi32_rd->dma_buffer, ubi32_rd->dma_buffer_end, ret);
331#endif
332
333    return ret;
334}
335
336/*
337 * This is the reverse of snd_ubi32_pcm_hw_params
338 */
339static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream)
340{
341#ifdef CONFIG_SND_DEBUG
342    snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n");
343#endif
344    return snd_pcm_lib_free_pages(substream);
345}
346
347/*
348 * Audio virtual peripheral capabilities (capture and playback are identical)
349 */
350static struct snd_pcm_hardware snd_ubi32_pcm_hw =
351{
352    .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
353         SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
354    .buffer_bytes_max = (64*1024),
355    .period_bytes_min = 64,
356    .period_bytes_max = 8184,//8184,//8176,
357    .periods_min = 2,
358    .periods_max = 255,
359    .fifo_size = 0, // THIS IS IGNORED BY ALSA
360};
361
362/*
363 * We fill this in later
364 */
365static struct snd_pcm_hw_constraint_list ubi32_pcm_rates;
366
367/*
368 * snd_ubi32_pcm_close
369 */
370static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream)
371{
372    /* Disable codec, stop DMA, free private data structures */
373    //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
374    struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
375
376#ifdef CONFIG_SND_DEBUG
377    snd_printk(KERN_INFO "snd_ubi32_pcm_close\n");
378#endif
379
380    substream->runtime->private_data = NULL;
381
382    kfree(ubi32_rd);
383
384    return 0;
385}
386
387/*
388 * snd_ubi32_pcm_open
389 */
390static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream)
391{
392    struct snd_pcm_runtime *runtime = substream->runtime;
393    struct ubi32_snd_runtime_data *ubi32_rd;
394    int ret = 0;
395
396#ifdef CONFIG_SND_DEBUG
397    snd_printk(KERN_INFO "ubi32 pcm open\n");
398#endif
399
400    /* Associate capabilities with component */
401    runtime->hw = snd_ubi32_pcm_hw;
402
403    /*
404     * Inform ALSA about constraints of the audio device
405     */
406    ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates);
407    if (ret < 0) {
408        snd_printk(KERN_INFO "invalid rate\n");
409        goto out;
410    }
411
412    /* Force the buffer size to be an integer multiple of period size */
413    ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
414    if (ret < 0) {
415        snd_printk(KERN_INFO "invalid period\n");
416        goto out;
417    }
418    /* Initialize structures/registers */
419    ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL);
420    if (ubi32_rd == NULL) {
421        ret = -ENOMEM;
422        goto out;
423    }
424
425    runtime->private_data = ubi32_rd;
426
427#ifdef CONFIG_SND_DEBUG
428    snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n");
429#endif
430
431    return 0;
432out:
433#ifdef CONFIG_SND_DEBUG
434    snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret);
435#endif
436
437    return ret;
438}
439
440static struct snd_pcm_ops snd_ubi32_pcm_ops = {
441    .open = snd_ubi32_pcm_open, /* Open */
442    .close = snd_ubi32_pcm_close, /* Close */
443    .ioctl = snd_pcm_lib_ioctl, /* Generic IOCTL handler */
444    .hw_params = snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */
445    .hw_free = snd_ubi32_pcm_hw_free, /* Free function for hw_params */
446    .prepare = snd_ubi32_pcm_prepare,
447    .trigger = snd_ubi32_pcm_trigger,
448    .pointer = snd_ubi32_pcm_pointer,
449};
450
451/*
452 * Interrupt handler that gets called when the audio device
453 * interrupts Linux
454 */
455static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata)
456{
457    struct snd_pcm *pcm = (struct snd_pcm *)appdata;
458    struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
459    struct audio_dev_regs *adr = ubi32_priv->adr;
460    struct snd_pcm_substream *substream;
461    struct ubi32_snd_runtime_data *ubi32_rd;
462    int dma_to_fill = 0;
463
464    /*
465     * Check to see if the interrupt is for us
466     */
467    if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) {
468        return IRQ_NONE;
469    }
470
471    /*
472     * Clear the interrupt
473     */
474    ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx);
475
476    /*
477     * We only have one stream since we don't mix. Therefore
478     * we don't need to search through substreams.
479     */
480    if (ubi32_priv->is_capture) {
481        substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
482    } else {
483        substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
484    }
485
486    if (!substream->runtime) {
487        snd_printk(KERN_WARNING "No runtime data\n");
488        return IRQ_NONE;
489    }
490
491    ubi32_rd = substream->runtime->private_data;
492
493#ifdef CONFIG_SND_DEBUG
494    snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n");
495#endif
496
497    if (ubi32_rd == NULL) {
498        snd_printk(KERN_WARNING "No private data\n");
499        return IRQ_NONE;
500    }
501
502    // Check interrupt cause
503    if (0) {
504        // Handle the underflow case
505    } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) ||
506           (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) {
507        if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) {
508            dma_to_fill = 0;
509            adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST;
510        } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) {
511            dma_to_fill = 1;
512            adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST;
513        }
514        ubi32_rd->period_ptr += ubi32_rd->period_size;
515        if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) {
516            ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
517        }
518        adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr;
519        adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size;
520        adr->dma_xfer_requests[dma_to_fill].active = 1;
521#ifdef CONFIG_SND_DEBUG
522        snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size);
523#endif
524        adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES;
525        snd_ubi32_vp_int_set(substream->pcm);
526    }
527    // If we are interrupted by the VP, that means we completed
528    // processing one period of audio. We need to inform the upper
529    // layers of ALSA of this.
530    snd_pcm_period_elapsed(substream);
531
532    return IRQ_HANDLED;
533}
534
535void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv)
536{
537    struct snd_pcm *pcm = ubi32_priv->pcm;
538    free_irq(ubi32_priv->rx_irq, pcm);
539}
540
541#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
542#error "Change this table to match pcm.h"
543#endif
544static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050,
545                      32000, 44100, 48000, 64000, 88200,
546                      96000, 176400, 192000};
547
548/*
549 * snd_ubi32_pcm_probe
550 */
551int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev)
552{
553    struct snd_pcm *pcm;
554    int ret, err;
555    int i;
556    int j;
557    int nrates;
558    unsigned int rate_max = 0;
559    unsigned int rate_min = 0xFFFFFFFF;
560    unsigned int rate_mask = 0;
561    struct audio_dev_regs *adr;
562    struct resource *res_adr;
563    struct resource *res_irq_tx;
564    struct resource *res_irq_rx;
565    struct ubi32pcm_platform_data *pdata;
566
567    pdata = pdev->dev.platform_data;
568    if (!pdata) {
569        return -ENODEV;
570    }
571
572    /*
573     * Get our resources, adr is the hardware driver base address
574     * and the tx and rx irqs are used to communicate with the
575     * hardware driver.
576     */
577    res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE);
578    res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE);
579    res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE);
580    if (!res_adr || !res_irq_tx || !res_irq_rx) {
581        snd_printk(KERN_WARNING "Could not get resources");
582        return -ENODEV;
583    }
584
585    ubi32_priv->ar = (struct audio_regs *)res_adr->start;
586    ubi32_priv->tx_irq = res_irq_tx->start;
587    ubi32_priv->rx_irq = res_irq_rx->start;
588    ubi32_priv->irq_idx = pdata->inst_num;
589    ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]);
590
591    /*
592     * Check the version
593     */
594    adr = ubi32_priv->adr;
595    if (adr->version != AUDIO_DEV_REGS_VERSION) {
596        snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n");
597        return -ENODEV;
598    }
599
600    /*
601     * Find out the standard rates, also find max and min rates
602     */
603    for (i = 0; i < ARRAY_SIZE(rates); i++) {
604        int found = 0;
605        for (j = 0; j < adr->n_sample_rates; j++) {
606            if (rates[i] == adr->sample_rates[j]) {
607                /*
608                 * Check to see if it is supported by the dac
609                 */
610                if ((rates[i] >= ubi32_priv->min_sample_rate) &&
611                    (!ubi32_priv->max_sample_rate ||
612                     (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) {
613                    found = 1;
614                    rate_mask |= (1 << i);
615                    nrates++;
616                    if (rates[i] < rate_min) {
617                        rate_min = rates[i];
618                    }
619                    if (rates[i] > rate_max) {
620                        rate_max = rates[i];
621                    }
622                    break;
623                }
624            }
625        }
626        if (!found) {
627            rate_mask |= SNDRV_PCM_RATE_KNOT;
628        }
629    }
630
631    snd_ubi32_pcm_hw.rates = rate_mask;
632    snd_ubi32_pcm_hw.rate_min = rate_min;
633    snd_ubi32_pcm_hw.rate_max = rate_max;
634    ubi32_pcm_rates.count = adr->n_sample_rates;
635    ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates;
636    ubi32_pcm_rates.mask = 0;
637
638    for (i = 0; i < 32; i++) {
639        if (adr->channel_mask & (1 << i)) {
640            if (!snd_ubi32_pcm_hw.channels_min) {
641                snd_ubi32_pcm_hw.channels_min = i;
642            }
643            snd_ubi32_pcm_hw.channels_max = i;
644        }
645    }
646    snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n",
647           snd_ubi32_pcm_hw.channels_min,
648           snd_ubi32_pcm_hw.channels_max);
649
650    if (adr->caps & AUDIONODE_CAP_BE) {
651        snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE;
652    }
653    if (adr->caps & AUDIONODE_CAP_LE) {
654        snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
655    }
656
657    snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n",
658           snd_ubi32_pcm_hw.rates,
659           snd_ubi32_pcm_hw.rate_min,
660           snd_ubi32_pcm_hw.rate_max,
661           ubi32_pcm_rates.count,
662           snd_ubi32_pcm_hw.formats,
663           ubi32_priv->is_capture ? "capture" : "playback");
664
665    if (ubi32_priv->is_capture) {
666        ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm);
667    } else {
668        ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm);
669    }
670
671    if (ret < 0) {
672        return ret;
673    }
674
675    pcm->private_data = ubi32_priv;
676    ubi32_priv->pcm = pcm;
677    ubi32_priv->pdata = pdata;
678
679    pcm->info_flags = 0;
680
681    strcpy(pcm->name, "Ubi32-PCM");
682
683    snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
684                          snd_dma_continuous_data(GFP_KERNEL),
685                          45*1024, 64*1024);
686
687    if (ubi32_priv->is_capture) {
688        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops);
689    } else {
690        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops);
691    }
692
693    /*
694     * Start up the audio device
695     */
696    adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
697    adr->command = AUDIO_CMD_ENABLE;
698    snd_ubi32_vp_int_set(pcm);
699
700    /*
701     * Request IRQ
702     */
703    err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm);
704    if (err) {
705        snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err);
706        return -ENODEV;
707    }
708
709    return ret;
710
711}
712

Archive Download this file



interactive