16 #include <linux/module.h>
29 #define S3C_PCM_CTL 0x00
30 #define S3C_PCM_CLKCTL 0x04
31 #define S3C_PCM_TXFIFO 0x08
32 #define S3C_PCM_RXFIFO 0x0C
33 #define S3C_PCM_IRQCTL 0x10
34 #define S3C_PCM_IRQSTAT 0x14
35 #define S3C_PCM_FIFOSTAT 0x18
36 #define S3C_PCM_CLRINT 0x20
39 #define S3C_PCM_CTL_TXDIPSTICK_MASK 0x3f
40 #define S3C_PCM_CTL_TXDIPSTICK_SHIFT 13
41 #define S3C_PCM_CTL_RXDIPSTICK_MASK 0x3f
42 #define S3C_PCM_CTL_RXDIPSTICK_SHIFT 7
43 #define S3C_PCM_CTL_TXDMA_EN (0x1 << 6)
44 #define S3C_PCM_CTL_RXDMA_EN (0x1 << 5)
45 #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1 << 4)
46 #define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1 << 3)
47 #define S3C_PCM_CTL_TXFIFO_EN (0x1 << 2)
48 #define S3C_PCM_CTL_RXFIFO_EN (0x1 << 1)
49 #define S3C_PCM_CTL_ENABLE (0x1 << 0)
52 #define S3C_PCM_CLKCTL_SERCLK_EN (0x1 << 19)
53 #define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1 << 18)
54 #define S3C_PCM_CLKCTL_SCLKDIV_MASK 0x1ff
55 #define S3C_PCM_CLKCTL_SYNCDIV_MASK 0x1ff
56 #define S3C_PCM_CLKCTL_SCLKDIV_SHIFT 9
57 #define S3C_PCM_CLKCTL_SYNCDIV_SHIFT 0
60 #define S3C_PCM_TXFIFO_DVALID (0x1 << 16)
61 #define S3C_PCM_TXFIFO_DATA_MSK (0xffff << 0)
64 #define S3C_PCM_RXFIFO_DVALID (0x1 << 16)
65 #define S3C_PCM_RXFIFO_DATA_MSK (0xffff << 0)
68 #define S3C_PCM_IRQCTL_IRQEN (0x1 << 14)
69 #define S3C_PCM_IRQCTL_WRDEN (0x1 << 12)
70 #define S3C_PCM_IRQCTL_TXEMPTYEN (0x1 << 11)
71 #define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1 << 10)
72 #define S3C_PCM_IRQCTL_TXFULLEN (0x1 << 9)
73 #define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1 << 8)
74 #define S3C_PCM_IRQCTL_TXSTARVEN (0x1 << 7)
75 #define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1 << 6)
76 #define S3C_PCM_IRQCTL_RXEMPTEN (0x1 << 5)
77 #define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1 << 4)
78 #define S3C_PCM_IRQCTL_RXFULLEN (0x1 << 3)
79 #define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1 << 2)
80 #define S3C_PCM_IRQCTL_RXSTARVEN (0x1 << 1)
81 #define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1 << 0)
84 #define S3C_PCM_IRQSTAT_IRQPND (0x1 << 13)
85 #define S3C_PCM_IRQSTAT_WRD_XFER (0x1 << 12)
86 #define S3C_PCM_IRQSTAT_TXEMPTY (0x1 << 11)
87 #define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1 << 10)
88 #define S3C_PCM_IRQSTAT_TXFULL (0x1 << 9)
89 #define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1 << 8)
90 #define S3C_PCM_IRQSTAT_TXSTARV (0x1 << 7)
91 #define S3C_PCM_IRQSTAT_TXERROVRFL (0x1 << 6)
92 #define S3C_PCM_IRQSTAT_RXEMPT (0x1 << 5)
93 #define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1 << 4)
94 #define S3C_PCM_IRQSTAT_RXFULL (0x1 << 3)
95 #define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1 << 2)
96 #define S3C_PCM_IRQSTAT_RXSTARV (0x1 << 1)
97 #define S3C_PCM_IRQSTAT_RXERROVRFL (0x1 << 0)
100 #define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f << 14)
101 #define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1 << 13)
102 #define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1 << 12)
103 #define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1 << 11)
104 #define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1 << 10)
105 #define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f << 4)
106 #define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1 << 3)
107 #define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1 << 2)
108 #define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1 << 1)
109 #define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1 << 0)
136 .name =
"PCM Stereo out"
140 .name =
"PCM Stereo in"
145 .client = &s3c_pcm_dma_client_out,
149 .client = &s3c_pcm_dma_client_out,
156 .client = &s3c_pcm_dma_client_in,
160 .client = &s3c_pcm_dma_client_in,
167 static void s3c_pcm_snd_txctrl(
struct s3c_pcm_info *pcm,
int on)
198 static void s3c_pcm_snd_rxctrl(
struct s3c_pcm_info *pcm,
int on)
245 s3c_pcm_snd_rxctrl(pcm, 1);
247 s3c_pcm_snd_txctrl(pcm, 1);
249 spin_unlock_irqrestore(&pcm->
lock, flags);
258 s3c_pcm_snd_rxctrl(pcm, 0);
260 s3c_pcm_snd_txctrl(pcm, 0);
262 spin_unlock_irqrestore(&pcm->
lock, flags);
281 int sclk_div, sync_div;
292 snd_soc_dai_set_dma_data(rtd->
cpu_dai, substream, dma_data);
330 spin_unlock_irqrestore(&pcm->
lock, flags);
332 dev_dbg(pcm->
dev,
"PCMSOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d\n",
339 static int s3c_pcm_set_fmt(
struct snd_soc_dai *cpu_dai,
342 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
359 dev_err(pcm->
dev,
"Unsupported clock inversion!\n");
369 dev_err(pcm->
dev,
"Unsupported master/slave format!\n");
382 dev_err(pcm->
dev,
"Invalid Clock gating request!\n");
397 dev_err(pcm->
dev,
"Unsupported data format!\n");
405 spin_unlock_irqrestore(&pcm->
lock, flags);
410 static int s3c_pcm_set_clkdiv(
struct snd_soc_dai *cpu_dai,
413 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
427 static int s3c_pcm_set_sysclk(
struct snd_soc_dai *cpu_dai,
428 int clk_id,
unsigned int freq,
int dir)
430 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
440 clkctl &= ~S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
457 .set_sysclk = s3c_pcm_set_sysclk,
458 .set_clkdiv = s3c_pcm_set_clkdiv,
459 .trigger = s3c_pcm_trigger,
460 .hw_params = s3c_pcm_hw_params,
461 .set_fmt = s3c_pcm_set_fmt,
464 #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
466 #define S3C_PCM_DAI_DECLARE \
467 .symmetric_rates = 1, \
468 .ops = &s3c_pcm_dai_ops, \
472 .rates = S3C_PCM_RATES, \
473 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
478 .rates = S3C_PCM_RATES, \
479 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
484 .name =
"samsung-pcm.0",
488 .name =
"samsung-pcm.1",
496 struct resource *mem_res, *dmatx_res, *dmarx_res;
506 pcm_pdata = pdev->
dev.platform_data;
511 dev_err(&pdev->
dev,
"Unable to get PCM-TX dma resource\n");
517 dev_err(&pdev->
dev,
"Unable to get PCM-RX dma resource\n");
523 dev_err(&pdev->
dev,
"Unable to get register resource\n");
528 dev_err(&pdev->
dev,
"Unable to configure gpio\n");
532 pcm = &s3c_pcm[pdev->
id];
541 if (IS_ERR(pcm->
cclk)) {
542 dev_err(&pdev->
dev,
"failed to get audio-bus\n");
543 ret = PTR_ERR(pcm->
cclk);
552 resource_size(mem_res),
"samsung-pcm")) {
553 dev_err(&pdev->
dev,
"Unable to request register region\n");
560 dev_err(&pdev->
dev,
"cannot ioremap registers\n");
566 if (IS_ERR(pcm->
pclk)) {
567 dev_err(&pdev->
dev,
"failed to get pcm_clock\n");
588 dev_err(&pdev->
dev,
"failed to get register DAI: %d\n", ret);
615 pm_runtime_disable(&pdev->
dev);
631 .probe = s3c_pcm_dev_probe,
634 .name =
"samsung-pcm",