kmb_platform.c 23.6 KB
Newer Older
1 2 3 4 5 6 7
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright (C) 2020 Intel Corporation.
//
// Intel KeemBay Platform driver.
//

8
#include <linux/bitrev.h>
9
#include <linux/clk.h>
10
#include <linux/dma-mapping.h>
11 12
#include <linux/io.h>
#include <linux/module.h>
13 14
#include <linux/of.h>
#include <linux/of_device.h>
15
#include <sound/dmaengine_pcm.h>
16 17 18 19 20 21 22 23 24
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "kmb_platform.h"

#define PERIODS_MIN		2
#define PERIODS_MAX		48
#define PERIOD_BYTES_MIN	4096
#define BUFFER_BYTES_MAX	(PERIODS_MAX * PERIOD_BYTES_MIN)
25
#define TDM_OPERATION		5
26 27 28 29 30 31 32 33 34 35
#define I2S_OPERATION		0
#define DATA_WIDTH_CONFIG_BIT	6
#define TDM_CHANNEL_CONFIG_BIT	3

static const struct snd_pcm_hardware kmb_pcm_hardware = {
	.info = SNDRV_PCM_INFO_INTERLEAVED |
		SNDRV_PCM_INFO_MMAP |
		SNDRV_PCM_INFO_MMAP_VALID |
		SNDRV_PCM_INFO_BATCH |
		SNDRV_PCM_INFO_BLOCK_TRANSFER,
36 37 38 39
	.rates = SNDRV_PCM_RATE_8000 |
		 SNDRV_PCM_RATE_16000 |
		 SNDRV_PCM_RATE_48000,
	.rate_min = 8000,
40 41 42
	.rate_max = 48000,
	.formats = SNDRV_PCM_FMTBIT_S16_LE |
		   SNDRV_PCM_FMTBIT_S24_LE |
43 44
		   SNDRV_PCM_FMTBIT_S32_LE |
		   SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
45 46 47 48 49 50 51 52 53 54
	.channels_min = 2,
	.channels_max = 2,
	.buffer_bytes_max = BUFFER_BYTES_MAX,
	.period_bytes_min = PERIOD_BYTES_MIN,
	.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
	.periods_min = PERIODS_MIN,
	.periods_max = PERIODS_MAX,
	.fifo_size = 16,
};

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/*
 * Convert to ADV7511 HDMI hardware format.
 * ADV7511 HDMI chip need parity bit replaced by block start bit and
 * with the preamble bits left out.
 * ALSA IEC958 subframe format:
 * bit 0-3  = preamble (0x8 = block start)
 *     4-7  = AUX (=0)
 *     8-27 = audio data (without AUX if 24bit sample)
 *     28   = validity
 *     29   = user data
 *     30   = channel status
 *     31   = parity
 *
 * ADV7511 IEC958 subframe format:
 * bit 0-23  = audio data
 *     24    = validity
 *     25    = user data
 *     26    = channel status
 *     27    = block start
 *     28-31 = 0
 * MSB to LSB bit reverse by software as hardware not supporting it.
 */
static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime,
				 struct kmb_i2s_info *kmb_i2s,
				 unsigned int tx_ptr)
{
	u32(*buf)[2] = (void *)runtime->dma_area;
	unsigned long temp;
	u32 i, j, sample;

	for (i = 0; i < kmb_i2s->fifo_th; i++) {
		j = 0;
		do {
			temp = buf[tx_ptr][j];
			/* Replace parity with block start*/
			assign_bit(31, &temp, (BIT(3) & temp));
			sample = bitrev32(temp);
			buf[tx_ptr][j] = sample << 4;
			j++;
		} while (j < 2);
		tx_ptr++;
	}
}

