static int mxs_pcm_dma_request(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct mxs_runtime_data *prtd = runtime->private_data; struct mxs_pcm_dma_params *dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); int desc_num = mxs_pcm_hardware.periods_max; int desc; int ret; if (!dma_data) return -ENODEV; prtd->params = dma_data; prtd->dma_ch = dma_data->dma_ch; ret = mxs_dma_request(prtd->dma_ch, mxs_pcm_dev, prtd->params->name); if (ret) { printk(KERN_ERR "%s: Failed to request DMA channel (%d:%d)\n", __func__, dma_data->dma_bus, dma_data->dma_ch); return ret; } /* Allocate memory for data and pio DMA descriptors */ for (desc = 0; desc < desc_num; desc++) { prtd->dma_desc_array[desc] = mxs_dma_alloc_desc(); if (prtd->dma_desc_array[desc] == NULL) { printk(KERN_ERR"%s Unable to allocate DMA command %d\n", __func__, desc); goto err; } } ret = request_irq(prtd->params->irq, mxs_pcm_dma_irq, 0, "MXS PCM DMA", substream); if (ret) { printk(KERN_ERR "%s: Unable to request DMA irq %d\n", __func__, prtd->params->irq); goto err; } /* Enable completion interrupt */ mxs_dma_ack_irq(prtd->dma_ch); mxs_dma_enable_irq(prtd->dma_ch, 1); return 0; err: while (--desc >= 0) mxs_dma_free_desc(prtd->dma_desc_array[desc]); mxs_dma_release(prtd->dma_ch, mxs_pcm_dev); return ret; }
static int __devinit mxs_hsadc_probe(struct platform_device *pdev) { struct mxs_hsadc_data *pd; struct resource *res; int rlevel = 0; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (pd) rlevel++; else goto quit; pd->dev = &pdev->dev; platform_set_drvdata(pdev, pd); pd->pdev = pdev; rlevel++; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) goto quit; pd->hsadc_base = ioremap(res->start, res->end - res->start); if (pd->hsadc_base) rlevel++; else goto quit; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res == NULL) goto quit; pd->pwm_base = ioremap(res->start, res->end - res->start); if (pd->pwm_base) rlevel++; else goto quit; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res) pd->dev_irq = res->start; else goto quit; res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (res) pd->dma_irq = res->start; else goto quit; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) pd->dma_ch = res->start; else goto quit; pd->ref_hsadc_clk = clk_get(NULL, "ref_hsadc"); if (pd->ref_hsadc_clk) rlevel++; else goto quit; pd->hsadc_clk = clk_get(NULL, "hsadc"); if (pd->hsadc_clk) rlevel++; else goto quit; pd->pwm_clk = clk_get(NULL, "pwm"); if (pd->pwm_clk) rlevel++; else goto quit; clk_enable(pd->ref_hsadc_clk); clk_enable(pd->hsadc_clk); clk_enable(pd->pwm_clk); rlevel++; clk_set_rate(pd->ref_hsadc_clk, REF_HSADC_FREQ); clk_set_rate(pd->hsadc_clk, HSADC_FREQ); if (request_irq(pd->dma_irq, hsadc_dma_isr, 0, "hsadc dma", pd)) goto quit; else rlevel++; if (request_irq(pd->dev_irq, hsadc_isr, 0, "hsadc irq", pd)) goto quit; else rlevel++; if (mxs_dma_request(pd->dma_ch, pd->dev, "hsadc")) goto quit; else rlevel++; mxs_dma_disable(pd->dma_ch); pd->desc = mxs_dma_alloc_desc(); if (pd->desc==NULL) goto quit; memset(&pd->desc->cmd, 0, sizeof(pd->desc->cmd)); rlevel++; pd->buf = dma_alloc_coherent(NULL, DMA_BUF_SIZE, &pd->buf_phy, GFP_KERNEL); if(!pd->buf) goto quit; rlevel++; if(hsadc_init_cdev(pd)) goto quit; #if HSADC_DEBUG printk(KERN_INFO "%s> probe successed.\n", HSADC_DEVICE_NAME); #endif return 0; quit: pr_err("%s quit at rlevel %d\n", __func__, rlevel); switch (rlevel) { case 14: hsadc_cleanup_cdev(pd); case 13: if (pd->buf_phy) dma_free_coherent(NULL, DMA_BUF_SIZE, pd->buf, pd->buf_phy); case 12: if (pd->desc) mxs_dma_free_desc(pd->desc); case 11: mxs_dma_release(pd->dma_ch, pd->dev); case 10: free_irq(pd->dev_irq, pd); case 9: free_irq(pd->dma_irq, pd); case 8: clk_disable(pd->pwm_clk); clk_disable(pd->hsadc_clk); clk_disable(pd->ref_hsadc_clk); case 7: clk_put(pd->pwm_clk); case 6: clk_put(pd->hsadc_clk); case 5: clk_put(pd->ref_hsadc_clk); case 4: iounmap(pd->pwm_base); case 3: iounmap(pd->hsadc_base); case 2: platform_set_drvdata(pdev, NULL); case 1: kfree(pd); case 0: default: return -ENODEV; } }