xref: /OK3568_Linux_fs/kernel/sound/soc/atmel/mchp-spdiftx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Driver for Microchip S/PDIF TX Controller
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6*4882a593Smuzhiyun //
7*4882a593Smuzhiyun // Author: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/spinlock.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <sound/asoundef.h>
15*4882a593Smuzhiyun #include <sound/dmaengine_pcm.h>
16*4882a593Smuzhiyun #include <sound/pcm_params.h>
17*4882a593Smuzhiyun #include <sound/soc.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * ---- S/PDIF Transmitter Controller Register map ----
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun #define SPDIFTX_CR			0x00	/* Control Register */
23*4882a593Smuzhiyun #define SPDIFTX_MR			0x04	/* Mode Register */
24*4882a593Smuzhiyun #define SPDIFTX_CDR			0x0C	/* Common Data Register */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define SPDIFTX_IER			0x14	/* Interrupt Enable Register */
27*4882a593Smuzhiyun #define SPDIFTX_IDR			0x18	/* Interrupt Disable Register */
28*4882a593Smuzhiyun #define SPDIFTX_IMR			0x1C	/* Interrupt Mask Register */
29*4882a593Smuzhiyun #define SPDIFTX_ISR			0x20	/* Interrupt Status Register */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define SPDIFTX_CH1UD(reg)	(0x50 + (reg) * 4)	/* User Data 1 Register x */
32*4882a593Smuzhiyun #define SPDIFTX_CH1S(reg)	(0x80 + (reg) * 4)	/* Channel Status 1 Register x */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define SPDIFTX_VERSION			0xF0
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun  * ---- Control Register (Write-only) ----
38*4882a593Smuzhiyun  */
39*4882a593Smuzhiyun #define SPDIFTX_CR_SWRST		BIT(0)	/* Software Reset */
40*4882a593Smuzhiyun #define SPDIFTX_CR_FCLR			BIT(1)	/* FIFO clear */
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun  * ---- Mode Register (Read/Write) ----
44*4882a593Smuzhiyun  */
45*4882a593Smuzhiyun /* Transmit Enable */
46*4882a593Smuzhiyun #define SPDIFTX_MR_TXEN_MASK		GENMASK(0, 0)
47*4882a593Smuzhiyun #define SPDIFTX_MR_TXEN_DISABLE		(0 << 0)
48*4882a593Smuzhiyun #define SPDIFTX_MR_TXEN_ENABLE		(1 << 0)
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* Multichannel Transfer */
51*4882a593Smuzhiyun #define SPDIFTX_MR_MULTICH_MASK		GENAMSK(1, 1)
52*4882a593Smuzhiyun #define SPDIFTX_MR_MULTICH_MONO		(0 << 1)
53*4882a593Smuzhiyun #define SPDIFTX_MR_MULTICH_DUAL		(1 << 1)
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* Data Word Endian Mode */
56*4882a593Smuzhiyun #define SPDIFTX_MR_ENDIAN_MASK		GENMASK(2, 2)
57*4882a593Smuzhiyun #define SPDIFTX_MR_ENDIAN_LITTLE	(0 << 2)
58*4882a593Smuzhiyun #define SPDIFTX_MR_ENDIAN_BIG		(1 << 2)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* Data Justification */
61*4882a593Smuzhiyun #define SPDIFTX_MR_JUSTIFY_MASK		GENMASK(3, 3)
62*4882a593Smuzhiyun #define SPDIFTX_MR_JUSTIFY_LSB		(0 << 3)
63*4882a593Smuzhiyun #define SPDIFTX_MR_JUSTIFY_MSB		(1 << 3)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* Common Audio Register Transfer Mode */
66*4882a593Smuzhiyun #define SPDIFTX_MR_CMODE_MASK			GENMASK(5, 4)
67*4882a593Smuzhiyun #define SPDIFTX_MR_CMODE_INDEX_ACCESS		(0 << 4)
68*4882a593Smuzhiyun #define SPDIFTX_MR_CMODE_TOGGLE_ACCESS		(1 << 4)
69*4882a593Smuzhiyun #define SPDIFTX_MR_CMODE_INTERLVD_ACCESS	(2 << 4)
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* Valid Bits per Sample */
72*4882a593Smuzhiyun #define SPDIFTX_MR_VBPS_MASK		GENMASK(13, 8)
73*4882a593Smuzhiyun #define SPDIFTX_MR_VBPS(bps)		(((bps) << 8) & SPDIFTX_MR_VBPS_MASK)
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /* Chunk Size */
76*4882a593Smuzhiyun #define SPDIFTX_MR_CHUNK_MASK		GENMASK(19, 16)
77*4882a593Smuzhiyun #define SPDIFTX_MR_CHUNK(size)		(((size) << 16) & SPDIFTX_MR_CHUNK_MASK)
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* Validity Bits for Channels 1 and 2 */
80*4882a593Smuzhiyun #define SPDIFTX_MR_VALID1			BIT(24)
81*4882a593Smuzhiyun #define SPDIFTX_MR_VALID2			BIT(25)
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /* Disable Null Frame on underrrun */
84*4882a593Smuzhiyun #define SPDIFTX_MR_DNFR_MASK		GENMASK(27, 27)
85*4882a593Smuzhiyun #define SPDIFTX_MR_DNFR_INVALID		(0 << 27)
86*4882a593Smuzhiyun #define SPDIFTX_MR_DNFR_VALID		(1 << 27)
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /* Bytes per Sample */
89*4882a593Smuzhiyun #define SPDIFTX_MR_BPS_MASK		GENMASK(29, 28)
90*4882a593Smuzhiyun #define SPDIFTX_MR_BPS(bytes) \
91*4882a593Smuzhiyun 	((((bytes) - 1) << 28) & SPDIFTX_MR_BPS_MASK)
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /*
94*4882a593Smuzhiyun  * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----
95*4882a593Smuzhiyun  */
96*4882a593Smuzhiyun #define SPDIFTX_IR_TXRDY		BIT(0)
97*4882a593Smuzhiyun #define SPDIFTX_IR_TXEMPTY		BIT(1)
98*4882a593Smuzhiyun #define SPDIFTX_IR_TXFULL		BIT(2)
99*4882a593Smuzhiyun #define SPDIFTX_IR_TXCHUNK		BIT(3)
100*4882a593Smuzhiyun #define SPDIFTX_IR_TXUDR		BIT(4)
101*4882a593Smuzhiyun #define SPDIFTX_IR_TXOVR		BIT(5)
102*4882a593Smuzhiyun #define SPDIFTX_IR_CSRDY		BIT(6)
103*4882a593Smuzhiyun #define SPDIFTX_IR_UDRDY		BIT(7)
104*4882a593Smuzhiyun #define SPDIFTX_IR_TXRDYCH(ch)		BIT((ch) + 8)
105*4882a593Smuzhiyun #define SPDIFTX_IR_SECE			BIT(10)
106*4882a593Smuzhiyun #define SPDIFTX_IR_TXUDRCH(ch)		BIT((ch) + 11)
107*4882a593Smuzhiyun #define SPDIFTX_IR_BEND			BIT(13)
108*4882a593Smuzhiyun 
mchp_spdiftx_readable_reg(struct device * dev,unsigned int reg)109*4882a593Smuzhiyun static bool mchp_spdiftx_readable_reg(struct device *dev, unsigned int reg)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	switch (reg) {
112*4882a593Smuzhiyun 	case SPDIFTX_MR:
113*4882a593Smuzhiyun 	case SPDIFTX_IMR:
114*4882a593Smuzhiyun 	case SPDIFTX_ISR:
115*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(0):
116*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(1):
117*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(2):
118*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(3):
119*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(4):
120*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(5):
121*4882a593Smuzhiyun 	case SPDIFTX_CH1S(0):
122*4882a593Smuzhiyun 	case SPDIFTX_CH1S(1):
123*4882a593Smuzhiyun 	case SPDIFTX_CH1S(2):
124*4882a593Smuzhiyun 	case SPDIFTX_CH1S(3):
125*4882a593Smuzhiyun 	case SPDIFTX_CH1S(4):
126*4882a593Smuzhiyun 	case SPDIFTX_CH1S(5):
127*4882a593Smuzhiyun 		return true;
128*4882a593Smuzhiyun 	default:
129*4882a593Smuzhiyun 		return false;
130*4882a593Smuzhiyun 	}
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
mchp_spdiftx_writeable_reg(struct device * dev,unsigned int reg)133*4882a593Smuzhiyun static bool mchp_spdiftx_writeable_reg(struct device *dev, unsigned int reg)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	switch (reg) {
136*4882a593Smuzhiyun 	case SPDIFTX_CR:
137*4882a593Smuzhiyun 	case SPDIFTX_MR:
138*4882a593Smuzhiyun 	case SPDIFTX_CDR:
139*4882a593Smuzhiyun 	case SPDIFTX_IER:
140*4882a593Smuzhiyun 	case SPDIFTX_IDR:
141*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(0):
142*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(1):
143*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(2):
144*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(3):
145*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(4):
146*4882a593Smuzhiyun 	case SPDIFTX_CH1UD(5):
147*4882a593Smuzhiyun 	case SPDIFTX_CH1S(0):
148*4882a593Smuzhiyun 	case SPDIFTX_CH1S(1):
149*4882a593Smuzhiyun 	case SPDIFTX_CH1S(2):
150*4882a593Smuzhiyun 	case SPDIFTX_CH1S(3):
151*4882a593Smuzhiyun 	case SPDIFTX_CH1S(4):
152*4882a593Smuzhiyun 	case SPDIFTX_CH1S(5):
153*4882a593Smuzhiyun 		return true;
154*4882a593Smuzhiyun 	default:
155*4882a593Smuzhiyun 		return false;
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
mchp_spdiftx_precious_reg(struct device * dev,unsigned int reg)159*4882a593Smuzhiyun static bool mchp_spdiftx_precious_reg(struct device *dev, unsigned int reg)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	switch (reg) {
162*4882a593Smuzhiyun 	case SPDIFTX_CDR:
163*4882a593Smuzhiyun 	case SPDIFTX_ISR:
164*4882a593Smuzhiyun 		return true;
165*4882a593Smuzhiyun 	default:
166*4882a593Smuzhiyun 		return false;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun static const struct regmap_config mchp_spdiftx_regmap_config = {
171*4882a593Smuzhiyun 	.reg_bits = 32,
172*4882a593Smuzhiyun 	.reg_stride = 4,
173*4882a593Smuzhiyun 	.val_bits = 32,
174*4882a593Smuzhiyun 	.max_register = SPDIFTX_VERSION,
175*4882a593Smuzhiyun 	.readable_reg = mchp_spdiftx_readable_reg,
176*4882a593Smuzhiyun 	.writeable_reg = mchp_spdiftx_writeable_reg,
177*4882a593Smuzhiyun 	.precious_reg = mchp_spdiftx_precious_reg,
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun #define SPDIFTX_GCLK_RATIO	128
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun #define SPDIFTX_CS_BITS		192
183*4882a593Smuzhiyun #define SPDIFTX_UD_BITS		192
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun struct mchp_spdiftx_mixer_control {
186*4882a593Smuzhiyun 	unsigned char				ch_stat[SPDIFTX_CS_BITS / 8];
187*4882a593Smuzhiyun 	unsigned char				user_data[SPDIFTX_UD_BITS / 8];
188*4882a593Smuzhiyun 	spinlock_t				lock; /* exclusive access to control data */
189*4882a593Smuzhiyun };
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun struct mchp_spdiftx_dev {
192*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control	control;
193*4882a593Smuzhiyun 	struct snd_dmaengine_dai_dma_data	playback;
194*4882a593Smuzhiyun 	struct device				*dev;
195*4882a593Smuzhiyun 	struct regmap				*regmap;
196*4882a593Smuzhiyun 	struct clk				*pclk;
197*4882a593Smuzhiyun 	struct clk				*gclk;
198*4882a593Smuzhiyun 	unsigned int				fmt;
199*4882a593Smuzhiyun 	unsigned int				gclk_enabled:1;
200*4882a593Smuzhiyun };
201*4882a593Smuzhiyun 
mchp_spdiftx_is_running(struct mchp_spdiftx_dev * dev)202*4882a593Smuzhiyun static inline int mchp_spdiftx_is_running(struct mchp_spdiftx_dev *dev)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	u32 mr;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	regmap_read(dev->regmap, SPDIFTX_MR, &mr);
207*4882a593Smuzhiyun 	return !!(mr & SPDIFTX_MR_TXEN_ENABLE);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
mchp_spdiftx_channel_status_write(struct mchp_spdiftx_dev * dev)210*4882a593Smuzhiyun static void mchp_spdiftx_channel_status_write(struct mchp_spdiftx_dev *dev)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
213*4882a593Smuzhiyun 	u32 val;
214*4882a593Smuzhiyun 	int i;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat) / 4; i++) {
217*4882a593Smuzhiyun 		val = (ctrl->ch_stat[(i * 4) + 0] << 0) |
218*4882a593Smuzhiyun 		      (ctrl->ch_stat[(i * 4) + 1] << 8) |
219*4882a593Smuzhiyun 		      (ctrl->ch_stat[(i * 4) + 2] << 16) |
220*4882a593Smuzhiyun 		      (ctrl->ch_stat[(i * 4) + 3] << 24);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 		regmap_write(dev->regmap, SPDIFTX_CH1S(i), val);
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
mchp_spdiftx_user_data_write(struct mchp_spdiftx_dev * dev)226*4882a593Smuzhiyun static void mchp_spdiftx_user_data_write(struct mchp_spdiftx_dev *dev)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
229*4882a593Smuzhiyun 	u32 val;
230*4882a593Smuzhiyun 	int i;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ctrl->user_data) / 4; i++) {
233*4882a593Smuzhiyun 		val = (ctrl->user_data[(i * 4) + 0] << 0) |
234*4882a593Smuzhiyun 		      (ctrl->user_data[(i * 4) + 1] << 8) |
235*4882a593Smuzhiyun 		      (ctrl->user_data[(i * 4) + 2] << 16) |
236*4882a593Smuzhiyun 		      (ctrl->user_data[(i * 4) + 3] << 24);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 		regmap_write(dev->regmap, SPDIFTX_CH1UD(i), val);
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
mchp_spdiftx_interrupt(int irq,void * dev_id)242*4882a593Smuzhiyun static irqreturn_t mchp_spdiftx_interrupt(int irq, void *dev_id)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = dev_id;
245*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
246*4882a593Smuzhiyun 	u32 sr, imr, pending, idr = 0;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	regmap_read(dev->regmap, SPDIFTX_ISR, &sr);
249*4882a593Smuzhiyun 	regmap_read(dev->regmap, SPDIFTX_IMR, &imr);
250*4882a593Smuzhiyun 	pending = sr & imr;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	if (!pending)
253*4882a593Smuzhiyun 		return IRQ_NONE;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (pending & SPDIFTX_IR_TXUDR) {
256*4882a593Smuzhiyun 		dev_warn(dev->dev, "underflow detected\n");
257*4882a593Smuzhiyun 		idr |= SPDIFTX_IR_TXUDR;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (pending & SPDIFTX_IR_TXOVR) {
261*4882a593Smuzhiyun 		dev_warn(dev->dev, "overflow detected\n");
262*4882a593Smuzhiyun 		idr |= SPDIFTX_IR_TXOVR;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	if (pending & SPDIFTX_IR_UDRDY) {
266*4882a593Smuzhiyun 		spin_lock(&ctrl->lock);
267*4882a593Smuzhiyun 		mchp_spdiftx_user_data_write(dev);
268*4882a593Smuzhiyun 		spin_unlock(&ctrl->lock);
269*4882a593Smuzhiyun 		idr |= SPDIFTX_IR_UDRDY;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	if (pending & SPDIFTX_IR_CSRDY) {
273*4882a593Smuzhiyun 		spin_lock(&ctrl->lock);
274*4882a593Smuzhiyun 		mchp_spdiftx_channel_status_write(dev);
275*4882a593Smuzhiyun 		spin_unlock(&ctrl->lock);
276*4882a593Smuzhiyun 		idr |= SPDIFTX_IR_CSRDY;
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_IDR, idr);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	return IRQ_HANDLED;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
mchp_spdiftx_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)284*4882a593Smuzhiyun static int mchp_spdiftx_dai_startup(struct snd_pcm_substream *substream,
285*4882a593Smuzhiyun 				    struct snd_soc_dai *dai)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	/* Software reset the IP */
290*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_CR,
291*4882a593Smuzhiyun 		     SPDIFTX_CR_SWRST | SPDIFTX_CR_FCLR);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	return 0;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
mchp_spdiftx_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)296*4882a593Smuzhiyun static void mchp_spdiftx_dai_shutdown(struct snd_pcm_substream *substream,
297*4882a593Smuzhiyun 				      struct snd_soc_dai *dai)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	/* Disable interrupts */
302*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_IDR, 0xffffffff);
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
mchp_spdiftx_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)305*4882a593Smuzhiyun static int mchp_spdiftx_trigger(struct snd_pcm_substream *substream, int cmd,
306*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
309*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
310*4882a593Smuzhiyun 	u32 mr;
311*4882a593Smuzhiyun 	int running;
312*4882a593Smuzhiyun 	int ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	/* do not start/stop while channel status or user data is updated */
315*4882a593Smuzhiyun 	spin_lock(&ctrl->lock);
316*4882a593Smuzhiyun 	regmap_read(dev->regmap, SPDIFTX_MR, &mr);
317*4882a593Smuzhiyun 	running = !!(mr & SPDIFTX_MR_TXEN_ENABLE);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	switch (cmd) {
320*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_START:
321*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_RESUME:
322*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
323*4882a593Smuzhiyun 		if (!running) {
324*4882a593Smuzhiyun 			mr &= ~SPDIFTX_MR_TXEN_MASK;
325*4882a593Smuzhiyun 			mr |= SPDIFTX_MR_TXEN_ENABLE;
326*4882a593Smuzhiyun 		}
327*4882a593Smuzhiyun 		break;
328*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_STOP:
329*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_SUSPEND:
330*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
331*4882a593Smuzhiyun 		if (running) {
332*4882a593Smuzhiyun 			mr &= ~SPDIFTX_MR_TXEN_MASK;
333*4882a593Smuzhiyun 			mr |= SPDIFTX_MR_TXEN_DISABLE;
334*4882a593Smuzhiyun 		}
335*4882a593Smuzhiyun 		break;
336*4882a593Smuzhiyun 	default:
337*4882a593Smuzhiyun 		spin_unlock(&ctrl->lock);
338*4882a593Smuzhiyun 		return -EINVAL;
339*4882a593Smuzhiyun 	}
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	ret = regmap_write(dev->regmap, SPDIFTX_MR, mr);
342*4882a593Smuzhiyun 	spin_unlock(&ctrl->lock);
343*4882a593Smuzhiyun 	if (ret) {
344*4882a593Smuzhiyun 		dev_err(dev->dev, "unable to disable TX: %d\n", ret);
345*4882a593Smuzhiyun 		return ret;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
mchp_spdiftx_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)351*4882a593Smuzhiyun static int mchp_spdiftx_hw_params(struct snd_pcm_substream *substream,
352*4882a593Smuzhiyun 				  struct snd_pcm_hw_params *params,
353*4882a593Smuzhiyun 				  struct snd_soc_dai *dai)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun 	unsigned long flags;
356*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
357*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
358*4882a593Smuzhiyun 	u32 mr;
359*4882a593Smuzhiyun 	unsigned int bps = params_physical_width(params) / 8;
360*4882a593Smuzhiyun 	int ret;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
363*4882a593Smuzhiyun 		__func__, params_rate(params), params_format(params),
364*4882a593Smuzhiyun 		params_width(params), params_channels(params));
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
367*4882a593Smuzhiyun 		dev_err(dev->dev, "Capture is not supported\n");
368*4882a593Smuzhiyun 		return -EINVAL;
369*4882a593Smuzhiyun 	}
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	regmap_read(dev->regmap, SPDIFTX_MR, &mr);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	if (mr & SPDIFTX_MR_TXEN_ENABLE) {
374*4882a593Smuzhiyun 		dev_err(dev->dev, "PCM already running\n");
375*4882a593Smuzhiyun 		return -EBUSY;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	/* Defaults: Toggle mode, justify to LSB, chunksize 1 */
379*4882a593Smuzhiyun 	mr = SPDIFTX_MR_CMODE_TOGGLE_ACCESS | SPDIFTX_MR_JUSTIFY_LSB;
380*4882a593Smuzhiyun 	dev->playback.maxburst = 1;
381*4882a593Smuzhiyun 	switch (params_channels(params)) {
382*4882a593Smuzhiyun 	case 1:
383*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_MULTICH_MONO;
384*4882a593Smuzhiyun 		break;
385*4882a593Smuzhiyun 	case 2:
386*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_MULTICH_DUAL;
387*4882a593Smuzhiyun 		if (bps > 2)
388*4882a593Smuzhiyun 			dev->playback.maxburst = 2;
389*4882a593Smuzhiyun 		break;
390*4882a593Smuzhiyun 	default:
391*4882a593Smuzhiyun 		dev_err(dev->dev, "unsupported number of channels: %d\n",
392*4882a593Smuzhiyun 			params_channels(params));
393*4882a593Smuzhiyun 		return -EINVAL;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 	mr |= SPDIFTX_MR_CHUNK(dev->playback.maxburst);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	switch (params_format(params)) {
398*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S8:
399*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(8);
400*4882a593Smuzhiyun 		break;
401*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S16_BE:
402*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
403*4882a593Smuzhiyun 		fallthrough;
404*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S16_LE:
405*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(16);
406*4882a593Smuzhiyun 		break;
407*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S18_3BE:
408*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
409*4882a593Smuzhiyun 		fallthrough;
410*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S18_3LE:
411*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(18);
412*4882a593Smuzhiyun 		break;
413*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S20_3BE:
414*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
415*4882a593Smuzhiyun 		fallthrough;
416*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S20_3LE:
417*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(20);
418*4882a593Smuzhiyun 		break;
419*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_3BE:
420*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
421*4882a593Smuzhiyun 		fallthrough;
422*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_3LE:
423*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(24);
424*4882a593Smuzhiyun 		break;
425*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_BE:
426*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
427*4882a593Smuzhiyun 		fallthrough;
428*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_LE:
429*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(24);
430*4882a593Smuzhiyun 		break;
431*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S32_BE:
432*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_ENDIAN_BIG;
433*4882a593Smuzhiyun 		fallthrough;
434*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S32_LE:
435*4882a593Smuzhiyun 		mr |= SPDIFTX_MR_VBPS(32);
436*4882a593Smuzhiyun 		break;
437*4882a593Smuzhiyun 	default:
438*4882a593Smuzhiyun 		dev_err(dev->dev, "unsupported PCM format: %d\n",
439*4882a593Smuzhiyun 			params_format(params));
440*4882a593Smuzhiyun 		return -EINVAL;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	mr |= SPDIFTX_MR_BPS(bps);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	spin_lock_irqsave(&ctrl->lock, flags);
446*4882a593Smuzhiyun 	ctrl->ch_stat[3] &= ~IEC958_AES3_CON_FS;
447*4882a593Smuzhiyun 	switch (params_rate(params)) {
448*4882a593Smuzhiyun 	case 22050:
449*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_22050;
450*4882a593Smuzhiyun 		break;
451*4882a593Smuzhiyun 	case 24000:
452*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_24000;
453*4882a593Smuzhiyun 		break;
454*4882a593Smuzhiyun 	case 32000:
455*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_32000;
456*4882a593Smuzhiyun 		break;
457*4882a593Smuzhiyun 	case 44100:
458*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_44100;
459*4882a593Smuzhiyun 		break;
460*4882a593Smuzhiyun 	case 48000:
461*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_48000;
462*4882a593Smuzhiyun 		break;
463*4882a593Smuzhiyun 	case 88200:
464*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_88200;
465*4882a593Smuzhiyun 		break;
466*4882a593Smuzhiyun 	case 96000:
467*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_96000;
468*4882a593Smuzhiyun 		break;
469*4882a593Smuzhiyun 	case 176400:
470*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_176400;
471*4882a593Smuzhiyun 		break;
472*4882a593Smuzhiyun 	case 192000:
473*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_192000;
474*4882a593Smuzhiyun 		break;
475*4882a593Smuzhiyun 	case 8000:
476*4882a593Smuzhiyun 	case 11025:
477*4882a593Smuzhiyun 	case 16000:
478*4882a593Smuzhiyun 	case 64000:
479*4882a593Smuzhiyun 		ctrl->ch_stat[3] |= IEC958_AES3_CON_FS_NOTID;
480*4882a593Smuzhiyun 		break;
481*4882a593Smuzhiyun 	default:
482*4882a593Smuzhiyun 		dev_err(dev->dev, "unsupported sample frequency: %u\n",
483*4882a593Smuzhiyun 			params_rate(params));
484*4882a593Smuzhiyun 		spin_unlock_irqrestore(&ctrl->lock, flags);
485*4882a593Smuzhiyun 		return -EINVAL;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 	mchp_spdiftx_channel_status_write(dev);
488*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ctrl->lock, flags);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	if (dev->gclk_enabled) {
491*4882a593Smuzhiyun 		clk_disable_unprepare(dev->gclk);
492*4882a593Smuzhiyun 		dev->gclk_enabled = 0;
493*4882a593Smuzhiyun 	}
494*4882a593Smuzhiyun 	ret = clk_set_rate(dev->gclk, params_rate(params) *
495*4882a593Smuzhiyun 				      SPDIFTX_GCLK_RATIO);
496*4882a593Smuzhiyun 	if (ret) {
497*4882a593Smuzhiyun 		dev_err(dev->dev,
498*4882a593Smuzhiyun 			"unable to change gclk rate to: rate %u * ratio %u\n",
499*4882a593Smuzhiyun 			params_rate(params), SPDIFTX_GCLK_RATIO);
500*4882a593Smuzhiyun 		return ret;
501*4882a593Smuzhiyun 	}
502*4882a593Smuzhiyun 	ret = clk_prepare_enable(dev->gclk);
503*4882a593Smuzhiyun 	if (ret) {
504*4882a593Smuzhiyun 		dev_err(dev->dev, "unable to enable gclk: %d\n", ret);
505*4882a593Smuzhiyun 		return ret;
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 	dev->gclk_enabled = 1;
508*4882a593Smuzhiyun 	dev_dbg(dev->dev, "%s(): GCLK set to %d\n", __func__,
509*4882a593Smuzhiyun 		params_rate(params) * SPDIFTX_GCLK_RATIO);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	/* Enable interrupts */
512*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_IER,
513*4882a593Smuzhiyun 		     SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_MR, mr);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
mchp_spdiftx_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)520*4882a593Smuzhiyun static int mchp_spdiftx_hw_free(struct snd_pcm_substream *substream,
521*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	regmap_write(dev->regmap, SPDIFTX_IDR,
526*4882a593Smuzhiyun 		     SPDIFTX_IR_TXUDR | SPDIFTX_IR_TXOVR);
527*4882a593Smuzhiyun 	if (dev->gclk_enabled) {
528*4882a593Smuzhiyun 		clk_disable_unprepare(dev->gclk);
529*4882a593Smuzhiyun 		dev->gclk_enabled = 0;
530*4882a593Smuzhiyun 	}
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	return regmap_write(dev->regmap, SPDIFTX_CR,
533*4882a593Smuzhiyun 			    SPDIFTX_CR_SWRST | SPDIFTX_CR_FCLR);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static const struct snd_soc_dai_ops mchp_spdiftx_dai_ops = {
537*4882a593Smuzhiyun 	.startup	= mchp_spdiftx_dai_startup,
538*4882a593Smuzhiyun 	.shutdown	= mchp_spdiftx_dai_shutdown,
539*4882a593Smuzhiyun 	.trigger	= mchp_spdiftx_trigger,
540*4882a593Smuzhiyun 	.hw_params	= mchp_spdiftx_hw_params,
541*4882a593Smuzhiyun 	.hw_free	= mchp_spdiftx_hw_free,
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun #define MCHP_SPDIFTX_RATES	SNDRV_PCM_RATE_8000_192000
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun #define MCHP_SPDIFTX_FORMATS	(SNDRV_PCM_FMTBIT_S8 |		\
547*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S16_LE |	\
548*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_U16_BE |	\
549*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S18_3LE |	\
550*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S18_3BE |	\
551*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S20_3LE |	\
552*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S20_3BE |	\
553*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S24_3LE |	\
554*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S24_3BE |	\
555*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S24_LE |	\
556*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S24_BE |	\
557*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S32_LE |	\
558*4882a593Smuzhiyun 				 SNDRV_PCM_FMTBIT_S32_BE	\
559*4882a593Smuzhiyun 				 )
560*4882a593Smuzhiyun 
mchp_spdiftx_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)561*4882a593Smuzhiyun static int mchp_spdiftx_info(struct snd_kcontrol *kcontrol,
562*4882a593Smuzhiyun 			     struct snd_ctl_elem_info *uinfo)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
565*4882a593Smuzhiyun 	uinfo->count = 1;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	return 0;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun 
mchp_spdiftx_cs_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uvalue)570*4882a593Smuzhiyun static int mchp_spdiftx_cs_get(struct snd_kcontrol *kcontrol,
571*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *uvalue)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun 	unsigned long flags;
574*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
575*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
576*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	spin_lock_irqsave(&ctrl->lock, flags);
579*4882a593Smuzhiyun 	memcpy(uvalue->value.iec958.status, ctrl->ch_stat,
580*4882a593Smuzhiyun 	       sizeof(ctrl->ch_stat));
581*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ctrl->lock, flags);
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	return 0;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun 
mchp_spdiftx_cs_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uvalue)586*4882a593Smuzhiyun static int mchp_spdiftx_cs_put(struct snd_kcontrol *kcontrol,
587*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *uvalue)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun 	unsigned long flags;
590*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
591*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
592*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
593*4882a593Smuzhiyun 	int changed = 0;
594*4882a593Smuzhiyun 	int i;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	spin_lock_irqsave(&ctrl->lock, flags);
597*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat); i++) {
598*4882a593Smuzhiyun 		if (ctrl->ch_stat[i] != uvalue->value.iec958.status[i])
599*4882a593Smuzhiyun 			changed = 1;
600*4882a593Smuzhiyun 		ctrl->ch_stat[i] = uvalue->value.iec958.status[i];
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	if (changed) {
604*4882a593Smuzhiyun 		/* don't enable IP while we copy the channel status */
605*4882a593Smuzhiyun 		if (mchp_spdiftx_is_running(dev)) {
606*4882a593Smuzhiyun 			/*
607*4882a593Smuzhiyun 			 * if SPDIF is running, wait for interrupt to write
608*4882a593Smuzhiyun 			 * channel status
609*4882a593Smuzhiyun 			 */
610*4882a593Smuzhiyun 			regmap_write(dev->regmap, SPDIFTX_IER,
611*4882a593Smuzhiyun 				     SPDIFTX_IR_CSRDY);
612*4882a593Smuzhiyun 		} else {
613*4882a593Smuzhiyun 			mchp_spdiftx_channel_status_write(dev);
614*4882a593Smuzhiyun 		}
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ctrl->lock, flags);
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	return changed;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun 
mchp_spdiftx_cs_mask(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uvalue)621*4882a593Smuzhiyun static int mchp_spdiftx_cs_mask(struct snd_kcontrol *kcontrol,
622*4882a593Smuzhiyun 				struct snd_ctl_elem_value *uvalue)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun 	memset(uvalue->value.iec958.status, 0xff,
625*4882a593Smuzhiyun 	       sizeof(uvalue->value.iec958.status));
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	return 0;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
mchp_spdiftx_subcode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uvalue)630*4882a593Smuzhiyun static int mchp_spdiftx_subcode_get(struct snd_kcontrol *kcontrol,
631*4882a593Smuzhiyun 				    struct snd_ctl_elem_value *uvalue)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
634*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
635*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
636*4882a593Smuzhiyun 	unsigned long flags;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	spin_lock_irqsave(&ctrl->lock, flags);
639*4882a593Smuzhiyun 	memcpy(uvalue->value.iec958.subcode, ctrl->user_data,
640*4882a593Smuzhiyun 	       sizeof(ctrl->user_data));
641*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ctrl->lock, flags);
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	return 0;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun 
mchp_spdiftx_subcode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * uvalue)646*4882a593Smuzhiyun static int mchp_spdiftx_subcode_put(struct snd_kcontrol *kcontrol,
647*4882a593Smuzhiyun 				    struct snd_ctl_elem_value *uvalue)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun 	unsigned long flags;
650*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
651*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
652*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl = &dev->control;
653*4882a593Smuzhiyun 	int changed = 0;
654*4882a593Smuzhiyun 	int i;
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	spin_lock_irqsave(&ctrl->lock, flags);
657*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ctrl->user_data); i++) {
658*4882a593Smuzhiyun 		if (ctrl->user_data[i] != uvalue->value.iec958.subcode[i])
659*4882a593Smuzhiyun 			changed = 1;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 		ctrl->user_data[i] = uvalue->value.iec958.subcode[i];
662*4882a593Smuzhiyun 	}
663*4882a593Smuzhiyun 	if (changed) {
664*4882a593Smuzhiyun 		if (mchp_spdiftx_is_running(dev)) {
665*4882a593Smuzhiyun 			/*
666*4882a593Smuzhiyun 			 * if SPDIF is running, wait for interrupt to write
667*4882a593Smuzhiyun 			 * user data
668*4882a593Smuzhiyun 			 */
669*4882a593Smuzhiyun 			regmap_write(dev->regmap, SPDIFTX_IER,
670*4882a593Smuzhiyun 				     SPDIFTX_IR_UDRDY);
671*4882a593Smuzhiyun 		} else {
672*4882a593Smuzhiyun 			mchp_spdiftx_user_data_write(dev);
673*4882a593Smuzhiyun 		}
674*4882a593Smuzhiyun 	}
675*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ctrl->lock, flags);
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	return changed;
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun static struct snd_kcontrol_new mchp_spdiftx_ctrls[] = {
681*4882a593Smuzhiyun 	/* Channel status controller */
682*4882a593Smuzhiyun 	{
683*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
684*4882a593Smuzhiyun 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
685*4882a593Smuzhiyun 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
686*4882a593Smuzhiyun 			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
687*4882a593Smuzhiyun 		.info = mchp_spdiftx_info,
688*4882a593Smuzhiyun 		.get = mchp_spdiftx_cs_get,
689*4882a593Smuzhiyun 		.put = mchp_spdiftx_cs_put,
690*4882a593Smuzhiyun 	},
691*4882a593Smuzhiyun 	{
692*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
693*4882a593Smuzhiyun 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
694*4882a593Smuzhiyun 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
695*4882a593Smuzhiyun 			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
696*4882a593Smuzhiyun 		.info = mchp_spdiftx_info,
697*4882a593Smuzhiyun 		.get = mchp_spdiftx_cs_mask,
698*4882a593Smuzhiyun 	},
699*4882a593Smuzhiyun 	/* User bits controller */
700*4882a593Smuzhiyun 	{
701*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
702*4882a593Smuzhiyun 		.name = "IEC958 Subcode Playback Default",
703*4882a593Smuzhiyun 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
704*4882a593Smuzhiyun 		.info = mchp_spdiftx_info,
705*4882a593Smuzhiyun 		.get = mchp_spdiftx_subcode_get,
706*4882a593Smuzhiyun 		.put = mchp_spdiftx_subcode_put,
707*4882a593Smuzhiyun 	},
708*4882a593Smuzhiyun };
709*4882a593Smuzhiyun 
mchp_spdiftx_dai_probe(struct snd_soc_dai * dai)710*4882a593Smuzhiyun static int mchp_spdiftx_dai_probe(struct snd_soc_dai *dai)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
713*4882a593Smuzhiyun 	int ret;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	snd_soc_dai_init_dma_data(dai, &dev->playback, NULL);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	ret = clk_prepare_enable(dev->pclk);
718*4882a593Smuzhiyun 	if (ret) {
719*4882a593Smuzhiyun 		dev_err(dev->dev,
720*4882a593Smuzhiyun 			"failed to enable the peripheral clock: %d\n", ret);
721*4882a593Smuzhiyun 		return ret;
722*4882a593Smuzhiyun 	}
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	/* Add controls */
725*4882a593Smuzhiyun 	snd_soc_add_dai_controls(dai, mchp_spdiftx_ctrls,
726*4882a593Smuzhiyun 				 ARRAY_SIZE(mchp_spdiftx_ctrls));
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	return 0;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
mchp_spdiftx_dai_remove(struct snd_soc_dai * dai)731*4882a593Smuzhiyun static int mchp_spdiftx_dai_remove(struct snd_soc_dai *dai)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev = snd_soc_dai_get_drvdata(dai);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	clk_disable_unprepare(dev->pclk);
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	return 0;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun static struct snd_soc_dai_driver mchp_spdiftx_dai = {
741*4882a593Smuzhiyun 	.name = "mchp-spdiftx",
742*4882a593Smuzhiyun 	.probe	= mchp_spdiftx_dai_probe,
743*4882a593Smuzhiyun 	.remove	= mchp_spdiftx_dai_remove,
744*4882a593Smuzhiyun 	.playback = {
745*4882a593Smuzhiyun 		.stream_name = "S/PDIF Playback",
746*4882a593Smuzhiyun 		.channels_min = 1,
747*4882a593Smuzhiyun 		.channels_max = 2,
748*4882a593Smuzhiyun 		.rates = MCHP_SPDIFTX_RATES,
749*4882a593Smuzhiyun 		.formats = MCHP_SPDIFTX_FORMATS,
750*4882a593Smuzhiyun 	},
751*4882a593Smuzhiyun 	.ops = &mchp_spdiftx_dai_ops,
752*4882a593Smuzhiyun };
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun static const struct snd_soc_component_driver mchp_spdiftx_component = {
755*4882a593Smuzhiyun 	.name		= "mchp-spdiftx",
756*4882a593Smuzhiyun };
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun static const struct of_device_id mchp_spdiftx_dt_ids[] = {
759*4882a593Smuzhiyun 	{
760*4882a593Smuzhiyun 		.compatible = "microchip,sama7g5-spdiftx",
761*4882a593Smuzhiyun 	},
762*4882a593Smuzhiyun 	{ /* sentinel */ }
763*4882a593Smuzhiyun };
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mchp_spdiftx_dt_ids);
mchp_spdiftx_probe(struct platform_device * pdev)766*4882a593Smuzhiyun static int mchp_spdiftx_probe(struct platform_device *pdev)
767*4882a593Smuzhiyun {
768*4882a593Smuzhiyun 	struct mchp_spdiftx_dev *dev;
769*4882a593Smuzhiyun 	struct resource *mem;
770*4882a593Smuzhiyun 	struct regmap *regmap;
771*4882a593Smuzhiyun 	void __iomem *base;
772*4882a593Smuzhiyun 	struct mchp_spdiftx_mixer_control *ctrl;
773*4882a593Smuzhiyun 	int irq;
774*4882a593Smuzhiyun 	int err;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	/* Get memory for driver data. */
777*4882a593Smuzhiyun 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
778*4882a593Smuzhiyun 	if (!dev)
779*4882a593Smuzhiyun 		return -ENOMEM;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	/* Map I/O registers. */
782*4882a593Smuzhiyun 	base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
783*4882a593Smuzhiyun 	if (IS_ERR(base))
784*4882a593Smuzhiyun 		return PTR_ERR(base);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	regmap = devm_regmap_init_mmio(&pdev->dev, base,
787*4882a593Smuzhiyun 				       &mchp_spdiftx_regmap_config);
788*4882a593Smuzhiyun 	if (IS_ERR(regmap))
789*4882a593Smuzhiyun 		return PTR_ERR(regmap);
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	/* Request IRQ */
792*4882a593Smuzhiyun 	irq = platform_get_irq(pdev, 0);
793*4882a593Smuzhiyun 	if (irq < 0)
794*4882a593Smuzhiyun 		return irq;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 	err = devm_request_irq(&pdev->dev, irq, mchp_spdiftx_interrupt, 0,
797*4882a593Smuzhiyun 			       dev_name(&pdev->dev), dev);
798*4882a593Smuzhiyun 	if (err)
799*4882a593Smuzhiyun 		return err;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	/* Get the peripheral clock */
802*4882a593Smuzhiyun 	dev->pclk = devm_clk_get(&pdev->dev, "pclk");
803*4882a593Smuzhiyun 	if (IS_ERR(dev->pclk)) {
804*4882a593Smuzhiyun 		err = PTR_ERR(dev->pclk);
805*4882a593Smuzhiyun 		dev_err(&pdev->dev,
806*4882a593Smuzhiyun 			"failed to get the peripheral clock: %d\n", err);
807*4882a593Smuzhiyun 		return err;
808*4882a593Smuzhiyun 	}
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	/* Get the generic clock */
811*4882a593Smuzhiyun 	dev->gclk = devm_clk_get(&pdev->dev, "gclk");
812*4882a593Smuzhiyun 	if (IS_ERR(dev->gclk)) {
813*4882a593Smuzhiyun 		err = PTR_ERR(dev->gclk);
814*4882a593Smuzhiyun 		dev_err(&pdev->dev,
815*4882a593Smuzhiyun 			"failed to get the PMC generic clock: %d\n", err);
816*4882a593Smuzhiyun 		return err;
817*4882a593Smuzhiyun 	}
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	ctrl = &dev->control;
820*4882a593Smuzhiyun 	spin_lock_init(&ctrl->lock);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	/* Init channel status */
823*4882a593Smuzhiyun 	ctrl->ch_stat[0] = IEC958_AES0_CON_NOT_COPYRIGHT |
824*4882a593Smuzhiyun 			   IEC958_AES0_CON_EMPHASIS_NONE;
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	dev->dev = &pdev->dev;
827*4882a593Smuzhiyun 	dev->regmap = regmap;
828*4882a593Smuzhiyun 	platform_set_drvdata(pdev, dev);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	dev->playback.addr = (dma_addr_t)mem->start + SPDIFTX_CDR;
831*4882a593Smuzhiyun 	dev->playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
834*4882a593Smuzhiyun 	if (err) {
835*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to register PMC: %d\n", err);
836*4882a593Smuzhiyun 		return err;
837*4882a593Smuzhiyun 	}
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	err = devm_snd_soc_register_component(&pdev->dev,
840*4882a593Smuzhiyun 					      &mchp_spdiftx_component,
841*4882a593Smuzhiyun 					      &mchp_spdiftx_dai, 1);
842*4882a593Smuzhiyun 	if (err) {
843*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to register component: %d\n", err);
844*4882a593Smuzhiyun 		return err;
845*4882a593Smuzhiyun 	}
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	return 0;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun static struct platform_driver mchp_spdiftx_driver = {
851*4882a593Smuzhiyun 	.probe	= mchp_spdiftx_probe,
852*4882a593Smuzhiyun 	.driver	= {
853*4882a593Smuzhiyun 		.name	= "mchp_spdiftx",
854*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(mchp_spdiftx_dt_ids),
855*4882a593Smuzhiyun 	},
856*4882a593Smuzhiyun };
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun module_platform_driver(mchp_spdiftx_driver);
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun MODULE_AUTHOR("Codrin Ciubotariu <codrin.ciubotariu@microchip.com>");
861*4882a593Smuzhiyun MODULE_DESCRIPTION("Microchip S/PDIF TX Controller Driver");
862*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
863