99 100 101 102 103 104 105 106 107
static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
				  struct snd_pcm_runtime *runtime,
				  unsigned int tx_ptr, bool *period_elapsed)
{
	unsigned int period_pos = tx_ptr % runtime->period_size;
	void __iomem *i2s_base = kmb_i2s->i2s_base;
	void *buf = runtime->dma_area;
	int i;

108 109 110
	if (kmb_i2s->iec958_fmt)
		hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr);

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
	/* KMB i2s uses two separate L/R FIFO */
	for (i = 0; i < kmb_i2s->fifo_th; i++) {
		if (kmb_i2s->config.data_width == 16) {
			writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
			writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
		} else {
			writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
			writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
		}

		period_pos++;

		if (++tx_ptr >= runtime->buffer_size)
			tx_ptr = 0;
	}

	*period_elapsed = period_pos >= runtime->period_size;

	return tx_ptr;
}

static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s,
				  struct snd_pcm_runtime *runtime,
				  unsigned int rx_ptr, bool *period_elapsed)
{
	unsigned int period_pos = rx_ptr % runtime->period_size;
	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 143

	/* KMB i2s uses two separate L/R FIFO */
	for (i = 0; i < kmb_i2s->fifo_th; i++) {
144 145 146 147 148 149 150 151 152 153 154 155
		for (j = 0; j < chan / 2; j++) {
			if (kmb_i2s->config.data_width == 16) {
				((u16 *)buf)[rx_ptr * chan + (j * 2)] =
						readl(i2s_base + LRBR_LTHR(j));
				((u16 *)buf)[rx_ptr * chan + ((j * 2) + 1)] =
						readl(i2s_base + RRBR_RTHR(j));
			} else {
				((u32 *)buf)[rx_ptr * chan + (j * 2)] =
						readl(i2s_base + LRBR_LTHR(j));
				((u32 *)buf)[rx_ptr * chan + ((j * 2) + 1)] =
						readl(i2s_base + RRBR_RTHR(j));
			}
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
		}
		period_pos++;

		if (++rx_ptr >= runtime->buffer_size)
			rx_ptr = 0;
	}

	*period_elapsed = period_pos >= runtime->period_size;

	return rx_ptr;
}

static inline void kmb_i2s_disable_channels(struct kmb_i2s_info *kmb_i2s,
					    u32 stream)
{
	u32 i;

173
	/* Disable all channels regardless of configuration*/
174
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
175
		for (i = 0; i < MAX_ISR; i++)
176 177
			writel(0, kmb_i2s->i2s_base + TER(i));
	} else {
178
		for (i = 0; i < MAX_ISR; i++)
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
			writel(0, kmb_i2s->i2s_base + RER(i));
	}
}

static inline void kmb_i2s_clear_irqs(struct kmb_i2s_info *kmb_i2s, u32 stream)
{
	struct i2s_clk_config_data *config = &kmb_i2s->config;
	u32 i;

	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		for (i = 0; i < config->chan_nr / 2; i++)
			readl(kmb_i2s->i2s_base + TOR(i));
	} else {
		for (i = 0; i < config->chan_nr / 2; i++)
			readl(kmb_i2s->i2s_base + ROR(i));
	}
}

static inline void kmb_i2s_irq_trigger(struct kmb_i2s_info *kmb_i2s,
				       u32 stream, int chan_nr, bool trigger)
{
	u32 i, irq;
	u32 flag;

	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		flag = TX_INT_FLAG;
	else
		flag = RX_INT_FLAG;

	for (i = 0; i < chan_nr / 2; i++) {
		irq = readl(kmb_i2s->i2s_base + IMR(i));

		if (trigger)
			irq = irq & ~flag;
		else
			irq = irq | flag;

		writel(irq, kmb_i2s->i2s_base + IMR(i));
	}
}

static void kmb_pcm_operation(struct kmb_i2s_info *kmb_i2s, bool playback)
{
	struct snd_pcm_substream *substream;
	bool period_elapsed;
	unsigned int new_ptr;
	unsigned int ptr;

	if (playback)
		substream = kmb_i2s->tx_substream;
	else
		substream = kmb_i2s->rx_substream;

	if (!substream || !snd_pcm_running(substream))
		return;

	if (playback) {
		ptr = kmb_i2s->tx_ptr;
		new_ptr = kmb_pcm_tx_fn(kmb_i2s, substream->runtime,
					ptr, &period_elapsed);
		cmpxchg(&kmb_i2s->tx_ptr, ptr, new_ptr);
	} else {
		ptr = kmb_i2s->rx_ptr;
		new_ptr = kmb_pcm_rx_fn(kmb_i2s, substream->runtime,
					ptr, &period_elapsed);
		cmpxchg(&kmb_i2s->rx_ptr, ptr, new_ptr);
	}

	if (period_elapsed)
		snd_pcm_period_elapsed(substream);
}

