blob: 9fbc759fdefe1ded82ec160bced3227e6898cacf [file] [log] [blame]
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001/*
2 * ALSA SoC McASP Audio Layer for TI DAVINCI processor
3 *
4 * Multi-channel Audio Serial Port Driver
5 *
6 * Author: Nirmal Pandey <n-pandey@ti.com>,
7 * Suresh Rajashekara <suresh.r@ti.com>
8 * Steve Chen <schen@.mvista.com>
9 *
10 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
11 * Copyright: (C) 2009 Texas Instruments, India
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090021#include <linux/slab.h>
Chaithrika U Sb67f4482009-06-05 06:28:40 -040022#include <linux/delay.h>
23#include <linux/io.h>
Peter Ujfalusiae726e92013-11-14 11:35:35 +020024#include <linux/clk.h>
Hebbar, Gururaja10884342012-08-08 20:40:32 +053025#include <linux/pm_runtime.h>
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +053026#include <linux/of.h>
27#include <linux/of_platform.h>
28#include <linux/of_device.h>
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +020029#include <linux/platform_data/davinci_asp.h>
Jyri Sarhaa75a0532015-03-20 13:31:08 +020030#include <linux/math64.h>
Peter Ujfalusica3d9432018-11-16 15:41:39 +020031#include <linux/bitmap.h>
Peter Ujfalusi540f1ba72019-01-03 16:05:52 +020032#include <linux/gpio/driver.h>
Chaithrika U Sb67f4482009-06-05 06:28:40 -040033
Daniel Mack64792852014-03-27 11:27:40 +010034#include <sound/asoundef.h>
Chaithrika U Sb67f4482009-06-05 06:28:40 -040035#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/initval.h>
39#include <sound/soc.h>
Peter Ujfalusi453c4992013-11-14 11:35:34 +020040#include <sound/dmaengine_pcm.h>
Chaithrika U Sb67f4482009-06-05 06:28:40 -040041
Peter Ujfalusif3f9cfa2014-07-16 15:12:04 +030042#include "edma-pcm.h"
Peter Ujfalusif2055e12018-12-17 14:21:34 +020043#include "sdma-pcm.h"
Chaithrika U Sb67f4482009-06-05 06:28:40 -040044#include "davinci-mcasp.h"
45
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +030046#define MCASP_MAX_AFIFO_DEPTH 64
47
Arnd Bergmann8ca51042019-03-07 11:11:30 +010048#ifdef CONFIG_PM
Peter Ujfalusi1cc0c052014-10-01 16:02:11 +030049static u32 context_regs[] = {
50 DAVINCI_MCASP_TXFMCTL_REG,
51 DAVINCI_MCASP_RXFMCTL_REG,
52 DAVINCI_MCASP_TXFMT_REG,
53 DAVINCI_MCASP_RXFMT_REG,
54 DAVINCI_MCASP_ACLKXCTL_REG,
55 DAVINCI_MCASP_ACLKRCTL_REG,
Peter Ujfalusif114ce62014-10-01 16:02:12 +030056 DAVINCI_MCASP_AHCLKXCTL_REG,
57 DAVINCI_MCASP_AHCLKRCTL_REG,
Peter Ujfalusi1cc0c052014-10-01 16:02:11 +030058 DAVINCI_MCASP_PDIR_REG,
Peter Ujfalusi540f1ba72019-01-03 16:05:52 +020059 DAVINCI_MCASP_PFUNC_REG,
Peter Ujfalusif114ce62014-10-01 16:02:12 +030060 DAVINCI_MCASP_RXMASK_REG,
61 DAVINCI_MCASP_TXMASK_REG,
62 DAVINCI_MCASP_RXTDM_REG,
63 DAVINCI_MCASP_TXTDM_REG,
Peter Ujfalusi1cc0c052014-10-01 16:02:11 +030064};
65
Peter Ujfalusi790bb942014-02-03 14:51:52 +020066struct davinci_mcasp_context {
Peter Ujfalusi1cc0c052014-10-01 16:02:11 +030067 u32 config_regs[ARRAY_SIZE(context_regs)];
Peter Ujfalusif114ce62014-10-01 16:02:12 +030068 u32 afifo_regs[2]; /* for read/write fifo control registers */
69 u32 *xrsr_regs; /* for serializer configuration */
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +020070 bool pm_state;
Peter Ujfalusi790bb942014-02-03 14:51:52 +020071};
Arnd Bergmann8ca51042019-03-07 11:11:30 +010072#endif
Peter Ujfalusi790bb942014-02-03 14:51:52 +020073
Jyri Sarhaa75a0532015-03-20 13:31:08 +020074struct davinci_mcasp_ruledata {
75 struct davinci_mcasp *mcasp;
76 int serializers;
77};
78
Peter Ujfalusi70091a32013-11-14 11:35:29 +020079struct davinci_mcasp {
Peter Ujfalusi453c4992013-11-14 11:35:34 +020080 struct snd_dmaengine_dai_dma_data dma_data[2];
Peter Ujfalusi21400a72013-11-14 11:35:26 +020081 void __iomem *base;
Peter Ujfalusi487dce82013-11-14 11:35:31 +020082 u32 fifo_base;
Peter Ujfalusi21400a72013-11-14 11:35:26 +020083 struct device *dev;
Misael Lopez Cruza7a33242014-11-12 16:38:05 +020084 struct snd_pcm_substream *substreams[2];
Peter Ujfalusi4a11ff22016-03-11 13:18:51 +020085 unsigned int dai_fmt;
Peter Ujfalusi21400a72013-11-14 11:35:26 +020086
87 /* McASP specific data */
88 int tdm_slots;
Jyri Sarhadd55ff82015-09-09 21:27:44 +030089 u32 tdm_mask[2];
90 int slot_width;
Peter Ujfalusi21400a72013-11-14 11:35:26 +020091 u8 op_mode;
Peter Ujfalusibc184542018-11-16 15:41:41 +020092 u8 dismod;
Peter Ujfalusi21400a72013-11-14 11:35:26 +020093 u8 num_serializer;
94 u8 *serial_dir;
95 u8 version;
Daniel Mack82675252014-07-16 14:04:41 +020096 u8 bclk_div;
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +020097 int streams;
Misael Lopez Cruza7a33242014-11-12 16:38:05 +020098 u32 irq_request[2];
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +020099 int dma_request[2];
Peter Ujfalusi21400a72013-11-14 11:35:26 +0200100
Jyri Sarhaab8b14b2014-01-27 17:37:52 +0200101 int sysclk_freq;
102 bool bclk_master;
103
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200104 unsigned long pdir; /* Pin direction bitfield */
105
Peter Ujfalusi21400a72013-11-14 11:35:26 +0200106 /* McASP FIFO related */
107 u8 txnumevt;
108 u8 rxnumevt;
109
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +0200110 bool dat_port;
111
Peter Ujfalusi11277832014-11-10 12:32:16 +0200112 /* Used for comstraint setting on the second stream */
113 u32 channels;
114
Peter Ujfalusi540f1ba72019-01-03 16:05:52 +0200115#ifdef CONFIG_GPIOLIB
116 struct gpio_chip gpio_chip;
117#endif
118
Peter Ujfalusi61754712019-01-03 16:05:50 +0200119#ifdef CONFIG_PM
Peter Ujfalusi790bb942014-02-03 14:51:52 +0200120 struct davinci_mcasp_context context;
Peter Ujfalusi21400a72013-11-14 11:35:26 +0200121#endif
Jyri Sarhaa75a0532015-03-20 13:31:08 +0200122
123 struct davinci_mcasp_ruledata ruledata[2];
Jyri Sarha5935a052015-04-23 16:16:05 +0300124 struct snd_pcm_hw_constraint_list chconstr[2];
Peter Ujfalusi21400a72013-11-14 11:35:26 +0200125};
126
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200127static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset,
128 u32 val)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400129{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200130 void __iomem *reg = mcasp->base + offset;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400131 __raw_writel(__raw_readl(reg) | val, reg);
132}
133
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200134static inline void mcasp_clr_bits(struct davinci_mcasp *mcasp, u32 offset,
135 u32 val)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400136{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200137 void __iomem *reg = mcasp->base + offset;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400138 __raw_writel((__raw_readl(reg) & ~(val)), reg);
139}
140
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200141static inline void mcasp_mod_bits(struct davinci_mcasp *mcasp, u32 offset,
142 u32 val, u32 mask)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400143{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200144 void __iomem *reg = mcasp->base + offset;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400145 __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
146}
147
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200148static inline void mcasp_set_reg(struct davinci_mcasp *mcasp, u32 offset,
149 u32 val)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400150{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200151 __raw_writel(val, mcasp->base + offset);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400152}
153
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200154static inline u32 mcasp_get_reg(struct davinci_mcasp *mcasp, u32 offset)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400155{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200156 return (u32)__raw_readl(mcasp->base + offset);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400157}
158
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200159static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400160{
161 int i = 0;
162
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200163 mcasp_set_bits(mcasp, ctl_reg, val);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400164
165 /* programming GBLCTL needs to read back from GBLCTL and verfiy */
166 /* loop count is to avoid the lock-up */
167 for (i = 0; i < 1000; i++) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200168 if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400169 break;
170 }
171
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200172 if (i == 1000 && ((mcasp_get_reg(mcasp, ctl_reg) & val) != val))
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400173 printk(KERN_ERR "GBLCTL write error\n");
174}
175
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200176static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
177{
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200178 u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
179 u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200180
181 return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
182}
183
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200184static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable)
185{
186 u32 bit = PIN_BIT_AMUTE;
187
188 for_each_set_bit_from(bit, &mcasp->pdir, PIN_BIT_AFSR + 1) {
189 if (enable)
190 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
191 else
192 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
193 }
194}
195
196static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
197{
198 u32 bit;
199
200 for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
201 if (enable)
202 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
203 else
204 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
205 }
206}
207
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200208static void mcasp_start_rx(struct davinci_mcasp *mcasp)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400209{
Peter Ujfalusibb372af2014-10-29 13:55:47 +0200210 if (mcasp->rxnumevt) { /* enable FIFO */
211 u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
212
213 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
214 mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
215 }
216
Peter Ujfalusi44982732014-10-29 13:55:45 +0200217 /* Start clocks */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200218 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
219 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200220 /*
221 * When ASYNC == 0 the transmit and receive sections operate
222 * synchronously from the transmit clock and frame sync. We need to make
223 * sure that the TX signlas are enabled when starting reception.
224 */
225 if (mcasp_is_synchronous(mcasp)) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200226 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
227 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200228 }
229
Peter Ujfalusi44982732014-10-29 13:55:45 +0200230 /* Activate serializer(s) */
Peter Ujfalusi1003c272018-11-16 15:41:38 +0200231 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200232 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
Peter Ujfalusi44982732014-10-29 13:55:45 +0200233 /* Release RX state machine */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200234 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
Peter Ujfalusi44982732014-10-29 13:55:45 +0200235 /* Release Frame Sync generator */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200236 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200237 if (mcasp_is_synchronous(mcasp))
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200238 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200239
240 /* enable receive IRQs */
241 mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
242 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400243}
244
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200245static void mcasp_start_tx(struct davinci_mcasp *mcasp)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400246{
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400247 u32 cnt;
248
Peter Ujfalusibb372af2014-10-29 13:55:47 +0200249 if (mcasp->txnumevt) { /* enable FIFO */
250 u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
251
252 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
253 mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
254 }
255
Peter Ujfalusi36bcecd2014-10-29 13:55:44 +0200256 /* Start clocks */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200257 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
258 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200259 mcasp_set_clk_pdir(mcasp, true);
260
Peter Ujfalusi36bcecd2014-10-29 13:55:44 +0200261 /* Activate serializer(s) */
Peter Ujfalusi1003c272018-11-16 15:41:38 +0200262 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200263 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400264
Peter Ujfalusi36bcecd2014-10-29 13:55:44 +0200265 /* wait for XDATA to be cleared */
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400266 cnt = 0;
Peter Ujfalusie2a0c9f2015-12-11 13:06:24 +0200267 while ((mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & XRDATA) &&
268 (cnt < 100000))
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400269 cnt++;
270
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200271 mcasp_set_axr_pdir(mcasp, true);
272
Peter Ujfalusi36bcecd2014-10-29 13:55:44 +0200273 /* Release TX state machine */
274 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
275 /* Release Frame Sync generator */
276 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200277
278 /* enable transmit IRQs */
279 mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
280 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400281}
282
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200283static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400284{
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200285 mcasp->streams++;
286
Peter Ujfalusibb372af2014-10-29 13:55:47 +0200287 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200288 mcasp_start_tx(mcasp);
Peter Ujfalusibb372af2014-10-29 13:55:47 +0200289 else
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200290 mcasp_start_rx(mcasp);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400291}
292
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200293static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400294{
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200295 /* disable IRQ sources */
296 mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
297 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
298
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200299 /*
300 * In synchronous mode stop the TX clocks if no other stream is
301 * running
302 */
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200303 if (mcasp_is_synchronous(mcasp) && !mcasp->streams) {
304 mcasp_set_clk_pdir(mcasp, false);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200305 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200306 }
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200307
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200308 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
309 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
Peter Ujfalusi03808662014-10-29 13:55:46 +0200310
311 if (mcasp->rxnumevt) { /* disable FIFO */
312 u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
313
314 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
315 }
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400316}
317
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200318static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400319{
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200320 u32 val = 0;
321
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200322 /* disable IRQ sources */
323 mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
324 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
325
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200326 /*
327 * In synchronous mode keep TX clocks running if the capture stream is
328 * still running.
329 */
330 if (mcasp_is_synchronous(mcasp) && mcasp->streams)
331 val = TXHCLKRST | TXCLKRST | TXFSRST;
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200332 else
333 mcasp_set_clk_pdir(mcasp, false);
334
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200335
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200336 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
337 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
Peter Ujfalusi03808662014-10-29 13:55:46 +0200338
339 if (mcasp->txnumevt) { /* disable FIFO */
340 u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
341
342 mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
343 }
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200344
345 mcasp_set_axr_pdir(mcasp, false);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400346}
347
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200348static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400349{
Peter Ujfalusi4dcb5a02013-11-14 11:35:33 +0200350 mcasp->streams--;
351
Peter Ujfalusi03808662014-10-29 13:55:46 +0200352 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200353 mcasp_stop_tx(mcasp);
Peter Ujfalusi03808662014-10-29 13:55:46 +0200354 else
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200355 mcasp_stop_rx(mcasp);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400356}
357
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200358static irqreturn_t davinci_mcasp_tx_irq_handler(int irq, void *data)
359{
360 struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
361 struct snd_pcm_substream *substream;
362 u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK];
363 u32 handled_mask = 0;
364 u32 stat;
365
366 stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG);
367 if (stat & XUNDRN & irq_mask) {
368 dev_warn(mcasp->dev, "Transmit buffer underflow\n");
369 handled_mask |= XUNDRN;
370
371 substream = mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK];
Takashi Iwaidae35d12018-07-04 16:01:43 +0200372 if (substream)
373 snd_pcm_stop_xrun(substream);
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200374 }
375
376 if (!handled_mask)
377 dev_warn(mcasp->dev, "unhandled tx event. txstat: 0x%08x\n",
378 stat);
379
380 if (stat & XRERR)
381 handled_mask |= XRERR;
382
383 /* Ack the handled event only */
384 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, handled_mask);
385
386 return IRQ_RETVAL(handled_mask);
387}
388
389static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data)
390{
391 struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
392 struct snd_pcm_substream *substream;
393 u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE];
394 u32 handled_mask = 0;
395 u32 stat;
396
397 stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG);
398 if (stat & ROVRN & irq_mask) {
399 dev_warn(mcasp->dev, "Receive buffer overflow\n");
400 handled_mask |= ROVRN;
401
402 substream = mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE];
Takashi Iwaidae35d12018-07-04 16:01:43 +0200403 if (substream)
404 snd_pcm_stop_xrun(substream);
Misael Lopez Cruza7a33242014-11-12 16:38:05 +0200405 }
406
407 if (!handled_mask)
408 dev_warn(mcasp->dev, "unhandled rx event. rxstat: 0x%08x\n",
409 stat);
410
411 if (stat & XRERR)
412 handled_mask |= XRERR;
413
414 /* Ack the handled event only */
415 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, handled_mask);
416
417 return IRQ_RETVAL(handled_mask);
418}
419
Peter Ujfalusi5a1b8a82014-12-30 16:10:32 +0200420static irqreturn_t davinci_mcasp_common_irq_handler(int irq, void *data)
421{
422 struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
423 irqreturn_t ret = IRQ_NONE;
424
425 if (mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK])
426 ret = davinci_mcasp_tx_irq_handler(irq, data);
427
428 if (mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE])
429 ret |= davinci_mcasp_rx_irq_handler(irq, data);
430
431 return ret;
432}
433
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400434static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
435 unsigned int fmt)
436{
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200437 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200438 int ret = 0;
Peter Ujfalusi6dfa9a42014-04-04 14:31:42 +0300439 u32 data_delay;
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300440 bool fs_pol_rising;
Peter Ujfalusiffd950f2014-04-04 14:31:45 +0300441 bool inv_fs = false;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400442
Peter Ujfalusi4a11ff22016-03-11 13:18:51 +0200443 if (!fmt)
444 return 0;
445
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200446 pm_runtime_get_sync(mcasp->dev);
Daniel Mack5296cf22012-10-04 15:08:42 +0200447 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
Peter Ujfalusi188edc52014-04-04 14:31:43 +0300448 case SND_SOC_DAIFMT_DSP_A:
449 mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
450 mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
Peter Ujfalusi188edc52014-04-04 14:31:43 +0300451 /* 1st data bit occur one ACLK cycle after the frame sync */
452 data_delay = 1;
453 break;
Daniel Mack5296cf22012-10-04 15:08:42 +0200454 case SND_SOC_DAIFMT_DSP_B:
455 case SND_SOC_DAIFMT_AC97:
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200456 mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
457 mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
Peter Ujfalusi6dfa9a42014-04-04 14:31:42 +0300458 /* No delay after FS */
459 data_delay = 0;
Daniel Mack5296cf22012-10-04 15:08:42 +0200460 break;
Peter Ujfalusiffd950f2014-04-04 14:31:45 +0300461 case SND_SOC_DAIFMT_I2S:
Daniel Mack5296cf22012-10-04 15:08:42 +0200462 /* configure a full-word SYNC pulse (LRCLK) */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200463 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
464 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
Peter Ujfalusi6dfa9a42014-04-04 14:31:42 +0300465 /* 1st data bit occur one ACLK cycle after the frame sync */
466 data_delay = 1;
Peter Ujfalusiffd950f2014-04-04 14:31:45 +0300467 /* FS need to be inverted */
468 inv_fs = true;
Daniel Mack5296cf22012-10-04 15:08:42 +0200469 break;
Peter Ujfalusi423761e2014-04-04 14:31:46 +0300470 case SND_SOC_DAIFMT_LEFT_J:
471 /* configure a full-word SYNC pulse (LRCLK) */
472 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
473 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
474 /* No delay after FS */
475 data_delay = 0;
476 break;
Peter Ujfalusiffd950f2014-04-04 14:31:45 +0300477 default:
478 ret = -EINVAL;
479 goto out;
Daniel Mack5296cf22012-10-04 15:08:42 +0200480 }
481
Peter Ujfalusi6dfa9a42014-04-04 14:31:42 +0300482 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay),
483 FSXDLY(3));
484 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay),
485 FSRDLY(3));
486
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400487 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
488 case SND_SOC_DAIFMT_CBS_CFS:
489 /* codec is clock and frame slave */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200490 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
491 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400492
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200493 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
494 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400495
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200496 /* BCLK */
497 set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
498 set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
499 /* Frame Sync */
500 set_bit(PIN_BIT_AFSX, &mcasp->pdir);
501 set_bit(PIN_BIT_AFSR, &mcasp->pdir);
502
Jyri Sarhaab8b14b2014-01-27 17:37:52 +0200503 mcasp->bclk_master = 1;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400504 break;
Peter Ujfalusi226e2f12015-02-12 16:41:26 +0200505 case SND_SOC_DAIFMT_CBS_CFM:
506 /* codec is clock slave and frame master */
507 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
508 mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
509
510 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
511 mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
512
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200513 /* BCLK */
514 set_bit(PIN_BIT_ACLKX, &mcasp->pdir);
515 set_bit(PIN_BIT_ACLKR, &mcasp->pdir);
516 /* Frame Sync */
517 clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
518 clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
519
Peter Ujfalusi226e2f12015-02-12 16:41:26 +0200520 mcasp->bclk_master = 1;
521 break;
Chaithrika U S517ee6c2009-08-11 16:59:12 -0400522 case SND_SOC_DAIFMT_CBM_CFS:
523 /* codec is clock master and frame slave */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200524 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
525 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
Chaithrika U S517ee6c2009-08-11 16:59:12 -0400526
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200527 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
528 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
Chaithrika U S517ee6c2009-08-11 16:59:12 -0400529
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200530 /* BCLK */
531 clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
532 clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
533 /* Frame Sync */
534 set_bit(PIN_BIT_AFSX, &mcasp->pdir);
535 set_bit(PIN_BIT_AFSR, &mcasp->pdir);
536
Jyri Sarhaab8b14b2014-01-27 17:37:52 +0200537 mcasp->bclk_master = 0;
Chaithrika U S517ee6c2009-08-11 16:59:12 -0400538 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400539 case SND_SOC_DAIFMT_CBM_CFM:
540 /* codec is clock and frame master */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200541 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
542 mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400543
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200544 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
545 mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400546
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200547 /* BCLK */
548 clear_bit(PIN_BIT_ACLKX, &mcasp->pdir);
549 clear_bit(PIN_BIT_ACLKR, &mcasp->pdir);
550 /* Frame Sync */
551 clear_bit(PIN_BIT_AFSX, &mcasp->pdir);
552 clear_bit(PIN_BIT_AFSR, &mcasp->pdir);
553
Jyri Sarhaab8b14b2014-01-27 17:37:52 +0200554 mcasp->bclk_master = 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400555 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400556 default:
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200557 ret = -EINVAL;
558 goto out;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400559 }
560
561 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
562 case SND_SOC_DAIFMT_IB_NF:
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200563 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
Peter Ujfalusi74ddd8c2014-04-04 14:31:41 +0300564 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300565 fs_pol_rising = true;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400566 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400567 case SND_SOC_DAIFMT_NB_IF:
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200568 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
Peter Ujfalusi74ddd8c2014-04-04 14:31:41 +0300569 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300570 fs_pol_rising = false;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400571 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400572 case SND_SOC_DAIFMT_IB_IF:
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200573 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
Peter Ujfalusi74ddd8c2014-04-04 14:31:41 +0300574 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300575 fs_pol_rising = false;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400576 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400577 case SND_SOC_DAIFMT_NB_NF:
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200578 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200579 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300580 fs_pol_rising = true;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400581 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400582 default:
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200583 ret = -EINVAL;
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300584 goto out;
585 }
586
Peter Ujfalusiffd950f2014-04-04 14:31:45 +0300587 if (inv_fs)
588 fs_pol_rising = !fs_pol_rising;
589
Peter Ujfalusi83f12502014-04-04 14:31:44 +0300590 if (fs_pol_rising) {
591 mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
592 mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
593 } else {
594 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
595 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400596 }
Peter Ujfalusi4a11ff22016-03-11 13:18:51 +0200597
598 mcasp->dai_fmt = fmt;
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200599out:
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +0200600 pm_runtime_put(mcasp->dev);
Peter Ujfalusi1d17a042014-01-30 15:21:30 +0200601 return ret;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400602}
603
Peter Ujfalusi226e73e2016-05-09 13:42:30 +0300604static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id,
Jyri Sarha88135432014-08-06 16:47:16 +0300605 int div, bool explicit)
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200606{
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +0200607 pm_runtime_get_sync(mcasp->dev);
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200608 switch (div_id) {
Peter Ujfalusi20d4b102016-05-09 13:42:29 +0300609 case MCASP_CLKDIV_AUXCLK: /* MCLK divider */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200610 mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200611 AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200612 mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200613 AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
614 break;
615
Peter Ujfalusi20d4b102016-05-09 13:42:29 +0300616 case MCASP_CLKDIV_BCLK: /* BCLK divider */
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200617 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200618 ACLKXDIV(div - 1), ACLKXDIV_MASK);
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200619 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200620 ACLKRDIV(div - 1), ACLKRDIV_MASK);
Jyri Sarha88135432014-08-06 16:47:16 +0300621 if (explicit)
622 mcasp->bclk_div = div;
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200623 break;
624
Peter Ujfalusi20d4b102016-05-09 13:42:29 +0300625 case MCASP_CLKDIV_BCLK_FS_RATIO:
626 /*
Jyri Sarha14a998b2015-09-17 10:39:05 +0300627 * BCLK/LRCLK ratio descries how many bit-clock cycles
628 * fit into one frame. The clock ratio is given for a
629 * full period of data (for I2S format both left and
630 * right channels), so it has to be divided by number
631 * of tdm-slots (for I2S - divided by 2).
632 * Instead of storing this ratio, we calculate a new
633 * tdm_slot width by dividing the the ratio by the
634 * number of configured tdm slots.
635 */
636 mcasp->slot_width = div / mcasp->tdm_slots;
637 if (div % mcasp->tdm_slots)
638 dev_warn(mcasp->dev,
639 "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots",
640 __func__, div, mcasp->tdm_slots);
Daniel Mack1b3bc062012-12-05 18:20:38 +0100641 break;
642
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200643 default:
644 return -EINVAL;
645 }
646
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +0200647 pm_runtime_put(mcasp->dev);
Daniel Mack4ed8c9b2012-10-04 15:08:39 +0200648 return 0;
649}
650
Jyri Sarha88135432014-08-06 16:47:16 +0300651static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
652 int div)
653{
Peter Ujfalusi226e73e2016-05-09 13:42:30 +0300654 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
655
656 return __davinci_mcasp_set_clkdiv(mcasp, div_id, div, 1);
Jyri Sarha88135432014-08-06 16:47:16 +0300657}
658
Daniel Mack5b66aa22012-10-04 15:08:41 +0200659static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
660 unsigned int freq, int dir)
661{
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200662 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
Daniel Mack5b66aa22012-10-04 15:08:41 +0200663
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +0200664 pm_runtime_get_sync(mcasp->dev);
Daniel Mack5b66aa22012-10-04 15:08:41 +0200665 if (dir == SND_SOC_CLOCK_OUT) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200666 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
667 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200668 set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
Daniel Mack5b66aa22012-10-04 15:08:41 +0200669 } else {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200670 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
671 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200672 clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
Daniel Mack5b66aa22012-10-04 15:08:41 +0200673 }
674
Jyri Sarhaab8b14b2014-01-27 17:37:52 +0200675 mcasp->sysclk_freq = freq;
676
Peter Ujfalusi6afda7f2015-03-05 16:55:21 +0200677 pm_runtime_put(mcasp->dev);
Daniel Mack5b66aa22012-10-04 15:08:41 +0200678 return 0;
679}
680
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300681/* All serializers must have equal number of channels */
682static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, int stream,
683 int serializers)
684{
685 struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream];
686 unsigned int *list = (unsigned int *) cl->list;
687 int slots = mcasp->tdm_slots;
688 int i, count = 0;
689
690 if (mcasp->tdm_mask[stream])
691 slots = hweight32(mcasp->tdm_mask[stream]);
692
Peter Ujfalusie4798d22017-05-11 09:58:22 +0300693 for (i = 1; i <= slots; i++)
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300694 list[count++] = i;
695
696 for (i = 2; i <= serializers; i++)
697 list[count++] = i*slots;
698
699 cl->count = count;
700
701 return 0;
702}
703
704static int davinci_mcasp_set_ch_constraints(struct davinci_mcasp *mcasp)
705{
706 int rx_serializers = 0, tx_serializers = 0, ret, i;
707
708 for (i = 0; i < mcasp->num_serializer; i++)
709 if (mcasp->serial_dir[i] == TX_MODE)
710 tx_serializers++;
711 else if (mcasp->serial_dir[i] == RX_MODE)
712 rx_serializers++;
713
714 ret = davinci_mcasp_ch_constraint(mcasp, SNDRV_PCM_STREAM_PLAYBACK,
715 tx_serializers);
716 if (ret)
717 return ret;
718
719 ret = davinci_mcasp_ch_constraint(mcasp, SNDRV_PCM_STREAM_CAPTURE,
720 rx_serializers);
721
722 return ret;
723}
724
725
726static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai,
727 unsigned int tx_mask,
728 unsigned int rx_mask,
729 int slots, int slot_width)
730{
731 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
732
733 dev_dbg(mcasp->dev,
734 "%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n",
735 __func__, tx_mask, rx_mask, slots, slot_width);
736
737 if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
738 dev_err(mcasp->dev,
739 "Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n",
740 tx_mask, rx_mask, slots);
741 return -EINVAL;
742 }
743
744 if (slot_width &&
745 (slot_width < 8 || slot_width > 32 || slot_width % 4 != 0)) {
746 dev_err(mcasp->dev, "%s: Unsupported slot_width %d\n",
747 __func__, slot_width);
748 return -EINVAL;
749 }
750
751 mcasp->tdm_slots = slots;
Andreas Dannenberg1bdd5932015-11-09 12:19:19 -0600752 mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
753 mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300754 mcasp->slot_width = slot_width;
755
756 return davinci_mcasp_set_ch_constraints(mcasp);
757}
758
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200759static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
Jyri Sarha14a998b2015-09-17 10:39:05 +0300760 int sample_width)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400761{
Daniel Mackba764b32012-12-05 18:20:37 +0100762 u32 fmt;
Jyri Sarha14a998b2015-09-17 10:39:05 +0300763 u32 tx_rotate = (sample_width / 4) & 0x7;
764 u32 mask = (1ULL << sample_width) - 1;
765 u32 slot_width = sample_width;
766
Peter Ujfalusife0a29e2014-09-04 10:52:53 +0300767 /*
768 * For captured data we should not rotate, inversion and masking is
769 * enoguh to get the data to the right position:
770 * Format data from bus after reverse (XRBUF)
771 * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB|
772 * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
773 * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
774 * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB|
775 */
776 u32 rx_rotate = 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400777
Daniel Mack1b3bc062012-12-05 18:20:38 +0100778 /*
Jyri Sarha14a998b2015-09-17 10:39:05 +0300779 * Setting the tdm slot width either with set_clkdiv() or
780 * set_tdm_slot() allows us to for example send 32 bits per
781 * channel to the codec, while only 16 of them carry audio
782 * payload.
Daniel Mack1b3bc062012-12-05 18:20:38 +0100783 */
Jyri Sarha14a998b2015-09-17 10:39:05 +0300784 if (mcasp->slot_width) {
Peter Ujfalusid742b922014-11-10 12:32:19 +0200785 /*
Jyri Sarha14a998b2015-09-17 10:39:05 +0300786 * When we have more bclk then it is needed for the
787 * data, we need to use the rotation to move the
788 * received samples to have correct alignment.
Peter Ujfalusid742b922014-11-10 12:32:19 +0200789 */
Jyri Sarha14a998b2015-09-17 10:39:05 +0300790 slot_width = mcasp->slot_width;
791 rx_rotate = (slot_width - sample_width) / 4;
Peter Ujfalusid742b922014-11-10 12:32:19 +0200792 }
Daniel Mack1b3bc062012-12-05 18:20:38 +0100793
Daniel Mackba764b32012-12-05 18:20:37 +0100794 /* mapping of the XSSZ bit-field as described in the datasheet */
Jyri Sarha14a998b2015-09-17 10:39:05 +0300795 fmt = (slot_width >> 1) - 1;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400796
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200797 if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200798 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
799 RXSSZ(0x0F));
800 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
801 TXSSZ(0x0F));
802 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
803 TXROT(7));
804 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
805 RXROT(7));
806 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
Yegor Yefremovf5023af2013-04-04 16:13:20 +0200807 }
808
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200809 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
Chaithrika U S0c31cf32009-09-15 18:13:29 -0400810
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400811 return 0;
812}
813
Peter Ujfalusi662ffae2014-01-30 15:15:22 +0200814static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
Peter Ujfalusidd093a02014-04-01 15:55:11 +0300815 int period_words, int channels)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400816{
Peter Ujfalusi5f04c602014-04-01 15:55:10 +0300817 struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream];
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400818 int i;
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400819 u8 tx_ser = 0;
820 u8 rx_ser = 0;
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200821 u8 slots = mcasp->tdm_slots;
Michal Bachraty2952b272013-02-28 16:07:08 +0100822 u8 max_active_serializers = (channels + slots - 1) / slots;
Peter Ujfalusi72383192015-09-14 16:06:48 +0300823 int active_serializers, numevt;
Peter Ujfalusi487dce82013-11-14 11:35:31 +0200824 u32 reg;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400825 /* Default configuration */
Peter Ujfalusi40448e52014-04-04 15:56:30 +0300826 if (mcasp->version < MCASP_VERSION_3)
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200827 mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400828
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400829 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200830 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
831 mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400832 } else {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200833 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
834 mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS);
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400835 }
836
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200837 for (i = 0; i < mcasp->num_serializer; i++) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200838 mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
839 mcasp->serial_dir[i]);
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200840 if (mcasp->serial_dir[i] == TX_MODE &&
Michal Bachraty2952b272013-02-28 16:07:08 +0100841 tx_ser < max_active_serializers) {
Misael Lopez Cruz19db62e2015-06-08 16:03:47 +0300842 mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
Peter Ujfalusibc184542018-11-16 15:41:41 +0200843 mcasp->dismod, DISMOD_MASK);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200844 set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400845 tx_ser++;
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200846 } else if (mcasp->serial_dir[i] == RX_MODE &&
Michal Bachraty2952b272013-02-28 16:07:08 +0100847 rx_ser < max_active_serializers) {
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200848 clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400849 rx_ser++;
Vishal Thanki096a8f82018-05-11 14:33:37 +0200850 } else if (mcasp->serial_dir[i] == INACTIVE_MODE) {
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200851 mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
852 SRMOD_INACTIVE, SRMOD_MASK);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200853 clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
854 } else if (mcasp->serial_dir[i] == TX_MODE) {
855 /* Unused TX pins, clear PDIR */
Peter Ujfalusibc184542018-11-16 15:41:41 +0200856 mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
857 mcasp->dismod, DISMOD_MASK);
Peter Ujfalusica3d9432018-11-16 15:41:39 +0200858 clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400859 }
860 }
861
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300862 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
863 active_serializers = tx_ser;
864 numevt = mcasp->txnumevt;
865 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
866 } else {
867 active_serializers = rx_ser;
868 numevt = mcasp->rxnumevt;
869 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
870 }
Daniel Mackecf327c2013-03-08 14:19:38 +0100871
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300872 if (active_serializers < max_active_serializers) {
Peter Ujfalusi70091a32013-11-14 11:35:29 +0200873 dev_warn(mcasp->dev, "stream has more channels (%d) than are "
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300874 "enabled in mcasp (%d)\n", channels,
875 active_serializers * slots);
Daniel Mackecf327c2013-03-08 14:19:38 +0100876 return -EINVAL;
877 }
878
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300879 /* AFIFO is not in use */
Peter Ujfalusi5f04c602014-04-01 15:55:10 +0300880 if (!numevt) {
881 /* Configure the burst size for platform drivers */
Peter Ujfalusi33445642014-04-01 15:55:12 +0300882 if (active_serializers > 1) {
883 /*
884 * If more than one serializers are in use we have one
885 * DMA request to provide data for all serializers.
886 * For example if three serializers are enabled the DMA
887 * need to transfer three words per DMA request.
888 */
Peter Ujfalusi33445642014-04-01 15:55:12 +0300889 dma_data->maxburst = active_serializers;
890 } else {
Peter Ujfalusi33445642014-04-01 15:55:12 +0300891 dma_data->maxburst = 0;
892 }
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300893 return 0;
Peter Ujfalusi5f04c602014-04-01 15:55:10 +0300894 }
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400895
Peter Ujfalusidd093a02014-04-01 15:55:11 +0300896 if (period_words % active_serializers) {
897 dev_err(mcasp->dev, "Invalid combination of period words and "
898 "active serializers: %d, %d\n", period_words,
899 active_serializers);
900 return -EINVAL;
901 }
902
903 /*
904 * Calculate the optimal AFIFO depth for platform side:
905 * The number of words for numevt need to be in steps of active
906 * serializers.
907 */
Peter Ujfalusi72383192015-09-14 16:06:48 +0300908 numevt = (numevt / active_serializers) * active_serializers;
909
Peter Ujfalusidd093a02014-04-01 15:55:11 +0300910 while (period_words % numevt && numevt > 0)
911 numevt -= active_serializers;
912 if (numevt <= 0)
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300913 numevt = active_serializers;
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400914
Peter Ujfalusi0bf0e8a2014-04-01 15:55:09 +0300915 mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK);
916 mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK);
Michal Bachraty2952b272013-02-28 16:07:08 +0100917
Peter Ujfalusi5f04c602014-04-01 15:55:10 +0300918 /* Configure the burst size for platform drivers */
Peter Ujfalusi33445642014-04-01 15:55:12 +0300919 if (numevt == 1)
920 numevt = 0;
Peter Ujfalusi5f04c602014-04-01 15:55:10 +0300921 dma_data->maxburst = numevt;
922
Michal Bachraty2952b272013-02-28 16:07:08 +0100923 return 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400924}
925
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +0200926static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
927 int channels)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400928{
929 int i, active_slots;
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +0200930 int total_slots;
931 int active_serializers;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400932 u32 mask = 0;
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +0200933 u32 busel = 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400934
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +0200935 total_slots = mcasp->tdm_slots;
936
937 /*
938 * If more than one serializer is needed, then use them with
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300939 * all the specified tdm_slots. Otherwise, one serializer can
940 * cope with the transaction using just as many slots as there
941 * are channels in the stream.
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +0200942 */
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300943 if (mcasp->tdm_mask[stream]) {
944 active_slots = hweight32(mcasp->tdm_mask[stream]);
945 active_serializers = (channels + active_slots - 1) /
946 active_slots;
947 if (active_serializers == 1) {
948 active_slots = channels;
949 for (i = 0; i < total_slots; i++) {
950 if ((1 << i) & mcasp->tdm_mask[stream]) {
951 mask |= (1 << i);
952 if (--active_slots <= 0)
953 break;
954 }
955 }
956 }
957 } else {
958 active_serializers = (channels + total_slots - 1) / total_slots;
959 if (active_serializers == 1)
960 active_slots = channels;
961 else
962 active_slots = total_slots;
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +0200963
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300964 for (i = 0; i < active_slots; i++)
965 mask |= (1 << i);
966 }
Peter Ujfalusif68205a2013-11-14 11:35:36 +0200967 mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
Chaithrika U S6a99fb52009-08-11 16:58:52 -0400968
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +0200969 if (!mcasp->dat_port)
970 busel = TXSEL;
971
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300972 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
973 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
974 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
975 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
976 FSXMOD(total_slots), FSXMOD(0x1FF));
977 } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
978 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
979 mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
980 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
981 FSRMOD(total_slots), FSRMOD(0x1FF));
Peter Ujfalusi0ad7d3a2015-11-23 12:51:53 +0200982 /*
983 * If McASP is set to be TX/RX synchronous and the playback is
984 * not running already we need to configure the TX slots in
985 * order to have correct FSX on the bus
986 */
987 if (mcasp_is_synchronous(mcasp) && !mcasp->channels)
988 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
989 FSXMOD(total_slots), FSXMOD(0x1FF));
Jyri Sarhadd55ff82015-09-09 21:27:44 +0300990 }
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400991
Peter Ujfalusi2c56c4c2014-01-30 15:15:23 +0200992 return 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400993}
994
995/* S/PDIF */
Daniel Mack64792852014-03-27 11:27:40 +0100996static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
997 unsigned int rate)
Chaithrika U Sb67f4482009-06-05 06:28:40 -0400998{
Daniel Mack64792852014-03-27 11:27:40 +0100999 u32 cs_value = 0;
1000 u8 *cs_bytes = (u8*) &cs_value;
1001
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001002 /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
1003 and LSB first */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001004 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001005
1006 /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001007 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001008
1009 /* Set the TX tdm : for all the slots */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001010 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001011
1012 /* Set the TX clock controls : div = 1 and internal */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001013 mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001014
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001015 mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001016
1017 /* Only 44100 and 48000 are valid, both have the same setting */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001018 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001019
1020 /* Enable the DIT */
Peter Ujfalusif68205a2013-11-14 11:35:36 +02001021 mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
Peter Ujfalusi2c56c4c2014-01-30 15:15:23 +02001022
Daniel Mack64792852014-03-27 11:27:40 +01001023 /* Set S/PDIF channel status bits */
1024 cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
1025 cs_bytes[1] = IEC958_AES1_CON_PCM_CODER;
1026
1027 switch (rate) {
1028 case 22050:
1029 cs_bytes[3] |= IEC958_AES3_CON_FS_22050;
1030 break;
1031 case 24000:
1032 cs_bytes[3] |= IEC958_AES3_CON_FS_24000;
1033 break;
1034 case 32000:
1035 cs_bytes[3] |= IEC958_AES3_CON_FS_32000;
1036 break;
1037 case 44100:
1038 cs_bytes[3] |= IEC958_AES3_CON_FS_44100;
1039 break;
1040 case 48000:
1041 cs_bytes[3] |= IEC958_AES3_CON_FS_48000;
1042 break;
1043 case 88200:
1044 cs_bytes[3] |= IEC958_AES3_CON_FS_88200;
1045 break;
1046 case 96000:
1047 cs_bytes[3] |= IEC958_AES3_CON_FS_96000;
1048 break;
1049 case 176400:
1050 cs_bytes[3] |= IEC958_AES3_CON_FS_176400;
1051 break;
1052 case 192000:
1053 cs_bytes[3] |= IEC958_AES3_CON_FS_192000;
1054 break;
1055 default:
1056 printk(KERN_WARNING "unsupported sampling rate: %d\n", rate);
1057 return -EINVAL;
1058 }
1059
1060 mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value);
1061 mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value);
1062
Peter Ujfalusi2c56c4c2014-01-30 15:15:23 +02001063 return 0;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001064}
1065
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001066static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001067 unsigned int bclk_freq, bool set)
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001068{
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001069 int error_ppm;
Peter Ujfalusiddecd142016-05-09 13:42:32 +03001070 unsigned int sysclk_freq = mcasp->sysclk_freq;
1071 u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG);
1072 int div = sysclk_freq / bclk_freq;
1073 int rem = sysclk_freq % bclk_freq;
1074 int aux_div = 1;
1075
1076 if (div > (ACLKXDIV_MASK + 1)) {
1077 if (reg & AHCLKXE) {
1078 aux_div = div / (ACLKXDIV_MASK + 1);
1079 if (div % (ACLKXDIV_MASK + 1))
1080 aux_div++;
1081
1082 sysclk_freq /= aux_div;
1083 div = sysclk_freq / bclk_freq;
1084 rem = sysclk_freq % bclk_freq;
1085 } else if (set) {
1086 dev_warn(mcasp->dev, "Too fast reference clock (%u)\n",
1087 sysclk_freq);
1088 }
1089 }
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001090
1091 if (rem != 0) {
1092 if (div == 0 ||
Peter Ujfalusiddecd142016-05-09 13:42:32 +03001093 ((sysclk_freq / div) - bclk_freq) >
1094 (bclk_freq - (sysclk_freq / (div+1)))) {
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001095 div++;
1096 rem = rem - bclk_freq;
1097 }
1098 }
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001099 error_ppm = (div*1000000 + (int)div64_long(1000000LL*rem,
1100 (int)bclk_freq)) / div - 1000000;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001101
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001102 if (set) {
1103 if (error_ppm)
1104 dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n",
1105 error_ppm);
1106
1107 __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0);
Peter Ujfalusiddecd142016-05-09 13:42:32 +03001108 if (reg & AHCLKXE)
1109 __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK,
1110 aux_div, 0);
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001111 }
1112
1113 return error_ppm;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001114}
1115
Peter Ujfalusi5fcb4572018-08-31 11:24:56 +03001116static inline u32 davinci_mcasp_tx_delay(struct davinci_mcasp *mcasp)
1117{
1118 if (!mcasp->txnumevt)
1119 return 0;
1120
1121 return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_WFIFOSTS_OFFSET);
1122}
1123
1124static inline u32 davinci_mcasp_rx_delay(struct davinci_mcasp *mcasp)
1125{
1126 if (!mcasp->rxnumevt)
1127 return 0;
1128
1129 return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_RFIFOSTS_OFFSET);
1130}
1131
1132static snd_pcm_sframes_t davinci_mcasp_delay(
1133 struct snd_pcm_substream *substream,
1134 struct snd_soc_dai *cpu_dai)
1135{
1136 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
1137 u32 fifo_use;
1138
1139 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1140 fifo_use = davinci_mcasp_tx_delay(mcasp);
1141 else
1142 fifo_use = davinci_mcasp_rx_delay(mcasp);
1143
1144 /*
1145 * Divide the used locations with the channel count to get the
1146 * FIFO usage in samples (don't care about partial samples in the
1147 * buffer).
1148 */
1149 return fifo_use / substream->runtime->channels;
1150}
1151
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001152static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
1153 struct snd_pcm_hw_params *params,
1154 struct snd_soc_dai *cpu_dai)
1155{
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001156 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001157 int word_length;
Peter Ujfalusia7e46bd2014-02-03 14:51:50 +02001158 int channels = params_channels(params);
Peter Ujfalusidd093a02014-04-01 15:55:11 +03001159 int period_size = params_period_size(params);
Peter Ujfalusi2c56c4c2014-01-30 15:15:23 +02001160 int ret;
Jyri Sarhaab8b14b2014-01-27 17:37:52 +02001161
Peter Ujfalusi4a11ff22016-03-11 13:18:51 +02001162 ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt);
1163 if (ret)
1164 return ret;
1165
Daniel Mack82675252014-07-16 14:04:41 +02001166 /*
1167 * If mcasp is BCLK master, and a BCLK divider was not provided by
1168 * the machine driver, we need to calculate the ratio.
1169 */
1170 if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
Jyri Sarha1f114f72015-04-23 16:16:04 +03001171 int slots = mcasp->tdm_slots;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001172 int rate = params_rate(params);
1173 int sbits = params_width(params);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001174
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001175 if (mcasp->slot_width)
1176 sbits = mcasp->slot_width;
1177
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001178 davinci_mcasp_calc_clk_div(mcasp, rate * sbits * slots, true);
Jyri Sarhaab8b14b2014-01-27 17:37:52 +02001179 }
1180
Peter Ujfalusidd093a02014-04-01 15:55:11 +03001181 ret = mcasp_common_hw_param(mcasp, substream->stream,
1182 period_size * channels, channels);
Peter Ujfalusi0f7d9a62014-01-30 15:15:24 +02001183 if (ret)
1184 return ret;
1185
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001186 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
Daniel Mack64792852014-03-27 11:27:40 +01001187 ret = mcasp_dit_hw_param(mcasp, params_rate(params));
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001188 else
Misael Lopez Cruz18a4f552014-11-10 12:32:17 +02001189 ret = mcasp_i2s_hw_param(mcasp, substream->stream,
1190 channels);
Peter Ujfalusi2c56c4c2014-01-30 15:15:23 +02001191
1192 if (ret)
1193 return ret;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001194
1195 switch (params_format(params)) {
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001196 case SNDRV_PCM_FORMAT_U8:
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001197 case SNDRV_PCM_FORMAT_S8:
Daniel Mackba764b32012-12-05 18:20:37 +01001198 word_length = 8;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001199 break;
1200
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001201 case SNDRV_PCM_FORMAT_U16_LE:
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001202 case SNDRV_PCM_FORMAT_S16_LE:
Daniel Mackba764b32012-12-05 18:20:37 +01001203 word_length = 16;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001204 break;
1205
Daniel Mack21eb24d2012-10-09 09:35:16 +02001206 case SNDRV_PCM_FORMAT_U24_3LE:
1207 case SNDRV_PCM_FORMAT_S24_3LE:
Daniel Mackba764b32012-12-05 18:20:37 +01001208 word_length = 24;
Daniel Mack21eb24d2012-10-09 09:35:16 +02001209 break;
1210
Daniel Mack6b7fa012012-10-09 11:56:40 +02001211 case SNDRV_PCM_FORMAT_U24_LE:
1212 case SNDRV_PCM_FORMAT_S24_LE:
Peter Ujfalusi182bef82014-06-26 08:09:24 +03001213 word_length = 24;
1214 break;
1215
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001216 case SNDRV_PCM_FORMAT_U32_LE:
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001217 case SNDRV_PCM_FORMAT_S32_LE:
Daniel Mackba764b32012-12-05 18:20:37 +01001218 word_length = 32;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001219 break;
1220
1221 default:
1222 printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
1223 return -EINVAL;
1224 }
Chaithrika U S6a99fb52009-08-11 16:58:52 -04001225
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001226 davinci_config_channel_size(mcasp, word_length);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001227
Peter Ujfalusi11277832014-11-10 12:32:16 +02001228 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
1229 mcasp->channels = channels;
1230
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001231 return 0;
1232}
1233
1234static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
1235 int cmd, struct snd_soc_dai *cpu_dai)
1236{
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001237 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001238 int ret = 0;
1239
1240 switch (cmd) {
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001241 case SNDRV_PCM_TRIGGER_RESUME:
Chaithrika U Se473b842010-01-20 17:06:33 +05301242 case SNDRV_PCM_TRIGGER_START:
1243 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001244 davinci_mcasp_start(mcasp, substream->stream);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001245 break;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001246 case SNDRV_PCM_TRIGGER_SUSPEND:
Chaithrika U Sa47979b2009-12-03 18:56:56 +05301247 case SNDRV_PCM_TRIGGER_STOP:
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001248 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001249 davinci_mcasp_stop(mcasp, substream->stream);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001250 break;
1251
1252 default:
1253 ret = -EINVAL;
1254 }
1255
1256 return ret;
1257}
1258
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001259static const unsigned int davinci_mcasp_dai_rates[] = {
1260 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
1261 88200, 96000, 176400, 192000,
1262};
1263
1264#define DAVINCI_MAX_RATE_ERROR_PPM 1000
1265
1266static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
1267 struct snd_pcm_hw_rule *rule)
1268{
1269 struct davinci_mcasp_ruledata *rd = rule->private;
1270 struct snd_interval *ri =
1271 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
1272 int sbits = params_width(params);
Jyri Sarha1f114f72015-04-23 16:16:04 +03001273 int slots = rd->mcasp->tdm_slots;
Jyri Sarha518f6ba2015-04-23 16:16:06 +03001274 struct snd_interval range;
1275 int i;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001276
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001277 if (rd->mcasp->slot_width)
1278 sbits = rd->mcasp->slot_width;
1279
Jyri Sarha518f6ba2015-04-23 16:16:06 +03001280 snd_interval_any(&range);
1281 range.empty = 1;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001282
1283 for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) {
Jyri Sarha518f6ba2015-04-23 16:16:06 +03001284 if (snd_interval_test(ri, davinci_mcasp_dai_rates[i])) {
Jyri Sarha1f114f72015-04-23 16:16:04 +03001285 uint bclk_freq = sbits*slots*
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001286 davinci_mcasp_dai_rates[i];
1287 int ppm;
1288
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001289 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq,
1290 false);
Jyri Sarha518f6ba2015-04-23 16:16:06 +03001291 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
1292 if (range.empty) {
1293 range.min = davinci_mcasp_dai_rates[i];
1294 range.empty = 0;
1295 }
1296 range.max = davinci_mcasp_dai_rates[i];
1297 }
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001298 }
1299 }
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001300
Jyri Sarha518f6ba2015-04-23 16:16:06 +03001301 dev_dbg(rd->mcasp->dev,
1302 "Frequencies %d-%d -> %d-%d for %d sbits and %d tdm slots\n",
1303 ri->min, ri->max, range.min, range.max, sbits, slots);
1304
1305 return snd_interval_refine(hw_param_interval(params, rule->var),
1306 &range);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001307}
1308
1309static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
1310 struct snd_pcm_hw_rule *rule)
1311{
1312 struct davinci_mcasp_ruledata *rd = rule->private;
1313 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1314 struct snd_mask nfmt;
1315 int rate = params_rate(params);
Jyri Sarha1f114f72015-04-23 16:16:04 +03001316 int slots = rd->mcasp->tdm_slots;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001317 int i, count = 0;
1318
1319 snd_mask_none(&nfmt);
1320
Peter Ujfalusi9be072a2016-09-01 10:05:12 +03001321 for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001322 if (snd_mask_test(fmt, i)) {
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001323 uint sbits = snd_pcm_format_width(i);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001324 int ppm;
1325
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001326 if (rd->mcasp->slot_width)
1327 sbits = rd->mcasp->slot_width;
1328
Peter Ujfalusi3e9bee12016-05-09 13:42:31 +03001329 ppm = davinci_mcasp_calc_clk_div(rd->mcasp,
1330 sbits * slots * rate,
1331 false);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001332 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
1333 snd_mask_set(&nfmt, i);
1334 count++;
1335 }
1336 }
1337 }
1338 dev_dbg(rd->mcasp->dev,
Jyri Sarha1f114f72015-04-23 16:16:04 +03001339 "%d possible sample format for %d Hz and %d tdm slots\n",
1340 count, rate, slots);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001341
1342 return snd_mask_refine(fmt, &nfmt);
1343}
1344
Peter Ujfalusid43c17d2018-01-05 12:18:07 +02001345static int davinci_mcasp_hw_rule_min_periodsize(
1346 struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
1347{
1348 struct snd_interval *period_size = hw_param_interval(params,
1349 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
1350 struct snd_interval frames;
1351
1352 snd_interval_any(&frames);
1353 frames.min = 64;
1354 frames.integer = 1;
1355
1356 return snd_interval_refine(period_size, &frames);
1357}
1358
Peter Ujfalusi11277832014-11-10 12:32:16 +02001359static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
1360 struct snd_soc_dai *cpu_dai)
1361{
1362 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
Peter Ujfalusi4cd9db02015-04-07 14:03:53 +03001363 struct davinci_mcasp_ruledata *ruledata =
1364 &mcasp->ruledata[substream->stream];
Peter Ujfalusi11277832014-11-10 12:32:16 +02001365 u32 max_channels = 0;
1366 int i, dir;
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001367 int tdm_slots = mcasp->tdm_slots;
1368
Peter Ujfalusi19357362016-05-09 13:39:14 +03001369 /* Do not allow more then one stream per direction */
1370 if (mcasp->substreams[substream->stream])
1371 return -EBUSY;
Peter Ujfalusi11277832014-11-10 12:32:16 +02001372
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02001373 mcasp->substreams[substream->stream] = substream;
1374
Peter Ujfalusi19357362016-05-09 13:39:14 +03001375 if (mcasp->tdm_mask[substream->stream])
1376 tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]);
1377
Peter Ujfalusi11277832014-11-10 12:32:16 +02001378 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
1379 return 0;
1380
1381 /*
1382 * Limit the maximum allowed channels for the first stream:
1383 * number of serializers for the direction * tdm slots per serializer
1384 */
1385 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1386 dir = TX_MODE;
1387 else
1388 dir = RX_MODE;
1389
1390 for (i = 0; i < mcasp->num_serializer; i++) {
1391 if (mcasp->serial_dir[i] == dir)
1392 max_channels++;
1393 }
Peter Ujfalusi4cd9db02015-04-07 14:03:53 +03001394 ruledata->serializers = max_channels;
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001395 max_channels *= tdm_slots;
Peter Ujfalusi11277832014-11-10 12:32:16 +02001396 /*
1397 * If the already active stream has less channels than the calculated
1398 * limnit based on the seirializers * tdm_slots, we need to use that as
1399 * a constraint for the second stream.
1400 * Otherwise (first stream or less allowed channels) we use the
1401 * calculated constraint.
1402 */
1403 if (mcasp->channels && mcasp->channels < max_channels)
1404 max_channels = mcasp->channels;
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001405 /*
1406 * But we can always allow channels upto the amount of
1407 * the available tdm_slots.
1408 */
1409 if (max_channels < tdm_slots)
1410 max_channels = tdm_slots;
Peter Ujfalusi11277832014-11-10 12:32:16 +02001411
1412 snd_pcm_hw_constraint_minmax(substream->runtime,
1413 SNDRV_PCM_HW_PARAM_CHANNELS,
Peter Ujfalusie4798d22017-05-11 09:58:22 +03001414 0, max_channels);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001415
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001416 snd_pcm_hw_constraint_list(substream->runtime,
1417 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1418 &mcasp->chconstr[substream->stream]);
1419
1420 if (mcasp->slot_width)
1421 snd_pcm_hw_constraint_minmax(substream->runtime,
1422 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1423 8, mcasp->slot_width);
Jyri Sarha5935a052015-04-23 16:16:05 +03001424
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001425 /*
1426 * If we rely on implicit BCLK divider setting we should
1427 * set constraints based on what we can provide.
1428 */
1429 if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
1430 int ret;
1431
Peter Ujfalusi4cd9db02015-04-07 14:03:53 +03001432 ruledata->mcasp = mcasp;
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001433
1434 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
1435 SNDRV_PCM_HW_PARAM_RATE,
1436 davinci_mcasp_hw_rule_rate,
Peter Ujfalusi4cd9db02015-04-07 14:03:53 +03001437 ruledata,
Jyri Sarha1f114f72015-04-23 16:16:04 +03001438 SNDRV_PCM_HW_PARAM_FORMAT, -1);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001439 if (ret)
1440 return ret;
1441 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
1442 SNDRV_PCM_HW_PARAM_FORMAT,
1443 davinci_mcasp_hw_rule_format,
Peter Ujfalusi4cd9db02015-04-07 14:03:53 +03001444 ruledata,
Jyri Sarha1f114f72015-04-23 16:16:04 +03001445 SNDRV_PCM_HW_PARAM_RATE, -1);
Jyri Sarhaa75a0532015-03-20 13:31:08 +02001446 if (ret)
1447 return ret;
1448 }
1449
Peter Ujfalusid43c17d2018-01-05 12:18:07 +02001450 snd_pcm_hw_rule_add(substream->runtime, 0,
1451 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1452 davinci_mcasp_hw_rule_min_periodsize, NULL,
1453 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
1454
Peter Ujfalusi11277832014-11-10 12:32:16 +02001455 return 0;
1456}
1457
1458static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
1459 struct snd_soc_dai *cpu_dai)
1460{
1461 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
1462
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02001463 mcasp->substreams[substream->stream] = NULL;
1464
Peter Ujfalusi11277832014-11-10 12:32:16 +02001465 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
1466 return;
1467
1468 if (!cpu_dai->active)
1469 mcasp->channels = 0;
1470}
1471
Lars-Peter Clausen85e76522011-11-23 11:40:40 +01001472static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
Peter Ujfalusi11277832014-11-10 12:32:16 +02001473 .startup = davinci_mcasp_startup,
1474 .shutdown = davinci_mcasp_shutdown,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001475 .trigger = davinci_mcasp_trigger,
Peter Ujfalusi5fcb4572018-08-31 11:24:56 +03001476 .delay = davinci_mcasp_delay,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001477 .hw_params = davinci_mcasp_hw_params,
1478 .set_fmt = davinci_mcasp_set_dai_fmt,
Daniel Mack4ed8c9b2012-10-04 15:08:39 +02001479 .set_clkdiv = davinci_mcasp_set_clkdiv,
Daniel Mack5b66aa22012-10-04 15:08:41 +02001480 .set_sysclk = davinci_mcasp_set_sysclk,
Jyri Sarhadd55ff82015-09-09 21:27:44 +03001481 .set_tdm_slot = davinci_mcasp_set_tdm_slot,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001482};
1483
Peter Ujfalusid5902f692014-04-01 15:55:07 +03001484static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
1485{
1486 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
1487
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02001488 dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
1489 dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
Peter Ujfalusid5902f692014-04-01 15:55:07 +03001490
1491 return 0;
1492}
1493
Peter Ujfalusied29cd52013-11-14 11:35:22 +02001494#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
1495
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001496#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
1497 SNDRV_PCM_FMTBIT_U8 | \
1498 SNDRV_PCM_FMTBIT_S16_LE | \
1499 SNDRV_PCM_FMTBIT_U16_LE | \
Daniel Mack21eb24d2012-10-09 09:35:16 +02001500 SNDRV_PCM_FMTBIT_S24_LE | \
1501 SNDRV_PCM_FMTBIT_U24_LE | \
1502 SNDRV_PCM_FMTBIT_S24_3LE | \
1503 SNDRV_PCM_FMTBIT_U24_3LE | \
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001504 SNDRV_PCM_FMTBIT_S32_LE | \
1505 SNDRV_PCM_FMTBIT_U32_LE)
1506
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001507static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001508 {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001509 .name = "davinci-mcasp.0",
Peter Ujfalusid5902f692014-04-01 15:55:07 +03001510 .probe = davinci_mcasp_dai_probe,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001511 .playback = {
Peter Ujfalusie4798d22017-05-11 09:58:22 +03001512 .channels_min = 1,
Michal Bachraty2952b272013-02-28 16:07:08 +01001513 .channels_max = 32 * 16,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001514 .rates = DAVINCI_MCASP_RATES,
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001515 .formats = DAVINCI_MCASP_PCM_FMTS,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001516 },
1517 .capture = {
Peter Ujfalusie4798d22017-05-11 09:58:22 +03001518 .channels_min = 1,
Michal Bachraty2952b272013-02-28 16:07:08 +01001519 .channels_max = 32 * 16,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001520 .rates = DAVINCI_MCASP_RATES,
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001521 .formats = DAVINCI_MCASP_PCM_FMTS,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001522 },
1523 .ops = &davinci_mcasp_dai_ops,
1524
Peter Ujfalusid75249f2014-11-10 12:32:18 +02001525 .symmetric_samplebits = 1,
Jyri Sarha295c3402015-09-09 21:27:42 +03001526 .symmetric_rates = 1,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001527 },
1528 {
Peter Ujfalusi58e48d92013-11-14 11:35:24 +02001529 .name = "davinci-mcasp.1",
Peter Ujfalusid5902f692014-04-01 15:55:07 +03001530 .probe = davinci_mcasp_dai_probe,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001531 .playback = {
1532 .channels_min = 1,
1533 .channels_max = 384,
1534 .rates = DAVINCI_MCASP_RATES,
Ben Gardiner0a9d1382011-08-26 12:02:44 -04001535 .formats = DAVINCI_MCASP_PCM_FMTS,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001536 },
1537 .ops = &davinci_mcasp_dai_ops,
1538 },
1539
1540};
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001541
Kuninori Morimotoeeef0ed2013-03-21 03:31:19 -07001542static const struct snd_soc_component_driver davinci_mcasp_component = {
1543 .name = "davinci-mcasp",
1544};
1545
Jyri Sarha256ba182013-10-18 18:37:42 +03001546/* Some HW specific values and defaults. The rest is filled in from DT. */
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001547static struct davinci_mcasp_pdata dm646x_mcasp_pdata = {
Jyri Sarha256ba182013-10-18 18:37:42 +03001548 .tx_dma_offset = 0x400,
1549 .rx_dma_offset = 0x400,
Jyri Sarha256ba182013-10-18 18:37:42 +03001550 .version = MCASP_VERSION_1,
1551};
1552
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001553static struct davinci_mcasp_pdata da830_mcasp_pdata = {
Jyri Sarha256ba182013-10-18 18:37:42 +03001554 .tx_dma_offset = 0x2000,
1555 .rx_dma_offset = 0x2000,
Jyri Sarha256ba182013-10-18 18:37:42 +03001556 .version = MCASP_VERSION_2,
1557};
1558
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001559static struct davinci_mcasp_pdata am33xx_mcasp_pdata = {
Jyri Sarha256ba182013-10-18 18:37:42 +03001560 .tx_dma_offset = 0,
1561 .rx_dma_offset = 0,
Jyri Sarha256ba182013-10-18 18:37:42 +03001562 .version = MCASP_VERSION_3,
1563};
1564
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001565static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
Peter Ujfalusi9ac00132016-06-02 12:55:05 +03001566 /* The CFG port offset will be calculated if it is needed */
1567 .tx_dma_offset = 0,
1568 .rx_dma_offset = 0,
Peter Ujfalusi453c4992013-11-14 11:35:34 +02001569 .version = MCASP_VERSION_4,
1570};
1571
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301572static const struct of_device_id mcasp_dt_ids[] = {
1573 {
1574 .compatible = "ti,dm646x-mcasp-audio",
Jyri Sarha256ba182013-10-18 18:37:42 +03001575 .data = &dm646x_mcasp_pdata,
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301576 },
1577 {
1578 .compatible = "ti,da830-mcasp-audio",
Jyri Sarha256ba182013-10-18 18:37:42 +03001579 .data = &da830_mcasp_pdata,
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301580 },
Hebbar, Gururajae5ec69d2012-09-03 13:40:40 +05301581 {
Jyri Sarha3af9e032013-10-18 18:37:44 +03001582 .compatible = "ti,am33xx-mcasp-audio",
Peter Ujfalusib14899d2013-11-14 11:35:37 +02001583 .data = &am33xx_mcasp_pdata,
Hebbar, Gururajae5ec69d2012-09-03 13:40:40 +05301584 },
Peter Ujfalusi453c4992013-11-14 11:35:34 +02001585 {
1586 .compatible = "ti,dra7-mcasp-audio",
1587 .data = &dra7_mcasp_pdata,
1588 },
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301589 { /* sentinel */ }
1590};
1591MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
1592
Peter Ujfalusiae726e92013-11-14 11:35:35 +02001593static int mcasp_reparent_fck(struct platform_device *pdev)
1594{
1595 struct device_node *node = pdev->dev.of_node;
1596 struct clk *gfclk, *parent_clk;
1597 const char *parent_name;
1598 int ret;
1599
1600 if (!node)
1601 return 0;
1602
1603 parent_name = of_get_property(node, "fck_parent", NULL);
1604 if (!parent_name)
1605 return 0;
1606
Peter Ujfalusic6702542016-01-27 15:02:49 +02001607 dev_warn(&pdev->dev, "Update the bindings to use assigned-clocks!\n");
1608
Peter Ujfalusiae726e92013-11-14 11:35:35 +02001609 gfclk = clk_get(&pdev->dev, "fck");
1610 if (IS_ERR(gfclk)) {
1611 dev_err(&pdev->dev, "failed to get fck\n");
1612 return PTR_ERR(gfclk);
1613 }
1614
1615 parent_clk = clk_get(NULL, parent_name);
1616 if (IS_ERR(parent_clk)) {
1617 dev_err(&pdev->dev, "failed to get parent clock\n");
1618 ret = PTR_ERR(parent_clk);
1619 goto err1;
1620 }
1621
1622 ret = clk_set_parent(gfclk, parent_clk);
1623 if (ret) {
1624 dev_err(&pdev->dev, "failed to reparent fck\n");
1625 goto err2;
1626 }
1627
1628err2:
1629 clk_put(parent_clk);
1630err1:
1631 clk_put(gfclk);
1632 return ret;
1633}
1634
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001635static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301636 struct platform_device *pdev)
1637{
1638 struct device_node *np = pdev->dev.of_node;
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001639 struct davinci_mcasp_pdata *pdata = NULL;
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301640 const struct of_device_id *match =
Sachin Kamatea421eb2013-05-22 16:53:37 +05301641 of_match_device(mcasp_dt_ids, &pdev->dev);
Jyri Sarha4023fe62013-10-18 18:37:43 +03001642 struct of_phandle_args dma_spec;
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301643
1644 const u32 *of_serial_dir32;
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301645 u32 val;
1646 int i, ret = 0;
1647
1648 if (pdev->dev.platform_data) {
1649 pdata = pdev->dev.platform_data;
Peter Ujfalusibc184542018-11-16 15:41:41 +02001650 pdata->dismod = DISMOD_LOW;
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301651 return pdata;
1652 } else if (match) {
Peter Ujfalusi272ee032016-06-02 12:55:24 +03001653 pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
1654 GFP_KERNEL);
1655 if (!pdata) {
Peter Ujfalusi272ee032016-06-02 12:55:24 +03001656 ret = -ENOMEM;
1657 return pdata;
1658 }
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301659 } else {
1660 /* control shouldn't reach here. something is wrong */
1661 ret = -EINVAL;
1662 goto nodata;
1663 }
1664
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301665 ret = of_property_read_u32(np, "op-mode", &val);
1666 if (ret >= 0)
1667 pdata->op_mode = val;
1668
1669 ret = of_property_read_u32(np, "tdm-slots", &val);
Michal Bachraty2952b272013-02-28 16:07:08 +01001670 if (ret >= 0) {
1671 if (val < 2 || val > 32) {
1672 dev_err(&pdev->dev,
1673 "tdm-slots must be in rage [2-32]\n");
1674 ret = -EINVAL;
1675 goto nodata;
1676 }
1677
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301678 pdata->tdm_slots = val;
Michal Bachraty2952b272013-02-28 16:07:08 +01001679 }
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301680
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301681 of_serial_dir32 = of_get_property(np, "serial-dir", &val);
1682 val /= sizeof(u32);
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301683 if (of_serial_dir32) {
Peter Ujfalusi1427e662013-10-18 18:37:46 +03001684 u8 *of_serial_dir = devm_kzalloc(&pdev->dev,
1685 (sizeof(*of_serial_dir) * val),
1686 GFP_KERNEL);
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301687 if (!of_serial_dir) {
1688 ret = -ENOMEM;
1689 goto nodata;
1690 }
1691
Peter Ujfalusi1427e662013-10-18 18:37:46 +03001692 for (i = 0; i < val; i++)
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301693 of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
1694
Peter Ujfalusi1427e662013-10-18 18:37:46 +03001695 pdata->num_serializer = val;
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301696 pdata->serial_dir = of_serial_dir;
1697 }
1698
Jyri Sarha4023fe62013-10-18 18:37:43 +03001699 ret = of_property_match_string(np, "dma-names", "tx");
1700 if (ret < 0)
1701 goto nodata;
1702
1703 ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
1704 &dma_spec);
1705 if (ret < 0)
1706 goto nodata;
1707
1708 pdata->tx_dma_channel = dma_spec.args[0];
1709
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02001710 /* RX is not valid in DIT mode */
1711 if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) {
1712 ret = of_property_match_string(np, "dma-names", "rx");
1713 if (ret < 0)
1714 goto nodata;
Jyri Sarha4023fe62013-10-18 18:37:43 +03001715
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02001716 ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
1717 &dma_spec);
1718 if (ret < 0)
1719 goto nodata;
Jyri Sarha4023fe62013-10-18 18:37:43 +03001720
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02001721 pdata->rx_dma_channel = dma_spec.args[0];
1722 }
Jyri Sarha4023fe62013-10-18 18:37:43 +03001723
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301724 ret = of_property_read_u32(np, "tx-num-evt", &val);
1725 if (ret >= 0)
1726 pdata->txnumevt = val;
1727
1728 ret = of_property_read_u32(np, "rx-num-evt", &val);
1729 if (ret >= 0)
1730 pdata->rxnumevt = val;
1731
1732 ret = of_property_read_u32(np, "sram-size-playback", &val);
1733 if (ret >= 0)
1734 pdata->sram_size_playback = val;
1735
1736 ret = of_property_read_u32(np, "sram-size-capture", &val);
1737 if (ret >= 0)
1738 pdata->sram_size_capture = val;
1739
Peter Ujfalusibc184542018-11-16 15:41:41 +02001740 ret = of_property_read_u32(np, "dismod", &val);
1741 if (ret >= 0) {
1742 if (val == 0 || val == 2 || val == 3) {
1743 pdata->dismod = DISMOD_VAL(val);
1744 } else {
1745 dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val);
1746 pdata->dismod = DISMOD_LOW;
1747 }
1748 } else {
1749 pdata->dismod = DISMOD_LOW;
1750 }
1751
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05301752 return pdata;
1753
1754nodata:
1755 if (ret < 0) {
1756 dev_err(&pdev->dev, "Error populating platform data, err %d\n",
1757 ret);
1758 pdata = NULL;
1759 }
1760 return pdata;
1761}
1762
Jyri Sarha9fbd58c2015-06-02 23:09:34 +03001763enum {
1764 PCM_EDMA,
1765 PCM_SDMA,
1766};
1767static const char *sdma_prefix = "ti,omap";
1768
1769static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp)
1770{
1771 struct dma_chan *chan;
1772 const char *tmp;
1773 int ret = PCM_EDMA;
1774
1775 if (!mcasp->dev->of_node)
1776 return PCM_EDMA;
1777
1778 tmp = mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data;
1779 chan = dma_request_slave_channel_reason(mcasp->dev, tmp);
1780 if (IS_ERR(chan)) {
1781 if (PTR_ERR(chan) != -EPROBE_DEFER)
1782 dev_err(mcasp->dev,
1783 "Can't verify DMA configuration (%ld)\n",
1784 PTR_ERR(chan));
1785 return PTR_ERR(chan);
1786 }
Takashi Iwaibefff4f2017-09-07 10:59:17 +02001787 if (WARN_ON(!chan->device || !chan->device->dev))
1788 return -EINVAL;
Jyri Sarha9fbd58c2015-06-02 23:09:34 +03001789
1790 if (chan->device->dev->of_node)
1791 ret = of_property_read_string(chan->device->dev->of_node,
1792 "compatible", &tmp);
1793 else
1794 dev_dbg(mcasp->dev, "DMA controller has no of-node\n");
1795
1796 dma_release_channel(chan);
1797 if (ret)
1798 return ret;
1799
1800 dev_dbg(mcasp->dev, "DMA controller compatible = \"%s\"\n", tmp);
1801 if (!strncmp(tmp, sdma_prefix, strlen(sdma_prefix)))
1802 return PCM_SDMA;
1803
1804 return PCM_EDMA;
1805}
1806
Peter Ujfalusi9ac00132016-06-02 12:55:05 +03001807static u32 davinci_mcasp_txdma_offset(struct davinci_mcasp_pdata *pdata)
1808{
1809 int i;
1810 u32 offset = 0;
1811
1812 if (pdata->version != MCASP_VERSION_4)
1813 return pdata->tx_dma_offset;
1814
1815 for (i = 0; i < pdata->num_serializer; i++) {
1816 if (pdata->serial_dir[i] == TX_MODE) {
1817 if (!offset) {
1818 offset = DAVINCI_MCASP_TXBUF_REG(i);
1819 } else {
1820 pr_err("%s: Only one serializer allowed!\n",
1821 __func__);
1822 break;
1823 }
1824 }
1825 }
1826
1827 return offset;
1828}
1829
1830static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata)
1831{
1832 int i;
1833 u32 offset = 0;
1834
1835 if (pdata->version != MCASP_VERSION_4)
1836 return pdata->rx_dma_offset;
1837
1838 for (i = 0; i < pdata->num_serializer; i++) {
1839 if (pdata->serial_dir[i] == RX_MODE) {
1840 if (!offset) {
1841 offset = DAVINCI_MCASP_RXBUF_REG(i);
1842 } else {
1843 pr_err("%s: Only one serializer allowed!\n",
1844 __func__);
1845 break;
1846 }
1847 }
1848 }
1849
1850 return offset;
1851}
1852
Peter Ujfalusi540f1ba72019-01-03 16:05:52 +02001853#ifdef CONFIG_GPIOLIB
1854static int davinci_mcasp_gpio_request(struct gpio_chip *chip, unsigned offset)
1855{
1856 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1857
1858 if (mcasp->num_serializer && offset < mcasp->num_serializer &&
1859 mcasp->serial_dir[offset] != INACTIVE_MODE) {
1860 dev_err(mcasp->dev, "AXR%u pin is used for audio\n", offset);
1861 return -EBUSY;
1862 }
1863
1864 /* Do not change the PIN yet */
1865
1866 return pm_runtime_get_sync(mcasp->dev);
1867}
1868
1869static void davinci_mcasp_gpio_free(struct gpio_chip *chip, unsigned offset)
1870{
1871 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1872
1873 /* Set the direction to input */
1874 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset));
1875
1876 /* Set the pin as McASP pin */
1877 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset));
1878
1879 pm_runtime_put_sync(mcasp->dev);
1880}
1881
1882static int davinci_mcasp_gpio_direction_out(struct gpio_chip *chip,
1883 unsigned offset, int value)
1884{
1885 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1886 u32 val;
1887
1888 if (value)
1889 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset));
1890 else
1891 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset));
1892
1893 val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG);
1894 if (!(val & BIT(offset))) {
1895 /* Set the pin as GPIO pin */
1896 mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset));
1897
1898 /* Set the direction to output */
1899 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset));
1900 }
1901
1902 return 0;
1903}
1904
1905static void davinci_mcasp_gpio_set(struct gpio_chip *chip, unsigned offset,
1906 int value)
1907{
1908 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1909
1910 if (value)
1911 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset));
1912 else
1913 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG, BIT(offset));
1914}
1915
1916static int davinci_mcasp_gpio_direction_in(struct gpio_chip *chip,
1917 unsigned offset)
1918{
1919 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1920 u32 val;
1921
1922 val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PFUNC_REG);
1923 if (!(val & BIT(offset))) {
1924 /* Set the direction to input */
1925 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(offset));
1926
1927 /* Set the pin as GPIO pin */
1928 mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG, BIT(offset));
1929 }
1930
1931 return 0;
1932}
1933
1934static int davinci_mcasp_gpio_get(struct gpio_chip *chip, unsigned offset)
1935{
1936 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1937 u32 val;
1938
1939 val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDSET_REG);
1940 if (val & BIT(offset))
1941 return 1;
1942
1943 return 0;
1944}
1945
1946static int davinci_mcasp_gpio_get_direction(struct gpio_chip *chip,
1947 unsigned offset)
1948{
1949 struct davinci_mcasp *mcasp = gpiochip_get_data(chip);
1950 u32 val;
1951
1952 val = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
1953 if (val & BIT(offset))
1954 return 0;
1955
1956 return 1;
1957}
1958
1959static const struct gpio_chip davinci_mcasp_template_chip = {
1960 .owner = THIS_MODULE,
1961 .request = davinci_mcasp_gpio_request,
1962 .free = davinci_mcasp_gpio_free,
1963 .direction_output = davinci_mcasp_gpio_direction_out,
1964 .set = davinci_mcasp_gpio_set,
1965 .direction_input = davinci_mcasp_gpio_direction_in,
1966 .get = davinci_mcasp_gpio_get,
1967 .get_direction = davinci_mcasp_gpio_get_direction,
1968 .base = -1,
1969 .ngpio = 32,
1970};
1971
1972static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
1973{
1974 if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller"))
1975 return 0;
1976
1977 mcasp->gpio_chip = davinci_mcasp_template_chip;
1978 mcasp->gpio_chip.label = dev_name(mcasp->dev);
1979 mcasp->gpio_chip.parent = mcasp->dev;
1980#ifdef CONFIG_OF_GPIO
1981 mcasp->gpio_chip.of_node = mcasp->dev->of_node;
1982#endif
1983
1984 return devm_gpiochip_add_data(mcasp->dev, &mcasp->gpio_chip, mcasp);
1985}
1986
1987#else /* CONFIG_GPIOLIB */
1988static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
1989{
1990 return 0;
1991}
1992#endif /* CONFIG_GPIOLIB */
1993
Chaithrika U Sb67f4482009-06-05 06:28:40 -04001994static int davinci_mcasp_probe(struct platform_device *pdev)
1995{
Peter Ujfalusi8de131f2014-03-14 16:42:46 +02001996 struct snd_dmaengine_dai_dma_data *dma_data;
Axel Lin508a43f2015-08-24 16:47:36 +08001997 struct resource *mem, *res, *dat;
Peter Ujfalusid1debaf2014-02-03 14:51:51 +02001998 struct davinci_mcasp_pdata *pdata;
Peter Ujfalusi70091a32013-11-14 11:35:29 +02001999 struct davinci_mcasp *mcasp;
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002000 char *irq_name;
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002001 int *dma;
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002002 int irq;
Julia Lawall96d31e22011-12-29 17:51:21 +01002003 int ret;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002004
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05302005 if (!pdev->dev.platform_data && !pdev->dev.of_node) {
2006 dev_err(&pdev->dev, "No platform data supplied\n");
2007 return -EINVAL;
2008 }
2009
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002010 mcasp = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcasp),
Julia Lawall96d31e22011-12-29 17:51:21 +01002011 GFP_KERNEL);
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002012 if (!mcasp)
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002013 return -ENOMEM;
2014
Hebbar, Gururaja3e3b8c32012-08-27 18:56:42 +05302015 pdata = davinci_mcasp_set_pdata_from_of(pdev);
2016 if (!pdata) {
2017 dev_err(&pdev->dev, "no platform data\n");
2018 return -EINVAL;
2019 }
2020
Jyri Sarha256ba182013-10-18 18:37:42 +03002021 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002022 if (!mem) {
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002023 dev_warn(mcasp->dev,
Jyri Sarha256ba182013-10-18 18:37:42 +03002024 "\"mpu\" mem resource not found, using index 0\n");
2025 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2026 if (!mem) {
2027 dev_err(&pdev->dev, "no mem resource?\n");
2028 return -ENODEV;
2029 }
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002030 }
2031
Axel Lin508a43f2015-08-24 16:47:36 +08002032 mcasp->base = devm_ioremap_resource(&pdev->dev, mem);
2033 if (IS_ERR(mcasp->base))
2034 return PTR_ERR(mcasp->base);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002035
Hebbar, Gururaja10884342012-08-08 20:40:32 +05302036 pm_runtime_enable(&pdev->dev);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002037
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002038 mcasp->op_mode = pdata->op_mode;
Peter Ujfalusi1a5923d2014-11-10 12:32:15 +02002039 /* sanity check for tdm slots parameter */
2040 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
2041 if (pdata->tdm_slots < 2) {
2042 dev_err(&pdev->dev, "invalid tdm slots: %d\n",
2043 pdata->tdm_slots);
2044 mcasp->tdm_slots = 2;
2045 } else if (pdata->tdm_slots > 32) {
2046 dev_err(&pdev->dev, "invalid tdm slots: %d\n",
2047 pdata->tdm_slots);
2048 mcasp->tdm_slots = 32;
2049 } else {
2050 mcasp->tdm_slots = pdata->tdm_slots;
2051 }
2052 }
2053
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002054 mcasp->num_serializer = pdata->num_serializer;
Peter Ujfalusi61754712019-01-03 16:05:50 +02002055#ifdef CONFIG_PM
Kees Cooka86854d2018-06-12 14:07:58 -07002056 mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
2057 mcasp->num_serializer, sizeof(u32),
Peter Ujfalusif114ce62014-10-01 16:02:12 +03002058 GFP_KERNEL);
Christophe Jaillet4243e042017-08-27 08:46:50 +02002059 if (!mcasp->context.xrsr_regs) {
2060 ret = -ENOMEM;
2061 goto err;
2062 }
Peter Ujfalusif114ce62014-10-01 16:02:12 +03002063#endif
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002064 mcasp->serial_dir = pdata->serial_dir;
2065 mcasp->version = pdata->version;
2066 mcasp->txnumevt = pdata->txnumevt;
2067 mcasp->rxnumevt = pdata->rxnumevt;
Peter Ujfalusibc184542018-11-16 15:41:41 +02002068 mcasp->dismod = pdata->dismod;
Peter Ujfalusi487dce82013-11-14 11:35:31 +02002069
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002070 mcasp->dev = &pdev->dev;
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002071
Peter Ujfalusi5a1b8a82014-12-30 16:10:32 +02002072 irq = platform_get_irq_byname(pdev, "common");
2073 if (irq >= 0) {
Peter Ujfalusiab1fffe2015-09-18 15:02:50 +03002074 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common",
Peter Ujfalusi5a1b8a82014-12-30 16:10:32 +02002075 dev_name(&pdev->dev));
Arvind Yadav0c8b7942017-09-20 15:36:09 +05302076 if (!irq_name) {
2077 ret = -ENOMEM;
2078 goto err;
2079 }
Peter Ujfalusi5a1b8a82014-12-30 16:10:32 +02002080 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
2081 davinci_mcasp_common_irq_handler,
Peter Ujfalusi8f511ff2015-02-02 14:38:32 +02002082 IRQF_ONESHOT | IRQF_SHARED,
2083 irq_name, mcasp);
Peter Ujfalusi5a1b8a82014-12-30 16:10:32 +02002084 if (ret) {
2085 dev_err(&pdev->dev, "common IRQ request failed\n");
2086 goto err;
2087 }
2088
2089 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN;
2090 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
2091 }
2092
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002093 irq = platform_get_irq_byname(pdev, "rx");
2094 if (irq >= 0) {
Peter Ujfalusiab1fffe2015-09-18 15:02:50 +03002095 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx",
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002096 dev_name(&pdev->dev));
Arvind Yadav0c8b7942017-09-20 15:36:09 +05302097 if (!irq_name) {
2098 ret = -ENOMEM;
2099 goto err;
2100 }
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002101 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
2102 davinci_mcasp_rx_irq_handler,
2103 IRQF_ONESHOT, irq_name, mcasp);
2104 if (ret) {
2105 dev_err(&pdev->dev, "RX IRQ request failed\n");
2106 goto err;
2107 }
2108
2109 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
2110 }
2111
2112 irq = platform_get_irq_byname(pdev, "tx");
2113 if (irq >= 0) {
Peter Ujfalusiab1fffe2015-09-18 15:02:50 +03002114 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx",
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002115 dev_name(&pdev->dev));
Arvind Yadav0c8b7942017-09-20 15:36:09 +05302116 if (!irq_name) {
2117 ret = -ENOMEM;
2118 goto err;
2119 }
Misael Lopez Cruza7a33242014-11-12 16:38:05 +02002120 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
2121 davinci_mcasp_tx_irq_handler,
2122 IRQF_ONESHOT, irq_name, mcasp);
2123 if (ret) {
2124 dev_err(&pdev->dev, "TX IRQ request failed\n");
2125 goto err;
2126 }
2127
2128 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN;
2129 }
2130
Jyri Sarha256ba182013-10-18 18:37:42 +03002131 dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002132 if (dat)
2133 mcasp->dat_port = true;
Jyri Sarha256ba182013-10-18 18:37:42 +03002134
Peter Ujfalusi8de131f2014-03-14 16:42:46 +02002135 dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002136 if (dat)
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002137 dma_data->addr = dat->start;
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002138 else
Peter Ujfalusi9ac00132016-06-02 12:55:05 +03002139 dma_data->addr = mem->start + davinci_mcasp_txdma_offset(pdata);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002140
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002141 dma = &mcasp->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002142 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
Jyri Sarha4023fe62013-10-18 18:37:43 +03002143 if (res)
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002144 *dma = res->start;
Jyri Sarha4023fe62013-10-18 18:37:43 +03002145 else
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002146 *dma = pdata->tx_dma_channel;
Troy Kisky92e2a6f2009-09-11 14:29:03 -07002147
Peter Ujfalusi8de131f2014-03-14 16:42:46 +02002148 /* dmaengine filter data for DT and non-DT boot */
2149 if (pdev->dev.of_node)
2150 dma_data->filter_data = "tx";
2151 else
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002152 dma_data->filter_data = dma;
Peter Ujfalusi8de131f2014-03-14 16:42:46 +02002153
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002154 /* RX is not valid in DIT mode */
2155 if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002156 dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002157 if (dat)
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002158 dma_data->addr = dat->start;
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002159 else
Peter Ujfalusi9ac00132016-06-02 12:55:05 +03002160 dma_data->addr =
2161 mem->start + davinci_mcasp_rxdma_offset(pdata);
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002162
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002163 dma = &mcasp->dma_request[SNDRV_PCM_STREAM_CAPTURE];
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002164 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
2165 if (res)
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002166 *dma = res->start;
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002167 else
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002168 *dma = pdata->rx_dma_channel;
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002169
2170 /* dmaengine filter data for DT and non-DT boot */
2171 if (pdev->dev.of_node)
2172 dma_data->filter_data = "rx";
2173 else
Peter Ujfalusi9759e7e2015-03-03 16:45:20 +02002174 dma_data->filter_data = dma;
Peter Ujfalusicaa1d792015-02-02 14:38:33 +02002175 }
Peter Ujfalusi453c4992013-11-14 11:35:34 +02002176
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002177 if (mcasp->version < MCASP_VERSION_3) {
2178 mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE;
Peter Ujfalusi64ebdec2014-03-07 15:03:55 +02002179 /* dma_params->dma_addr is pointing to the data port address */
Peter Ujfalusicbc7956c2013-11-14 11:35:32 +02002180 mcasp->dat_port = true;
2181 } else {
2182 mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE;
2183 }
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002184
Jyri Sarhadd55ff82015-09-09 21:27:44 +03002185 /* Allocate memory for long enough list for all possible
2186 * scenarios. Maximum number tdm slots is 32 and there cannot
2187 * be more serializers than given in the configuration. The
2188 * serializer directions could be taken into account, but it
2189 * would make code much more complex and save only couple of
2190 * bytes.
2191 */
2192 mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list =
Kees Cooka86854d2018-06-12 14:07:58 -07002193 devm_kcalloc(mcasp->dev,
2194 32 + mcasp->num_serializer - 1,
2195 sizeof(unsigned int),
Jyri Sarhadd55ff82015-09-09 21:27:44 +03002196 GFP_KERNEL);
2197
2198 mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list =
Kees Cooka86854d2018-06-12 14:07:58 -07002199 devm_kcalloc(mcasp->dev,
2200 32 + mcasp->num_serializer - 1,
2201 sizeof(unsigned int),
Jyri Sarhadd55ff82015-09-09 21:27:44 +03002202 GFP_KERNEL);
2203
2204 if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list ||
Christophe Jaillet1b8b68b2017-09-16 07:40:29 +02002205 !mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list) {
2206 ret = -ENOMEM;
2207 goto err;
2208 }
Jyri Sarhadd55ff82015-09-09 21:27:44 +03002209
2210 ret = davinci_mcasp_set_ch_constraints(mcasp);
Jyri Sarha5935a052015-04-23 16:16:05 +03002211 if (ret)
2212 goto err;
2213
Peter Ujfalusi70091a32013-11-14 11:35:29 +02002214 dev_set_drvdata(&pdev->dev, mcasp);
Peter Ujfalusiae726e92013-11-14 11:35:35 +02002215
2216 mcasp_reparent_fck(pdev);
2217
Peter Ujfalusi540f1ba72019-01-03 16:05:52 +02002218 /* All PINS as McASP */
2219 pm_runtime_get_sync(mcasp->dev);
2220 mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
2221 pm_runtime_put(mcasp->dev);
2222
2223 ret = davinci_mcasp_init_gpiochip(mcasp);
2224 if (ret)
2225 goto err;
2226
Peter Ujfalusib6bb3702014-04-22 14:03:13 +03002227 ret = devm_snd_soc_register_component(&pdev->dev,
2228 &davinci_mcasp_component,
2229 &davinci_mcasp_dai[pdata->op_mode], 1);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002230
2231 if (ret != 0)
Peter Ujfalusib6bb3702014-04-22 14:03:13 +03002232 goto err;
Hebbar, Gururajaf08095a2012-08-27 18:56:39 +05302233
Jyri Sarha9fbd58c2015-06-02 23:09:34 +03002234 ret = davinci_mcasp_get_dma_type(mcasp);
2235 switch (ret) {
2236 case PCM_EDMA:
Peter Ujfalusif3f9cfa2014-07-16 15:12:04 +03002237 ret = edma_pcm_platform_register(&pdev->dev);
Jyri Sarha9fbd58c2015-06-02 23:09:34 +03002238 break;
2239 case PCM_SDMA:
Peter Ujfalusi077a4032018-05-09 14:03:55 +03002240 ret = sdma_pcm_platform_register(&pdev->dev, NULL, NULL);
Jyri Sarha9fbd58c2015-06-02 23:09:34 +03002241 break;
2242 default:
2243 dev_err(&pdev->dev, "No DMA controller found (%d)\n", ret);
2244 case -EPROBE_DEFER:
2245 goto err;
Peter Ujfalusid5c6c592014-04-16 15:46:20 +03002246 break;
2247 }
2248
2249 if (ret) {
2250 dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
Peter Ujfalusib6bb3702014-04-22 14:03:13 +03002251 goto err;
Hebbar, Gururajaf08095a2012-08-27 18:56:39 +05302252 }
2253
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002254 return 0;
2255
Peter Ujfalusib6bb3702014-04-22 14:03:13 +03002256err:
Hebbar, Gururaja10884342012-08-08 20:40:32 +05302257 pm_runtime_disable(&pdev->dev);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002258 return ret;
2259}
2260
2261static int davinci_mcasp_remove(struct platform_device *pdev)
2262{
Hebbar, Gururaja10884342012-08-08 20:40:32 +05302263 pm_runtime_disable(&pdev->dev);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002264
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002265 return 0;
2266}
2267
Peter Ujfalusi61754712019-01-03 16:05:50 +02002268#ifdef CONFIG_PM
2269static int davinci_mcasp_runtime_suspend(struct device *dev)
2270{
2271 struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
2272 struct davinci_mcasp_context *context = &mcasp->context;
2273 u32 reg;
2274 int i;
2275
2276 for (i = 0; i < ARRAY_SIZE(context_regs); i++)
2277 context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
2278
2279 if (mcasp->txnumevt) {
2280 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
2281 context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
2282 }
2283 if (mcasp->rxnumevt) {
2284 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
2285 context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
2286 }
2287
2288 for (i = 0; i < mcasp->num_serializer; i++)
2289 context->xrsr_regs[i] = mcasp_get_reg(mcasp,
2290 DAVINCI_MCASP_XRSRCTL_REG(i));
2291
2292 return 0;
2293}
2294
2295static int davinci_mcasp_runtime_resume(struct device *dev)
2296{
2297 struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
2298 struct davinci_mcasp_context *context = &mcasp->context;
2299 u32 reg;
2300 int i;
2301
2302 for (i = 0; i < ARRAY_SIZE(context_regs); i++)
2303 mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
2304
2305 if (mcasp->txnumevt) {
2306 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
2307 mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
2308 }
2309 if (mcasp->rxnumevt) {
2310 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
2311 mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
2312 }
2313
2314 for (i = 0; i < mcasp->num_serializer; i++)
2315 mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
2316 context->xrsr_regs[i]);
2317
2318 return 0;
2319}
2320
2321#endif
2322
2323static const struct dev_pm_ops davinci_mcasp_pm_ops = {
2324 SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend,
2325 davinci_mcasp_runtime_resume,
2326 NULL)
2327};
2328
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002329static struct platform_driver davinci_mcasp_driver = {
2330 .probe = davinci_mcasp_probe,
2331 .remove = davinci_mcasp_remove,
2332 .driver = {
2333 .name = "davinci-mcasp",
Peter Ujfalusi61754712019-01-03 16:05:50 +02002334 .pm = &davinci_mcasp_pm_ops,
Sachin Kamatea421eb2013-05-22 16:53:37 +05302335 .of_match_table = mcasp_dt_ids,
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002336 },
2337};
2338
Axel Linf9b8a512011-11-25 10:09:27 +08002339module_platform_driver(davinci_mcasp_driver);
Chaithrika U Sb67f4482009-06-05 06:28:40 -04002340
2341MODULE_AUTHOR("Steve Chen");
2342MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
2343MODULE_LICENSE("GPL");