0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/interrupt.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/dma-mapping.h>
0011 #include <linux/slab.h>
0012 #include <linux/module.h>
0013 #include <sound/pcm.h>
0014 #include <sound/pcm_params.h>
0015 #include <sound/soc.h>
0016
0017 #include "i2s.h"
0018 #include "idma.h"
0019 #include "i2s-regs.h"
0020
0021 #define ST_RUNNING (1<<0)
0022 #define ST_OPENED (1<<1)
0023
0024 static const struct snd_pcm_hardware idma_hardware = {
0025 .info = SNDRV_PCM_INFO_INTERLEAVED |
0026 SNDRV_PCM_INFO_BLOCK_TRANSFER |
0027 SNDRV_PCM_INFO_MMAP |
0028 SNDRV_PCM_INFO_MMAP_VALID |
0029 SNDRV_PCM_INFO_PAUSE |
0030 SNDRV_PCM_INFO_RESUME,
0031 .buffer_bytes_max = MAX_IDMA_BUFFER,
0032 .period_bytes_min = 128,
0033 .period_bytes_max = MAX_IDMA_PERIOD,
0034 .periods_min = 1,
0035 .periods_max = 2,
0036 };
0037
0038 struct idma_ctrl {
0039 spinlock_t lock;
0040 int state;
0041 dma_addr_t start;
0042 dma_addr_t pos;
0043 dma_addr_t end;
0044 dma_addr_t period;
0045 dma_addr_t periodsz;
0046 void *token;
0047 void (*cb)(void *dt, int bytes_xfer);
0048 };
0049
0050 static struct idma_info {
0051 spinlock_t lock;
0052 void __iomem *regs;
0053 dma_addr_t lp_tx_addr;
0054 } idma;
0055
0056 static int idma_irq;
0057
0058 static void idma_getpos(dma_addr_t *src)
0059 {
0060 *src = idma.lp_tx_addr +
0061 (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
0062 }
0063
0064 static int idma_enqueue(struct snd_pcm_substream *substream)
0065 {
0066 struct snd_pcm_runtime *runtime = substream->runtime;
0067 struct idma_ctrl *prtd = substream->runtime->private_data;
0068 u32 val;
0069
0070 spin_lock(&prtd->lock);
0071 prtd->token = (void *) substream;
0072 spin_unlock(&prtd->lock);
0073
0074
0075 val = idma.lp_tx_addr + prtd->periodsz;
0076 writel(val, idma.regs + I2SLVL0ADDR);
0077
0078
0079 val = idma.lp_tx_addr;
0080 writel(val, idma.regs + I2SSTR0);
0081
0082
0083
0084
0085
0086 val = readl(idma.regs + I2SSIZE);
0087 val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT);
0088 val |= (((runtime->dma_bytes >> 2) &
0089 I2SSIZE_TRNMSK) << I2SSIZE_SHIFT);
0090 writel(val, idma.regs + I2SSIZE);
0091
0092 val = readl(idma.regs + I2SAHB);
0093 val |= AHB_INTENLVL0;
0094 writel(val, idma.regs + I2SAHB);
0095
0096 return 0;
0097 }
0098
0099 static void idma_setcallbk(struct snd_pcm_substream *substream,
0100 void (*cb)(void *, int))
0101 {
0102 struct idma_ctrl *prtd = substream->runtime->private_data;
0103
0104 spin_lock(&prtd->lock);
0105 prtd->cb = cb;
0106 spin_unlock(&prtd->lock);
0107 }
0108
0109 static void idma_control(int op)
0110 {
0111 u32 val = readl(idma.regs + I2SAHB);
0112
0113 spin_lock(&idma.lock);
0114
0115 switch (op) {
0116 case LPAM_DMA_START:
0117 val |= (AHB_INTENLVL0 | AHB_DMAEN);
0118 break;
0119 case LPAM_DMA_STOP:
0120 val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
0121 break;
0122 default:
0123 spin_unlock(&idma.lock);
0124 return;
0125 }
0126
0127 writel(val, idma.regs + I2SAHB);
0128 spin_unlock(&idma.lock);
0129 }
0130
0131 static void idma_done(void *id, int bytes_xfer)
0132 {
0133 struct snd_pcm_substream *substream = id;
0134 struct idma_ctrl *prtd = substream->runtime->private_data;
0135
0136 if (prtd && (prtd->state & ST_RUNNING))
0137 snd_pcm_period_elapsed(substream);
0138 }
0139
0140 static int idma_hw_params(struct snd_soc_component *component,
0141 struct snd_pcm_substream *substream,
0142 struct snd_pcm_hw_params *params)
0143 {
0144 struct snd_pcm_runtime *runtime = substream->runtime;
0145 struct idma_ctrl *prtd = substream->runtime->private_data;
0146 u32 mod = readl(idma.regs + I2SMOD);
0147 u32 ahb = readl(idma.regs + I2SAHB);
0148
0149 ahb |= (AHB_DMARLD | AHB_INTMASK);
0150 mod |= MOD_TXS_IDMA;
0151 writel(ahb, idma.regs + I2SAHB);
0152 writel(mod, idma.regs + I2SMOD);
0153
0154 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
0155 runtime->dma_bytes = params_buffer_bytes(params);
0156
0157 prtd->start = prtd->pos = runtime->dma_addr;
0158 prtd->period = params_periods(params);
0159 prtd->periodsz = params_period_bytes(params);
0160 prtd->end = runtime->dma_addr + runtime->dma_bytes;
0161
0162 idma_setcallbk(substream, idma_done);
0163
0164 return 0;
0165 }
0166
0167 static int idma_hw_free(struct snd_soc_component *component,
0168 struct snd_pcm_substream *substream)
0169 {
0170 snd_pcm_set_runtime_buffer(substream, NULL);
0171
0172 return 0;
0173 }
0174
0175 static int idma_prepare(struct snd_soc_component *component,
0176 struct snd_pcm_substream *substream)
0177 {
0178 struct idma_ctrl *prtd = substream->runtime->private_data;
0179
0180 prtd->pos = prtd->start;
0181
0182
0183 idma_control(LPAM_DMA_STOP);
0184 idma_enqueue(substream);
0185
0186 return 0;
0187 }
0188
0189 static int idma_trigger(struct snd_soc_component *component,
0190 struct snd_pcm_substream *substream, int cmd)
0191 {
0192 struct idma_ctrl *prtd = substream->runtime->private_data;
0193 int ret = 0;
0194
0195 spin_lock(&prtd->lock);
0196
0197 switch (cmd) {
0198 case SNDRV_PCM_TRIGGER_RESUME:
0199 case SNDRV_PCM_TRIGGER_START:
0200 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0201 prtd->state |= ST_RUNNING;
0202 idma_control(LPAM_DMA_START);
0203 break;
0204
0205 case SNDRV_PCM_TRIGGER_SUSPEND:
0206 case SNDRV_PCM_TRIGGER_STOP:
0207 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0208 prtd->state &= ~ST_RUNNING;
0209 idma_control(LPAM_DMA_STOP);
0210 break;
0211
0212 default:
0213 ret = -EINVAL;
0214 break;
0215 }
0216
0217 spin_unlock(&prtd->lock);
0218
0219 return ret;
0220 }
0221
0222 static snd_pcm_uframes_t
0223 idma_pointer(struct snd_soc_component *component,
0224 struct snd_pcm_substream *substream)
0225 {
0226 struct snd_pcm_runtime *runtime = substream->runtime;
0227 struct idma_ctrl *prtd = runtime->private_data;
0228 dma_addr_t src;
0229 unsigned long res;
0230
0231 spin_lock(&prtd->lock);
0232
0233 idma_getpos(&src);
0234 res = src - prtd->start;
0235
0236 spin_unlock(&prtd->lock);
0237
0238 return bytes_to_frames(substream->runtime, res);
0239 }
0240
0241 static int idma_mmap(struct snd_soc_component *component,
0242 struct snd_pcm_substream *substream,
0243 struct vm_area_struct *vma)
0244 {
0245 struct snd_pcm_runtime *runtime = substream->runtime;
0246 unsigned long size, offset;
0247
0248
0249 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
0250 size = vma->vm_end - vma->vm_start;
0251 offset = vma->vm_pgoff << PAGE_SHIFT;
0252 return io_remap_pfn_range(vma, vma->vm_start,
0253 (runtime->dma_addr + offset) >> PAGE_SHIFT,
0254 size, vma->vm_page_prot);
0255 }
0256
0257 static irqreturn_t iis_irq(int irqno, void *dev_id)
0258 {
0259 struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
0260 u32 iisahb, val, addr;
0261
0262 iisahb = readl(idma.regs + I2SAHB);
0263
0264 val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;
0265
0266 if (val) {
0267 iisahb |= val;
0268 writel(iisahb, idma.regs + I2SAHB);
0269
0270 addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr;
0271 addr += prtd->periodsz;
0272 addr %= (u32)(prtd->end - prtd->start);
0273 addr += idma.lp_tx_addr;
0274
0275 writel(addr, idma.regs + I2SLVL0ADDR);
0276
0277 if (prtd->cb)
0278 prtd->cb(prtd->token, prtd->period);
0279 }
0280
0281 return IRQ_HANDLED;
0282 }
0283
0284 static int idma_open(struct snd_soc_component *component,
0285 struct snd_pcm_substream *substream)
0286 {
0287 struct snd_pcm_runtime *runtime = substream->runtime;
0288 struct idma_ctrl *prtd;
0289 int ret;
0290
0291 snd_soc_set_runtime_hwparams(substream, &idma_hardware);
0292
0293 prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL);
0294 if (prtd == NULL)
0295 return -ENOMEM;
0296
0297 ret = request_irq(idma_irq, iis_irq, 0, "i2s", prtd);
0298 if (ret < 0) {
0299 pr_err("fail to claim i2s irq , ret = %d\n", ret);
0300 kfree(prtd);
0301 return ret;
0302 }
0303
0304 spin_lock_init(&prtd->lock);
0305
0306 runtime->private_data = prtd;
0307
0308 return 0;
0309 }
0310
0311 static int idma_close(struct snd_soc_component *component,
0312 struct snd_pcm_substream *substream)
0313 {
0314 struct snd_pcm_runtime *runtime = substream->runtime;
0315 struct idma_ctrl *prtd = runtime->private_data;
0316
0317 free_irq(idma_irq, prtd);
0318
0319 if (!prtd)
0320 pr_err("idma_close called with prtd == NULL\n");
0321
0322 kfree(prtd);
0323
0324 return 0;
0325 }
0326
0327 static void idma_free(struct snd_soc_component *component,
0328 struct snd_pcm *pcm)
0329 {
0330 struct snd_pcm_substream *substream;
0331 struct snd_dma_buffer *buf;
0332
0333 substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
0334 if (!substream)
0335 return;
0336
0337 buf = &substream->dma_buffer;
0338 if (!buf->area)
0339 return;
0340
0341 iounmap((void __iomem *)buf->area);
0342
0343 buf->area = NULL;
0344 buf->addr = 0;
0345 }
0346
0347 static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
0348 {
0349 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
0350 struct snd_dma_buffer *buf = &substream->dma_buffer;
0351
0352 buf->dev.dev = pcm->card->dev;
0353 buf->private_data = NULL;
0354
0355
0356 buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
0357 buf->addr = idma.lp_tx_addr;
0358 buf->bytes = idma_hardware.buffer_bytes_max;
0359 buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes);
0360 if (!buf->area)
0361 return -ENOMEM;
0362
0363 return 0;
0364 }
0365
0366 static int idma_new(struct snd_soc_component *component,
0367 struct snd_soc_pcm_runtime *rtd)
0368 {
0369 struct snd_card *card = rtd->card->snd_card;
0370 struct snd_pcm *pcm = rtd->pcm;
0371 int ret;
0372
0373 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
0374 if (ret)
0375 return ret;
0376
0377 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
0378 ret = preallocate_idma_buffer(pcm,
0379 SNDRV_PCM_STREAM_PLAYBACK);
0380 }
0381
0382 return ret;
0383 }
0384
0385 void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
0386 {
0387 spin_lock_init(&idma.lock);
0388 idma.regs = regs;
0389 idma.lp_tx_addr = addr;
0390 }
0391 EXPORT_SYMBOL_GPL(idma_reg_addr_init);
0392
0393 static const struct snd_soc_component_driver asoc_idma_platform = {
0394 .open = idma_open,
0395 .close = idma_close,
0396 .trigger = idma_trigger,
0397 .pointer = idma_pointer,
0398 .mmap = idma_mmap,
0399 .hw_params = idma_hw_params,
0400 .hw_free = idma_hw_free,
0401 .prepare = idma_prepare,
0402 .pcm_construct = idma_new,
0403 .pcm_destruct = idma_free,
0404 };
0405
0406 static int asoc_idma_platform_probe(struct platform_device *pdev)
0407 {
0408 idma_irq = platform_get_irq(pdev, 0);
0409 if (idma_irq < 0)
0410 return idma_irq;
0411
0412 return devm_snd_soc_register_component(&pdev->dev, &asoc_idma_platform,
0413 NULL, 0);
0414 }
0415
0416 static struct platform_driver asoc_idma_driver = {
0417 .driver = {
0418 .name = "samsung-idma",
0419 },
0420
0421 .probe = asoc_idma_platform_probe,
0422 };
0423
0424 module_platform_driver(asoc_idma_driver);
0425
0426 MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
0427 MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
0428 MODULE_LICENSE("GPL");