static int kmb_pcm_open(struct snd_soc_component *component,
			struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
255
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
	struct kmb_i2s_info *kmb_i2s;

	kmb_i2s = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
	snd_soc_set_runtime_hwparams(substream, &kmb_pcm_hardware);
	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
	runtime->private_data = kmb_i2s;

	return 0;
}

static int kmb_pcm_trigger(struct snd_soc_component *component,
			   struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct kmb_i2s_info *kmb_i2s = runtime->private_data;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			kmb_i2s->tx_ptr = 0;
			kmb_i2s->tx_substream = substream;
		} else {
			kmb_i2s->rx_ptr = 0;
			kmb_i2s->rx_substream = substream;
		}
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			kmb_i2s->tx_substream = NULL;
		else
			kmb_i2s->rx_substream = NULL;
287
		kmb_i2s->iec958_fmt = false;
288 289 290 291 292 293 294 295 296 297 298 299 300
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id)
{
	struct kmb_i2s_info *kmb_i2s = dev_id;
	struct i2s_clk_config_data *config = &kmb_i2s->config;
	irqreturn_t ret = IRQ_NONE;
301
	u32 tx_enabled = 0;
302 303 304 305 306 307 308 309
	u32 isr[4];
	int i;

	for (i = 0; i < config->chan_nr / 2; i++)
		isr[i] = readl(kmb_i2s->i2s_base + ISR(i));

	kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
	kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
	/* Only check TX interrupt if TX is active */
	tx_enabled = readl(kmb_i2s->i2s_base + ITER);

	/*
	 * Data available. Retrieve samples from FIFO
	 */

	/*
	 * 8 channel audio will have isr[0..2] triggered,
	 * reading the specific isr based on the audio configuration,
	 * to avoid reading the buffers too early.
	 */
	switch (config->chan_nr) {
	case 2:
		if (isr[0] & ISR_RXDA)
			kmb_pcm_operation(kmb_i2s, false);
		ret = IRQ_HANDLED;
		break;
	case 4:
		if (isr[1] & ISR_RXDA)
			kmb_pcm_operation(kmb_i2s, false);
		ret = IRQ_HANDLED;
		break;
	case 8:
		if (isr[3] & ISR_RXDA)
			kmb_pcm_operation(kmb_i2s, false);
		ret = IRQ_HANDLED;
		break;
	}
339 340 341 342 343

	for (i = 0; i < config->chan_nr / 2; i++) {
		/*
		 * Check if TX fifo is empty. If empty fill FIFO with samples
		 */
344
		if ((isr[i] & ISR_TXFE) && tx_enabled) {
345 346 347
			kmb_pcm_operation(kmb_i2s, true);
			ret = IRQ_HANDLED;
		}
348

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		/* Error Handling: TX */
		if (isr[i] & ISR_TXFO) {
			dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i);
			ret = IRQ_HANDLED;
		}
		/* Error Handling: RX */
		if (isr[i] & ISR_RXFO) {
			dev_dbg(kmb_i2s->dev, "RX overrun (ch_id=%d)\n", i);
			ret = IRQ_HANDLED;
		}
	}

	return ret;
}

static int kmb_platform_pcm_new(struct snd_soc_component *component,
				struct snd_soc_pcm_runtime *soc_runtime)
{
	size_t size = kmb_pcm_hardware.buffer_bytes_max;
	/* Use SNDRV_DMA_TYPE_CONTINUOUS as KMB doesn't use PCI sg buffer */
	snd_pcm_set_managed_buffer_all(soc_runtime->pcm,
				       SNDRV_DMA_TYPE_CONTINUOUS,
				       NULL, size, size);
	return 0;
}

