1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (C) 2020 Intel Corporation.
4//
5// Intel KeemBay Platform driver.
6//
7
8#include <linux/bitrev.h>
9#include <linux/clk.h>
10#include <linux/dma-mapping.h>
11#include <linux/io.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <sound/dmaengine_pcm.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include "kmb_platform.h"
20
21#define PERIODS_MIN		2
22#define PERIODS_MAX		48
23#define PERIOD_BYTES_MIN	4096
24#define BUFFER_BYTES_MAX	(PERIODS_MAX * PERIOD_BYTES_MIN)
25#define TDM_OPERATION		5
26#define I2S_OPERATION		0
27#define DATA_WIDTH_CONFIG_BIT	6
28#define TDM_CHANNEL_CONFIG_BIT	3
29
30static const struct snd_pcm_hardware kmb_pcm_hardware = {
31	.info = SNDRV_PCM_INFO_INTERLEAVED |
32		SNDRV_PCM_INFO_MMAP |
33		SNDRV_PCM_INFO_MMAP_VALID |
34		SNDRV_PCM_INFO_BATCH |
35		SNDRV_PCM_INFO_BLOCK_TRANSFER,
36	.rates = SNDRV_PCM_RATE_8000 |
37		 SNDRV_PCM_RATE_16000 |
38		 SNDRV_PCM_RATE_48000,
39	.rate_min = 8000,
40	.rate_max = 48000,
41	.formats = SNDRV_PCM_FMTBIT_S16_LE |
42		   SNDRV_PCM_FMTBIT_S24_LE |
43		   SNDRV_PCM_FMTBIT_S32_LE |
44		   SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
45	.channels_min = 2,
46	.channels_max = 2,
47	.buffer_bytes_max = BUFFER_BYTES_MAX,
48	.period_bytes_min = PERIOD_BYTES_MIN,
49	.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
50	.periods_min = PERIODS_MIN,
51	.periods_max = PERIODS_MAX,
52	.fifo_size = 16,
53};
54
55/*
56 * Convert to ADV7511 HDMI hardware format.
57 * ADV7511 HDMI chip need parity bit replaced by block start bit and
58 * with the preamble bits left out.
59 * ALSA IEC958 subframe format:
60 * bit 0-3  = preamble (0x8 = block start)
61 *     4-7  = AUX (=0)
62 *     8-27 = audio data (without AUX if 24bit sample)
63 *     28   = validity
64 *     29   = user data
65 *     30   = channel status
66 *     31   = parity
67 *
68 * ADV7511 IEC958 subframe format:
69 * bit 0-23  = audio data
70 *     24    = validity
71 *     25    = user data
72 *     26    = channel status
73 *     27    = block start
74 *     28-31 = 0
75 * MSB to LSB bit reverse by software as hardware not supporting it.
76 */
77static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime,
78				 struct kmb_i2s_info *kmb_i2s,
79				 unsigned int tx_ptr)
80{
81	u32(*buf)[2] = (void *)runtime->dma_area;
82	unsigned long temp;
83	u32 i, j, sample;
84
85	for (i = 0; i < kmb_i2s->fifo_th; i++) {
86		j = 0;
87		do {
88			temp = buf[tx_ptr][j];
89			/* Replace parity with block start*/
90			assign_bit(31, &temp, (BIT(3) & temp));
91			sample = bitrev32(temp);
92			buf[tx_ptr][j] = sample << 4;
93			j++;
94		} while (j < 2);
95		tx_ptr++;
96	}
97}
98
99static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
100				  struct snd_pcm_runtime *runtime,
101				  unsigned int tx_ptr, bool *period_elapsed)
102{
103	unsigned int period_pos = tx_ptr % runtime->period_size;
104	void __iomem *i2s_base = kmb_i2s->i2s_base;
105	void *buf = runtime->dma_area;
106	int i;
107
108	if (kmb_i2s->iec958_fmt)
109		hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr);
110
111	/* KMB i2s uses two separate L/R FIFO */
112	for (i = 0; i < kmb_i2s->fifo_th; i++) {
113		if (kmb_i2s->config.data_width == 16) {
114			writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
115			writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
116		} else {
117			writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
118			writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
119		}
120
121		period_pos++;
122
123		if (++tx_ptr >= runtime->buffer_size)
124			tx_ptr = 0;
125	}
126
127	*period_elapsed = period_pos >= runtime->period_size;
128
129	return tx_ptr;
130}
131
132static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s,
133				  struct snd_pcm_runtime *runtime,
134				  unsigned int rx_ptr, bool *period_elapsed)
135{
136	unsigned int period_pos = rx_ptr % runtime->period_size;
137	void __iomem *i2s_base = kmb_i2s->i2s_base;
138	int chan = kmb_i2s->config.chan_nr;
139	void *buf = runtime->dma_area;
140	int i, j;
141
142	/* KMB i2s uses two separate L/R FIFO */
143	for (i = 0; i < kmb_i2s->fifo_th; i++) {
144		for (j = 0; j < chan / 2; j++) {
145			if (kmb_i2s->config.data_width == 16) {
146				((u16 *)buf)[rx_ptr * chan + (j * 2)] =
147						readl(i2s_base + LRBR_LTHR(j));
148				((u16 *)buf)[rx_ptr * chan + ((j * 2) + 1)] =
149						readl(i2s_base + RRBR_RTHR(j));
150			} else {
151				((u32 *)buf)[rx_ptr * chan + (j * 2)] =
152						readl(i2s_base + LRBR_LTHR(j));
153				((u32 *)buf)[rx_ptr * chan + ((j * 2) + 1)] =
154						readl(i2s_base + RRBR_RTHR(j));
155			}
156		}
157		period_pos++;
158
159		if (++rx_ptr >= runtime->buffer_size)
160			rx_ptr = 0;
161	}
162
163	*period_elapsed = period_pos >= runtime->period_size;
164
165	return rx_ptr;
166}
167
168static inline void kmb_i2s_disable_channels(struct kmb_i2s_info *kmb_i2s,
169					    u32 stream)
170{
171	u32 i;
172
173	/* Disable all channels regardless of configuration*/
174	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
175		for (i = 0; i < MAX_ISR; i++)
176			writel(0, kmb_i2s->i2s_base + TER(i));
177	} else {
178		for (i = 0; i < MAX_ISR; i++)
179			writel(0, kmb_i2s->i2s_base + RER(i));
180	}
181}
182
183static inline void kmb_i2s_clear_irqs(struct kmb_i2s_info *kmb_i2s, u32 stream)
184{
185	struct i2s_clk_config_data *config = &kmb_i2s->config;
186	u32 i;
187
188	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
189		for (i = 0; i < config->chan_nr / 2; i++)
190			readl(kmb_i2s->i2s_base + TOR(i));
191	} else {
192		for (i = 0; i < config->chan_nr / 2; i++)
193			readl(kmb_i2s->i2s_base + ROR(i));
194	}
195}
196
197static inline void kmb_i2s_irq_trigger(struct kmb_i2s_info *kmb_i2s,
198				       u32 stream, int chan_nr, bool trigger)
199{
200	u32 i, irq;
201	u32 flag;
202
203	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
204		flag = TX_INT_FLAG;
205	else
206		flag = RX_INT_FLAG;
207
208	for (i = 0; i < chan_nr / 2; i++) {
209		irq = readl(kmb_i2s->i2s_base + IMR(i));
210
211		if (trigger)
212			irq = irq & ~flag;
213		else
214			irq = irq | flag;
215
216		writel(irq, kmb_i2s->i2s_base + IMR(i));
217	}
218}
219
220static void kmb_pcm_operation(struct kmb_i2s_info *kmb_i2s, bool playback)
221{
222	struct snd_pcm_substream *substream;
223	bool period_elapsed;
224	unsigned int new_ptr;
225	unsigned int ptr;
226
227	if (playback)
228		substream = kmb_i2s->tx_substream;
229	else
230		substream = kmb_i2s->rx_substream;
231
232	if (!substream || !snd_pcm_running(substream))
233		return;
234
235	if (playback) {
236		ptr = kmb_i2s->tx_ptr;
237		new_ptr = kmb_pcm_tx_fn(kmb_i2s, substream->runtime,
238					ptr, &period_elapsed);
239		cmpxchg(&kmb_i2s->tx_ptr, ptr, new_ptr);
240	} else {
241		ptr = kmb_i2s->rx_ptr;
242		new_ptr = kmb_pcm_rx_fn(kmb_i2s, substream->runtime,
243					ptr, &period_elapsed);
244		cmpxchg(&kmb_i2s->rx_ptr, ptr, new_ptr);
245	}
246
247	if (period_elapsed)
248		snd_pcm_period_elapsed(substream);
249}
250
251static int kmb_pcm_open(struct snd_soc_component *component,
252			struct snd_pcm_substream *substream)
253{
254	struct snd_pcm_runtime *runtime = substream->runtime;
255	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
256	struct kmb_i2s_info *kmb_i2s;
257
258	kmb_i2s = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
259	snd_soc_set_runtime_hwparams(substream, &kmb_pcm_hardware);
260	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
261	runtime->private_data = kmb_i2s;
262
263	return 0;
264}
265
266static int kmb_pcm_trigger(struct snd_soc_component *component,
267			   struct snd_pcm_substream *substream, int cmd)
268{
269	struct snd_pcm_runtime *runtime = substream->runtime;
270	struct kmb_i2s_info *kmb_i2s = runtime->private_data;
271
272	switch (cmd) {
273	case SNDRV_PCM_TRIGGER_START:
274		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
275			kmb_i2s->tx_ptr = 0;
276			kmb_i2s->tx_substream = substream;
277		} else {
278			kmb_i2s->rx_ptr = 0;
279			kmb_i2s->rx_substream = substream;
280		}
281		break;
282	case SNDRV_PCM_TRIGGER_STOP:
283		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
284			kmb_i2s->tx_substream = NULL;
285		else
286			kmb_i2s->rx_substream = NULL;
287		kmb_i2s->iec958_fmt = false;
288		break;
289	default:
290		return -EINVAL;
291	}
292
293	return 0;
294}
295
296static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id)
297{
298	struct kmb_i2s_info *kmb_i2s = dev_id;
299	struct i2s_clk_config_data *config = &kmb_i2s->config;
300	irqreturn_t ret = IRQ_NONE;
301	u32 tx_enabled = 0;
302	u32 isr[4];
303	int i;
304
305	for (i = 0; i < config->chan_nr / 2; i++)
306		isr[i] = readl(kmb_i2s->i2s_base + ISR(i));
307
308	kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
309	kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);
310	/* Only check TX interrupt if TX is active */
311	tx_enabled = readl(kmb_i2s->i2s_base + ITER);
312
313	/*
314	 * Data available. Retrieve samples from FIFO
315	 */
316
317	/*
318	 * 8 channel audio will have isr[0..2] triggered,
319	 * reading the specific isr based on the audio configuration,
320	 * to avoid reading the buffers too early.
321	 */
322	switch (config->chan_nr) {
323	case 2:
324		if (isr[0] & ISR_RXDA)
325			kmb_pcm_operation(kmb_i2s, false);
326		ret = IRQ_HANDLED;
327		break;
328	case 4:
329		if (isr[1] & ISR_RXDA)
330			kmb_pcm_operation(kmb_i2s, false);
331		ret = IRQ_HANDLED;
332		break;
333	case 8:
334		if (isr[3] & ISR_RXDA)
335			kmb_pcm_operation(kmb_i2s, false);
336		ret = IRQ_HANDLED;
337		break;
338	}
339
340	for (i = 0; i < config->chan_nr / 2; i++) {
341		/*
342		 * Check if TX fifo is empty. If empty fill FIFO with samples
343		 */
344		if ((isr[i] & ISR_TXFE) && tx_enabled) {
345			kmb_pcm_operation(kmb_i2s, true);
346			ret = IRQ_HANDLED;
347		}
348
349		/* Error Handling: TX */
350		if (isr[i] & ISR_TXFO) {
351			dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i);
352			ret = IRQ_HANDLED;
353		}
354		/* Error Handling: RX */
355		if (isr[i] & ISR_RXFO) {
356			dev_dbg(kmb_i2s->dev, "RX overrun (ch_id=%d)\n", i);
357			ret = IRQ_HANDLED;
358		}
359	}
360
361	return ret;
362}
363
364static int kmb_platform_pcm_new(struct snd_soc_component *component,
365				struct snd_soc_pcm_runtime *soc_runtime)
366{
367	size_t size = kmb_pcm_hardware.buffer_bytes_max;
368	/* Use SNDRV_DMA_TYPE_CONTINUOUS as KMB doesn't use PCI sg buffer */
369	snd_pcm_set_managed_buffer_all(soc_runtime->pcm,
370				       SNDRV_DMA_TYPE_CONTINUOUS,
371				       NULL, size, size);
372	return 0;
373}
374
375static snd_pcm_uframes_t kmb_pcm_pointer(struct snd_soc_component *component,
376					 struct snd_pcm_substream *substream)
377{
378	struct snd_pcm_runtime *runtime = substream->runtime;
379	struct kmb_i2s_info *kmb_i2s = runtime->private_data;
380	snd_pcm_uframes_t pos;
381
382	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
383		pos = kmb_i2s->tx_ptr;
384	else
385		pos = kmb_i2s->rx_ptr;
386
387	return pos < runtime->buffer_size ? pos : 0;
388}
389
390static const struct snd_soc_component_driver kmb_component = {
391	.name			= "kmb",
392	.pcm_construct		= kmb_platform_pcm_new,
393	.open			= kmb_pcm_open,
394	.trigger		= kmb_pcm_trigger,
395	.pointer		= kmb_pcm_pointer,
396	.legacy_dai_naming	= 1,
397};
398
399static const struct snd_soc_component_driver kmb_component_dma = {
400	.name			= "kmb",
401	.legacy_dai_naming	= 1,
402};
403
404static int kmb_probe(struct snd_soc_dai *cpu_dai)
405{
406	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
407
408	if (kmb_i2s->use_pio)
409		return 0;
410
411	snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data,
412				  &kmb_i2s->capture_dma_data);
413
414	return 0;
415}
416
417static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
418{
419	u32 dma_reg;
420
421	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
422	/* Enable DMA handshake for stream */
423	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
424		dma_reg |= I2S_DMAEN_TXBLOCK;
425	else
426		dma_reg |= I2S_DMAEN_RXBLOCK;
427
428	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
429}
430
431static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
432{
433	u32 dma_reg;
434
435	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
436	/* Disable DMA handshake for stream */
437	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
438		dma_reg &= ~I2S_DMAEN_TXBLOCK;
439		writel(1, kmb_i2s->i2s_base + I2S_RTXDMA);
440	} else {
441		dma_reg &= ~I2S_DMAEN_RXBLOCK;
442		writel(1, kmb_i2s->i2s_base + I2S_RRXDMA);
443	}
444	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
445}
446
447static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
448			  struct snd_pcm_substream *substream)
449{
450	struct i2s_clk_config_data *config = &kmb_i2s->config;
451
452	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
453	writel(1, kmb_i2s->i2s_base + IER);
454
455	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
456		writel(1, kmb_i2s->i2s_base + ITER);
457	else
458		writel(1, kmb_i2s->i2s_base + IRER);
459
460	if (kmb_i2s->use_pio)
461		kmb_i2s_irq_trigger(kmb_i2s, substream->stream,
462				    config->chan_nr, true);
463	else
464		kmb_i2s_enable_dma(kmb_i2s, substream->stream);
465
466	if (kmb_i2s->clock_provider)
467		writel(1, kmb_i2s->i2s_base + CER);
468	else
469		writel(0, kmb_i2s->i2s_base + CER);
470}
471
472static void kmb_i2s_stop(struct kmb_i2s_info *kmb_i2s,
473			 struct snd_pcm_substream *substream)
474{
475	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
476	kmb_i2s_clear_irqs(kmb_i2s, substream->stream);
477
478	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
479		writel(0, kmb_i2s->i2s_base + ITER);
480	else
481		writel(0, kmb_i2s->i2s_base + IRER);
482
483	kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
484
485	if (!kmb_i2s->active) {
486		writel(0, kmb_i2s->i2s_base + CER);
487		writel(0, kmb_i2s->i2s_base + IER);
488	}
489}
490
491static void kmb_disable_clk(void *clk)
492{
493	clk_disable_unprepare(clk);
494}
495
496static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
497{
498	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
499	int ret;
500
501	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
502	case SND_SOC_DAIFMT_BC_FC:
503		kmb_i2s->clock_provider = false;
504		ret = 0;
505		break;
506	case SND_SOC_DAIFMT_BP_FP:
507		writel(CLOCK_PROVIDER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0);
508
509		ret = clk_prepare_enable(kmb_i2s->clk_i2s);
510		if (ret < 0)
511			return ret;
512
513		ret = devm_add_action_or_reset(kmb_i2s->dev, kmb_disable_clk,
514					       kmb_i2s->clk_i2s);
515		if (ret)
516			return ret;
517
518		kmb_i2s->clock_provider = true;
519		break;
520	default:
521		return -EINVAL;
522	}
523
524	return ret;
525}
526
527static int kmb_dai_trigger(struct snd_pcm_substream *substream,
528			   int cmd, struct snd_soc_dai *cpu_dai)
529{
530	struct kmb_i2s_info *kmb_i2s  = snd_soc_dai_get_drvdata(cpu_dai);
531
532	switch (cmd) {
533	case SNDRV_PCM_TRIGGER_START:
534		/* Keep track of i2s activity before turn off
535		 * the i2s interface
536		 */
537		kmb_i2s->active++;
538		kmb_i2s_start(kmb_i2s, substream);
539		break;
540	case SNDRV_PCM_TRIGGER_STOP:
541		kmb_i2s->active--;
542		if (kmb_i2s->use_pio)
543			kmb_i2s_stop(kmb_i2s, substream);
544		break;
545	default:
546		return  -EINVAL;
547	}
548
549	return 0;
550}
551
552static void kmb_i2s_config(struct kmb_i2s_info *kmb_i2s, int stream)
553{
554	struct i2s_clk_config_data *config = &kmb_i2s->config;
555	u32 ch_reg;
556
557	kmb_i2s_disable_channels(kmb_i2s, stream);
558
559	for (ch_reg = 0; ch_reg < config->chan_nr / 2; ch_reg++) {
560		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
561			writel(kmb_i2s->xfer_resolution,
562			       kmb_i2s->i2s_base + TCR(ch_reg));
563
564			writel(kmb_i2s->fifo_th - 1,
565			       kmb_i2s->i2s_base + TFCR(ch_reg));
566
567			writel(1, kmb_i2s->i2s_base + TER(ch_reg));
568		} else {
569			writel(kmb_i2s->xfer_resolution,
570			       kmb_i2s->i2s_base + RCR(ch_reg));
571
572			writel(kmb_i2s->fifo_th - 1,
573			       kmb_i2s->i2s_base + RFCR(ch_reg));
574
575			writel(1, kmb_i2s->i2s_base + RER(ch_reg));
576		}
577	}
578}
579
580static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
581			     struct snd_pcm_hw_params *hw_params,
582			     struct snd_soc_dai *cpu_dai)
583{
584	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
585	struct i2s_clk_config_data *config = &kmb_i2s->config;
586	u32 write_val;
587	int ret;
588
589	switch (params_format(hw_params)) {
590	case SNDRV_PCM_FORMAT_S16_LE:
591		config->data_width = 16;
592		kmb_i2s->ccr = 0x00;
593		kmb_i2s->xfer_resolution = 0x02;
594		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
595		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
596		break;
597	case SNDRV_PCM_FORMAT_S24_LE:
598		config->data_width = 32;
599		kmb_i2s->ccr = 0x14;
600		kmb_i2s->xfer_resolution = 0x05;
601		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
602		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
603		break;
604	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
605		kmb_i2s->iec958_fmt = true;
606		fallthrough;
607	case SNDRV_PCM_FORMAT_S32_LE:
608		config->data_width = 32;
609		kmb_i2s->ccr = 0x10;
610		kmb_i2s->xfer_resolution = 0x05;
611		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
612		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
613		break;
614	default:
615		dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt");
616		return -EINVAL;
617	}
618
619	config->chan_nr = params_channels(hw_params);
620
621	switch (config->chan_nr) {
622	case 8:
623	case 4:
624		/*
625		 * Platform is not capable of providing clocks for
626		 * multi channel audio
627		 */
628		if (kmb_i2s->clock_provider)
629			return -EINVAL;
630
631		write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) |
632				(config->data_width << DATA_WIDTH_CONFIG_BIT) |
633				TDM_OPERATION;
634
635		writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0);
636		break;
637	case 2:
638		/*
639		 * Platform is only capable of providing clocks need for
640		 * 2 channel master mode
641		 */
642		if (!(kmb_i2s->clock_provider))
643			return -EINVAL;
644
645		write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) |
646				(config->data_width << DATA_WIDTH_CONFIG_BIT) |
647				CLOCK_PROVIDER_MODE | I2S_OPERATION;
648
649		writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0);
650		break;
651	default:
652		dev_dbg(kmb_i2s->dev, "channel not supported\n");
653		return -EINVAL;
654	}
655
656	kmb_i2s_config(kmb_i2s, substream->stream);
657
658	writel(kmb_i2s->ccr, kmb_i2s->i2s_base + CCR);
659
660	config->sample_rate = params_rate(hw_params);
661
662	if (kmb_i2s->clock_provider) {
663		/* Only 2 ch supported in Master mode */
664		u32 bitclk = config->sample_rate * config->data_width * 2;
665
666		ret = clk_set_rate(kmb_i2s->clk_i2s, bitclk);
667		if (ret) {
668			dev_err(kmb_i2s->dev,
669				"Can't set I2S clock rate: %d\n", ret);
670			return ret;
671		}
672	}
673
674	return 0;
675}
676
677static int kmb_dai_prepare(struct snd_pcm_substream *substream,
678			   struct snd_soc_dai *cpu_dai)
679{
680	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
681
682	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
683		writel(1, kmb_i2s->i2s_base + TXFFR);
684	else
685		writel(1, kmb_i2s->i2s_base + RXFFR);
686
687	return 0;
688}
689
690static int kmb_dai_startup(struct snd_pcm_substream *substream,
691			   struct snd_soc_dai *cpu_dai)
692{
693	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
694	struct snd_dmaengine_dai_dma_data *dma_data;
695
696	if (kmb_i2s->use_pio)
697		return 0;
698
699	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
700		dma_data = &kmb_i2s->play_dma_data;
701	else
702		dma_data = &kmb_i2s->capture_dma_data;
703
704	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
705
706	return 0;
707}
708
709static int kmb_dai_hw_free(struct snd_pcm_substream *substream,
710			   struct snd_soc_dai *cpu_dai)
711{
712	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
713	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
714	if (kmb_i2s->use_pio)
715		kmb_i2s_clear_irqs(kmb_i2s, substream->stream);
716
717	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
718		writel(0, kmb_i2s->i2s_base + ITER);
719	else
720		writel(0, kmb_i2s->i2s_base + IRER);
721
722	if (kmb_i2s->use_pio)
723		kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
724	else
725		kmb_i2s_disable_dma(kmb_i2s, substream->stream);
726
727	if (!kmb_i2s->active) {
728		writel(0, kmb_i2s->i2s_base + CER);
729		writel(0, kmb_i2s->i2s_base + IER);
730	}
731
732	return 0;
733}
734
735static const struct snd_soc_dai_ops kmb_dai_ops = {
736	.probe		= kmb_probe,
737	.startup	= kmb_dai_startup,
738	.trigger	= kmb_dai_trigger,
739	.hw_params	= kmb_dai_hw_params,
740	.hw_free	= kmb_dai_hw_free,
741	.prepare	= kmb_dai_prepare,
742	.set_fmt	= kmb_set_dai_fmt,
743};
744
745static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = {
746	{
747		.name = "intel_kmb_hdmi_i2s",
748		.playback = {
749			.channels_min = 2,
750			.channels_max = 2,
751			.rates = SNDRV_PCM_RATE_48000,
752			.rate_min = 48000,
753			.rate_max = 48000,
754			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
755				    SNDRV_PCM_FMTBIT_S24_LE |
756				    SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
757		},
758		.ops = &kmb_dai_ops,
759	},
760};
761
762static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
763	{
764		.name = "intel_kmb_i2s",
765		.playback = {
766			.channels_min = 2,
767			.channels_max = 2,
768			.rates = SNDRV_PCM_RATE_8000 |
769				 SNDRV_PCM_RATE_16000 |
770				 SNDRV_PCM_RATE_48000,
771			.rate_min = 8000,
772			.rate_max = 48000,
773			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
774				    SNDRV_PCM_FMTBIT_S24_LE |
775				    SNDRV_PCM_FMTBIT_S16_LE),
776		},
777		.capture = {
778			.channels_min = 2,
779			.channels_max = 2,
780			.rates = SNDRV_PCM_RATE_8000 |
781				 SNDRV_PCM_RATE_16000 |
782				 SNDRV_PCM_RATE_48000,
783			.rate_min = 8000,
784			.rate_max = 48000,
785			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
786				    SNDRV_PCM_FMTBIT_S24_LE |
787				    SNDRV_PCM_FMTBIT_S16_LE),
788		},
789		.ops = &kmb_dai_ops,
790	},
791};
792
793static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = {
794	{
795		.name = "intel_kmb_tdm",
796		.capture = {
797			.channels_min = 4,
798			.channels_max = 8,
799			.rates = SNDRV_PCM_RATE_8000 |
800				 SNDRV_PCM_RATE_16000 |
801				 SNDRV_PCM_RATE_48000,
802			.rate_min = 8000,
803			.rate_max = 48000,
804			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
805				    SNDRV_PCM_FMTBIT_S24_LE |
806				    SNDRV_PCM_FMTBIT_S16_LE),
807		},
808		.ops = &kmb_dai_ops,
809	},
810};
811
812static const struct of_device_id kmb_plat_of_match[] = {
813	{ .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai},
814	{ .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai},
815	{ .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai},
816	{}
817};
818
819static int kmb_plat_dai_probe(struct platform_device *pdev)
820{
821	struct device_node *np = pdev->dev.of_node;
822	struct snd_soc_dai_driver *kmb_i2s_dai;
823	const struct of_device_id *match;
824	struct device *dev = &pdev->dev;
825	struct kmb_i2s_info *kmb_i2s;
826	struct resource *res;
827	int ret, irq;
828	u32 comp1_reg;
829
830	kmb_i2s = devm_kzalloc(dev, sizeof(*kmb_i2s), GFP_KERNEL);
831	if (!kmb_i2s)
832		return -ENOMEM;
833
834	kmb_i2s_dai = devm_kzalloc(dev, sizeof(*kmb_i2s_dai), GFP_KERNEL);
835	if (!kmb_i2s_dai)
836		return -ENOMEM;
837
838	match = of_match_device(kmb_plat_of_match, &pdev->dev);
839	if (!match) {
840		dev_err(&pdev->dev, "Error: No device match found\n");
841		return -ENODEV;
842	}
843	kmb_i2s_dai = (struct snd_soc_dai_driver *) match->data;
844
845	/* Prepare the related clocks */
846	kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk");
847	if (IS_ERR(kmb_i2s->clk_apb)) {
848		dev_err(dev, "Failed to get apb clock\n");
849		return PTR_ERR(kmb_i2s->clk_apb);
850	}
851
852	ret = clk_prepare_enable(kmb_i2s->clk_apb);
853	if (ret < 0)
854		return ret;
855
856	ret = devm_add_action_or_reset(dev, kmb_disable_clk, kmb_i2s->clk_apb);
857	if (ret) {
858		dev_err(dev, "Failed to add clk_apb reset action\n");
859		return ret;
860	}
861
862	kmb_i2s->clk_i2s = devm_clk_get(dev, "osc");
863	if (IS_ERR(kmb_i2s->clk_i2s)) {
864		dev_err(dev, "Failed to get osc clock\n");
865		return PTR_ERR(kmb_i2s->clk_i2s);
866	}
867
868	kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
869	if (IS_ERR(kmb_i2s->i2s_base))
870		return PTR_ERR(kmb_i2s->i2s_base);
871
872	kmb_i2s->pss_base = devm_platform_ioremap_resource(pdev, 1);
873	if (IS_ERR(kmb_i2s->pss_base))
874		return PTR_ERR(kmb_i2s->pss_base);
875
876	kmb_i2s->dev = &pdev->dev;
877
878	comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1);
879
880	kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2;
881
882	kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas"));
883
884	if (kmb_i2s->use_pio) {
885		irq = platform_get_irq_optional(pdev, 0);
886		if (irq > 0) {
887			ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
888					       pdev->name, kmb_i2s);
889			if (ret < 0) {
890				dev_err(dev, "failed to request irq\n");
891				return ret;
892			}
893		}
894		ret = devm_snd_soc_register_component(dev, &kmb_component,
895						      kmb_i2s_dai, 1);
896	} else {
897		kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA;
898		kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA;
899		ret = snd_dmaengine_pcm_register(&pdev->dev,
900						 NULL, 0);
901		if (ret) {
902			dev_err(&pdev->dev, "could not register dmaengine: %d\n",
903				ret);
904			return ret;
905		}
906		ret = devm_snd_soc_register_component(dev, &kmb_component_dma,
907						      kmb_i2s_dai, 1);
908	}
909
910	if (ret) {
911		dev_err(dev, "not able to register dai\n");
912		return ret;
913	}
914
915	/* To ensure none of the channels are enabled at boot up */
916	kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
917	kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);
918
919	dev_set_drvdata(dev, kmb_i2s);
920
921	return ret;
922}
923
924static struct platform_driver kmb_plat_dai_driver = {
925	.driver		= {
926		.name		= "kmb-plat-dai",
927		.of_match_table = kmb_plat_of_match,
928	},
929	.probe		= kmb_plat_dai_probe,
930};
931
932module_platform_driver(kmb_plat_dai_driver);
933
934MODULE_DESCRIPTION("ASoC Intel KeemBay Platform driver");
935MODULE_AUTHOR("Sia Jee Heng <jee.heng.sia@intel.com>");
936MODULE_AUTHOR("Sit, Michael Wei Hong <michael.wei.hong.sit@intel.com>");
937MODULE_LICENSE("GPL v2");
938MODULE_ALIAS("platform:kmb_platform");
939