static snd_pcm_uframes_t kmb_pcm_pointer(struct snd_soc_component *component,
					 struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct kmb_i2s_info *kmb_i2s = runtime->private_data;
	snd_pcm_uframes_t pos;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		pos = kmb_i2s->tx_ptr;
	else
		pos = kmb_i2s->rx_ptr;

	return pos < runtime->buffer_size ? pos : 0;
}

static const struct snd_soc_component_driver kmb_component = {
391 392 393 394 395 396
	.name			= "kmb",
	.pcm_construct		= kmb_platform_pcm_new,
	.open			= kmb_pcm_open,
	.trigger		= kmb_pcm_trigger,
	.pointer		= kmb_pcm_pointer,
	.legacy_dai_naming	= 1,
397 398
};

399
static const struct snd_soc_component_driver kmb_component_dma = {
400 401
	.name			= "kmb",
	.legacy_dai_naming	= 1,
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
};

static int kmb_probe(struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);

	if (kmb_i2s->use_pio)
		return 0;

	snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data,
				  &kmb_i2s->capture_dma_data);

	return 0;
}

static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
{
	u32 dma_reg;

	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
	/* Enable DMA handshake for stream */
	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
		dma_reg |= I2S_DMAEN_TXBLOCK;
	else
		dma_reg |= I2S_DMAEN_RXBLOCK;

	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
}

static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream)
{
	u32 dma_reg;

	dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR);
	/* Disable DMA handshake for stream */
	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_reg &= ~I2S_DMAEN_TXBLOCK;
		writel(1, kmb_i2s->i2s_base + I2S_RTXDMA);
	} else {
		dma_reg &= ~I2S_DMAEN_RXBLOCK;
		writel(1, kmb_i2s->i2s_base + I2S_RRXDMA);
	}
	writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR);
}

447 448 449 450 451 452 453 454 455 456 457 458 459
static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
			  struct snd_pcm_substream *substream)
{
	struct i2s_clk_config_data *config = &kmb_i2s->config;

	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
	writel(1, kmb_i2s->i2s_base + IER);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		writel(1, kmb_i2s->i2s_base + ITER);
	else
		writel(1, kmb_i2s->i2s_base + IRER);

460 461 462 463 464
	if (kmb_i2s->use_pio)
		kmb_i2s_irq_trigger(kmb_i2s, substream->stream,
				    config->chan_nr, true);
	else
		kmb_i2s_enable_dma(kmb_i2s, substream->stream);
465

466
	if (kmb_i2s->clock_provider)
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
		writel(1, kmb_i2s->i2s_base + CER);
	else
		writel(0, kmb_i2s->i2s_base + CER);
}

static void kmb_i2s_stop(struct kmb_i2s_info *kmb_i2s,
			 struct snd_pcm_substream *substream)
{
	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
	kmb_i2s_clear_irqs(kmb_i2s, substream->stream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		writel(0, kmb_i2s->i2s_base + ITER);
	else
		writel(0, kmb_i2s->i2s_base + IRER);

	kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);

	if (!kmb_i2s->active) {
		writel(0, kmb_i2s->i2s_base + CER);
		writel(0, kmb_i2s->i2s_base + IER);
	}
}

static void kmb_disable_clk(void *clk)
{
	clk_disable_unprepare(clk);
}

static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
	int ret;

501
	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
502
	case SND_SOC_DAIFMT_BC_FC:
503
		kmb_i2s->clock_provider = false;
504 505
		ret = 0;
		break;
506
	case SND_SOC_DAIFMT_BP_FP:
507
		writel(CLOCK_PROVIDER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0);
508 509 510 511 512 513 514 515 516 517

		ret = clk_prepare_enable(kmb_i2s->clk_i2s);
		if (ret < 0)
			return ret;

		ret = devm_add_action_or_reset(kmb_i2s->dev, kmb_disable_clk,
					       kmb_i2s->clk_i2s);
		if (ret)
			return ret;

518
		kmb_i2s->clock_provider = true;
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
		break;
	default:
		return -EINVAL;
	}

	return ret;
}

static int kmb_dai_trigger(struct snd_pcm_substream *substream,
			   int cmd, struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s  = snd_soc_dai_get_drvdata(cpu_dai);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		/* Keep track of i2s activity before turn off
		 * the i2s interface
		 */
		kmb_i2s->active++;
		kmb_i2s_start(kmb_i2s, substream);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		kmb_i2s->active--;
542 543
		if (kmb_i2s->use_pio)
			kmb_i2s_stop(kmb_i2s, substream);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
		break;
	default:
		return  -EINVAL;
	}

	return 0;
}

static void kmb_i2s_config(struct kmb_i2s_info *kmb_i2s, int stream)
{
	struct i2s_clk_config_data *config = &kmb_i2s->config;
	u32 ch_reg;

	kmb_i2s_disable_channels(kmb_i2s, stream);

	for (ch_reg = 0; ch_reg < config->chan_nr / 2; ch_reg++) {
		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
			writel(kmb_i2s->xfer_resolution,
			       kmb_i2s->i2s_base + TCR(ch_reg));

			writel(kmb_i2s->fifo_th - 1,
			       kmb_i2s->i2s_base + TFCR(ch_reg));

			writel(1, kmb_i2s->i2s_base + TER(ch_reg));
		} else {
			writel(kmb_i2s->xfer_resolution,
			       kmb_i2s->i2s_base + RCR(ch_reg));

			writel(kmb_i2s->fifo_th - 1,
			       kmb_i2s->i2s_base + RFCR(ch_reg));

			writel(1, kmb_i2s->i2s_base + RER(ch_reg));
		}
	}
}

static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *hw_params,
			     struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
	struct i2s_clk_config_data *config = &kmb_i2s->config;
586
	u32 write_val;
587 588 589 590 591 592 593
	int ret;

	switch (params_format(hw_params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		config->data_width = 16;
		kmb_i2s->ccr = 0x00;
		kmb_i2s->xfer_resolution = 0x02;
594 595
		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
596 597
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
598 599 600
		config->data_width = 32;
		kmb_i2s->ccr = 0x14;
		kmb_i2s->xfer_resolution = 0x05;
601 602
		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
603
		break;
604 605 606
	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
		kmb_i2s->iec958_fmt = true;
		fallthrough;
607 608 609 610
	case SNDRV_PCM_FORMAT_S32_LE:
		config->data_width = 32;
		kmb_i2s->ccr = 0x10;
		kmb_i2s->xfer_resolution = 0x05;
611 612
		kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
613 614 615 616 617 618 619 620 621
		break;
	default:
		dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt");
		return -EINVAL;
	}

	config->chan_nr = params_channels(hw_params);

	switch (config->chan_nr) {
622 623 624 625 626 627
	case 8:
	case 4:
		/*
		 * Platform is not capable of providing clocks for
		 * multi channel audio
		 */
628
		if (kmb_i2s->clock_provider)
629 630
			return -EINVAL;

631 632
		write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) |
				(config->data_width << DATA_WIDTH_CONFIG_BIT) |
633
				TDM_OPERATION;
634 635

		writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0);
636 637 638 639 640 641
		break;
	case 2:
		/*
		 * Platform is only capable of providing clocks need for
		 * 2 channel master mode
		 */
642
		if (!(kmb_i2s->clock_provider))
643 644 645 646
			return -EINVAL;

		write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) |
				(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 651 652 653 654 655 656 657 658 659 660 661
		break;
	default:
		dev_dbg(kmb_i2s->dev, "channel not supported\n");
		return -EINVAL;
	}

	kmb_i2s_config(kmb_i2s, substream->stream);

	writel(kmb_i2s->ccr, kmb_i2s->i2s_base + CCR);

	config->sample_rate = params_rate(hw_params);

662
	if (kmb_i2s->clock_provider) {
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
		/* Only 2 ch supported in Master mode */
		u32 bitclk = config->sample_rate * config->data_width * 2;

		ret = clk_set_rate(kmb_i2s->clk_i2s, bitclk);
		if (ret) {
			dev_err(kmb_i2s->dev,
				"Can't set I2S clock rate: %d\n", ret);
			return ret;
		}
	}

	return 0;
}

static int kmb_dai_prepare(struct snd_pcm_substream *substream,
			   struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		writel(1, kmb_i2s->i2s_base + TXFFR);
	else
		writel(1, kmb_i2s->i2s_base + RXFFR);

	return 0;
}

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
static int kmb_dai_startup(struct snd_pcm_substream *substream,
			   struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
	struct snd_dmaengine_dai_dma_data *dma_data;

	if (kmb_i2s->use_pio)
		return 0;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		dma_data = &kmb_i2s->play_dma_data;
	else
		dma_data = &kmb_i2s->capture_dma_data;

	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);

	return 0;
}

static int kmb_dai_hw_free(struct snd_pcm_substream *substream,
			   struct snd_soc_dai *cpu_dai)
{
	struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
	/* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
	if (kmb_i2s->use_pio)
		kmb_i2s_clear_irqs(kmb_i2s, substream->stream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		writel(0, kmb_i2s->i2s_base + ITER);
	else
		writel(0, kmb_i2s->i2s_base + IRER);

	if (kmb_i2s->use_pio)
		kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
	else
		kmb_i2s_disable_dma(kmb_i2s, substream->stream);

	if (!kmb_i2s->active) {
		writel(0, kmb_i2s->i2s_base + CER);
		writel(0, kmb_i2s->i2s_base + IER);
	}

	return 0;
}

735
static const struct snd_soc_dai_ops kmb_dai_ops = {
736
	.startup	= kmb_dai_startup,
737 738
	.trigger	= kmb_dai_trigger,
	.hw_params	= kmb_dai_hw_params,
739
	.hw_free	= kmb_dai_hw_free,
740
	.prepare	= kmb_dai_prepare,
741
	.set_fmt	= kmb_set_dai_fmt,
742 743
};

744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = {
	{
		.name = "intel_kmb_hdmi_i2s",
		.playback = {
			.channels_min = 2,
			.channels_max = 2,
			.rates = SNDRV_PCM_RATE_48000,
			.rate_min = 48000,
			.rate_max = 48000,
			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_S24_LE |
				    SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE),
		},
		.ops = &kmb_dai_ops,
		.probe = kmb_probe,
	},
};

762
static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = {
763
	{
764
		.name = "intel_kmb_i2s",
765 766 767
		.playback = {
			.channels_min = 2,
			.channels_max = 2,
768 769 770 771
			.rates = SNDRV_PCM_RATE_8000 |
				 SNDRV_PCM_RATE_16000 |
				 SNDRV_PCM_RATE_48000,
			.rate_min = 8000,
772 773 774 775 776 777 778 779
			.rate_max = 48000,
			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
				    SNDRV_PCM_FMTBIT_S24_LE |
				    SNDRV_PCM_FMTBIT_S16_LE),
		},
		.capture = {
			.channels_min = 2,
			.channels_max = 2,
780 781 782 783
			.rates = SNDRV_PCM_RATE_8000 |
				 SNDRV_PCM_RATE_16000 |
				 SNDRV_PCM_RATE_48000,
			.rate_min = 8000,
784 785 786 787 788 789
			.rate_max = 48000,
			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
				    SNDRV_PCM_FMTBIT_S24_LE |
				    SNDRV_PCM_FMTBIT_S16_LE),
		},
		.ops = &kmb_dai_ops,
790
		.probe = kmb_probe,
791 792 793
	},
};

794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = {
	{
		.name = "intel_kmb_tdm",
		.capture = {
			.channels_min = 4,
			.channels_max = 8,
			.rates = SNDRV_PCM_RATE_8000 |
				 SNDRV_PCM_RATE_16000 |
				 SNDRV_PCM_RATE_48000,
			.rate_min = 8000,
			.rate_max = 48000,
			.formats = (SNDRV_PCM_FMTBIT_S32_LE |
				    SNDRV_PCM_FMTBIT_S24_LE |
				    SNDRV_PCM_FMTBIT_S16_LE),
		},
		.ops = &kmb_dai_ops,
810
		.probe = kmb_probe,
811 812 813 814 815
	},
};

static const struct of_device_id kmb_plat_of_match[] = {
	{ .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai},
816
	{ .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai},
817 818 819 820
	{ .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai},
	{}
};

821 822
static int kmb_plat_dai_probe(struct platform_device *pdev)
{
823
	struct device_node *np = pdev->dev.of_node;
824
	struct snd_soc_dai_driver *kmb_i2s_dai;
825
	const struct of_device_id *match;
826 827
	struct device *dev = &pdev->dev;
	struct kmb_i2s_info *kmb_i2s;
828
	struct resource *res;
829 830 831 832 833 834 835 836 837 838 839
	int ret, irq;
	u32 comp1_reg;

	kmb_i2s = devm_kzalloc(dev, sizeof(*kmb_i2s), GFP_KERNEL);
	if (!kmb_i2s)
		return -ENOMEM;

	kmb_i2s_dai = devm_kzalloc(dev, sizeof(*kmb_i2s_dai), GFP_KERNEL);
	if (!kmb_i2s_dai)
		return -ENOMEM;

840 841 842 843 844 845
	match = of_match_device(kmb_plat_of_match, &pdev->dev);
	if (!match) {
		dev_err(&pdev->dev, "Error: No device match found\n");
		return -ENODEV;
	}
	kmb_i2s_dai = (struct snd_soc_dai_driver *) match->data;
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869

	/* Prepare the related clocks */
	kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk");
	if (IS_ERR(kmb_i2s->clk_apb)) {
		dev_err(dev, "Failed to get apb clock\n");
		return PTR_ERR(kmb_i2s->clk_apb);
	}

	ret = clk_prepare_enable(kmb_i2s->clk_apb);
	if (ret < 0)
		return ret;

	ret = devm_add_action_or_reset(dev, kmb_disable_clk, kmb_i2s->clk_apb);
	if (ret) {
		dev_err(dev, "Failed to add clk_apb reset action\n");
		return ret;
	}

	kmb_i2s->clk_i2s = devm_clk_get(dev, "osc");
	if (IS_ERR(kmb_i2s->clk_i2s)) {
		dev_err(dev, "Failed to get osc clock\n");
		return PTR_ERR(kmb_i2s->clk_i2s);
	}

870
	kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
871 872 873 874 875 876 877 878 879 880 881 882 883
	if (IS_ERR(kmb_i2s->i2s_base))
		return PTR_ERR(kmb_i2s->i2s_base);

	kmb_i2s->pss_base = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(kmb_i2s->pss_base))
		return PTR_ERR(kmb_i2s->pss_base);

	kmb_i2s->dev = &pdev->dev;

	comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1);

	kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2;

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
	kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas"));

	if (kmb_i2s->use_pio) {
		irq = platform_get_irq_optional(pdev, 0);
		if (irq > 0) {
			ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
					       pdev->name, kmb_i2s);
			if (ret < 0) {
				dev_err(dev, "failed to request irq\n");
				return ret;
			}
		}
		ret = devm_snd_soc_register_component(dev, &kmb_component,
						      kmb_i2s_dai, 1);
	} else {
		kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA;
		kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA;
		ret = snd_dmaengine_pcm_register(&pdev->dev,
						 NULL, 0);
		if (ret) {
			dev_err(&pdev->dev, "could not register dmaengine: %d\n",
				ret);
			return ret;
		}
		ret = devm_snd_soc_register_component(dev, &kmb_component_dma,
						      kmb_i2s_dai, 1);
	}

912 913 914 915 916
	if (ret) {
		dev_err(dev, "not able to register dai\n");
		return ret;
	}

917 918 919 920
	/* To ensure none of the channels are enabled at boot up */
	kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
	kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);

921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
	dev_set_drvdata(dev, kmb_i2s);

	return ret;
}

static struct platform_driver kmb_plat_dai_driver = {
	.driver		= {
		.name		= "kmb-plat-dai",
		.of_match_table = kmb_plat_of_match,
	},
	.probe		= kmb_plat_dai_probe,
};

module_platform_driver(kmb_plat_dai_driver);

MODULE_DESCRIPTION("ASoC Intel KeemBay Platform driver");
MODULE_AUTHOR("Sia Jee Heng <jee.heng.sia@intel.com>");
MODULE_AUTHOR("Sit, Michael Wei Hong <michael.wei.hong.sit@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:kmb_platform");