18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Driver for Microchip S/PDIF RX Controller
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
68c2ecf20Sopenharmony_ci//
78c2ecf20Sopenharmony_ci// Author: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/clk.h>
108c2ecf20Sopenharmony_ci#include <linux/io.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/regmap.h>
138c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <sound/dmaengine_pcm.h>
168c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
178c2ecf20Sopenharmony_ci#include <sound/soc.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * ---- S/PDIF Receiver Controller Register map ----
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci#define SPDIFRX_CR			0x00	/* Control Register */
238c2ecf20Sopenharmony_ci#define SPDIFRX_MR			0x04	/* Mode Register */
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define SPDIFRX_IER			0x10	/* Interrupt Enable Register */
268c2ecf20Sopenharmony_ci#define SPDIFRX_IDR			0x14	/* Interrupt Disable Register */
278c2ecf20Sopenharmony_ci#define SPDIFRX_IMR			0x18	/* Interrupt Mask Register */
288c2ecf20Sopenharmony_ci#define SPDIFRX_ISR			0x1c	/* Interrupt Status Register */
298c2ecf20Sopenharmony_ci#define SPDIFRX_RSR			0x20	/* Status Register */
308c2ecf20Sopenharmony_ci#define SPDIFRX_RHR			0x24	/* Holding Register */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define SPDIFRX_CHSR(channel, reg)	\
338c2ecf20Sopenharmony_ci	(0x30 + (channel) * 0x30 + (reg) * 4)	/* Channel x Status Registers */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define SPDIFRX_CHUD(channel, reg)	\
368c2ecf20Sopenharmony_ci	(0x48 + (channel) * 0x30 + (reg) * 4)	/* Channel x User Data Registers */
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define SPDIFRX_WPMR			0xE4	/* Write Protection Mode Register */
398c2ecf20Sopenharmony_ci#define SPDIFRX_WPSR			0xE8	/* Write Protection Status Register */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define SPDIFRX_VERSION			0xFC	/* Version Register */
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * ---- Control Register (Write-only) ----
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci#define SPDIFRX_CR_SWRST		BIT(0)	/* Software Reset */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/*
498c2ecf20Sopenharmony_ci * ---- Mode Register (Read/Write) ----
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_ci/* Receive Enable */
528c2ecf20Sopenharmony_ci#define SPDIFRX_MR_RXEN_MASK		GENMASK(0, 0)
538c2ecf20Sopenharmony_ci#define SPDIFRX_MR_RXEN_DISABLE		(0 << 0)	/* SPDIF Receiver Disabled */
548c2ecf20Sopenharmony_ci#define SPDIFRX_MR_RXEN_ENABLE		(1 << 0)	/* SPDIF Receiver Enabled */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* Validity Bit Mode */
578c2ecf20Sopenharmony_ci#define SPDIFRX_MR_VBMODE_MASK		GENAMSK(1, 1)
588c2ecf20Sopenharmony_ci#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
598c2ecf20Sopenharmony_ci	(0 << 1)	/* Load sample regardless of validity bit value */
608c2ecf20Sopenharmony_ci#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
618c2ecf20Sopenharmony_ci	(1 << 1)	/* Load sample only if validity bit is 0 */
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* Data Word Endian Mode */
648c2ecf20Sopenharmony_ci#define SPDIFRX_MR_ENDIAN_MASK		GENMASK(2, 2)
658c2ecf20Sopenharmony_ci#define SPDIFRX_MR_ENDIAN_LITTLE	(0 << 2)	/* Little Endian Mode */
668c2ecf20Sopenharmony_ci#define SPDIFRX_MR_ENDIAN_BIG		(1 << 2)	/* Big Endian Mode */
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* Parity Bit Mode */
698c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PBMODE_MASK		GENMASK(3, 3)
708c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PBMODE_PARCHECK	(0 << 3)	/* Parity Check Enabled */
718c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PBMODE_NOPARCHECK	(1 << 3)	/* Parity Check Disabled */
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* Sample Data Width */
748c2ecf20Sopenharmony_ci#define SPDIFRX_MR_DATAWIDTH_MASK	GENMASK(5, 4)
758c2ecf20Sopenharmony_ci#define SPDIFRX_MR_DATAWIDTH(width) \
768c2ecf20Sopenharmony_ci	(((6 - (width) / 4) << 4) & SPDIFRX_MR_DATAWIDTH_MASK)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* Packed Data Mode in Receive Holding Register */
798c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PACK_MASK		GENMASK(7, 7)
808c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PACK_DISABLED	(0 << 7)
818c2ecf20Sopenharmony_ci#define SPDIFRX_MR_PACK_ENABLED		(1 << 7)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/* Start of Block Bit Mode */
848c2ecf20Sopenharmony_ci#define SPDIFRX_MR_SBMODE_MASK		GENMASK(8, 8)
858c2ecf20Sopenharmony_ci#define SPDIFRX_MR_SBMODE_ALWAYS_LOAD	(0 << 8)
868c2ecf20Sopenharmony_ci#define SPDIFRX_MR_SBMODE_DISCARD	(1 << 8)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* Consecutive Preamble Error Threshold Automatic Restart */
898c2ecf20Sopenharmony_ci#define SPDIFRX_MR_AUTORST_MASK			GENMASK(24, 24)
908c2ecf20Sopenharmony_ci#define SPDIFRX_MR_AUTORST_NOACTION		(0 << 24)
918c2ecf20Sopenharmony_ci#define SPDIFRX_MR_AUTORST_UNLOCK_ON_PRE_ERR	(1 << 24)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/*
948c2ecf20Sopenharmony_ci * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_ci#define SPDIFRX_IR_RXRDY			BIT(0)
978c2ecf20Sopenharmony_ci#define SPDIFRX_IR_LOCKED			BIT(1)
988c2ecf20Sopenharmony_ci#define SPDIFRX_IR_LOSS				BIT(2)
998c2ecf20Sopenharmony_ci#define SPDIFRX_IR_BLOCKEND			BIT(3)
1008c2ecf20Sopenharmony_ci#define SPDIFRX_IR_SFE				BIT(4)
1018c2ecf20Sopenharmony_ci#define SPDIFRX_IR_PAR_ERR			BIT(5)
1028c2ecf20Sopenharmony_ci#define SPDIFRX_IR_OVERRUN			BIT(6)
1038c2ecf20Sopenharmony_ci#define SPDIFRX_IR_RXFULL			BIT(7)
1048c2ecf20Sopenharmony_ci#define SPDIFRX_IR_CSC(ch)			BIT((ch) + 8)
1058c2ecf20Sopenharmony_ci#define SPDIFRX_IR_SECE				BIT(10)
1068c2ecf20Sopenharmony_ci#define SPDIFRX_IR_BLOCKST			BIT(11)
1078c2ecf20Sopenharmony_ci#define SPDIFRX_IR_NRZ_ERR			BIT(12)
1088c2ecf20Sopenharmony_ci#define SPDIFRX_IR_PRE_ERR			BIT(13)
1098c2ecf20Sopenharmony_ci#define SPDIFRX_IR_CP_ERR			BIT(14)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci/*
1128c2ecf20Sopenharmony_ci * ---- Receiver Status Register (Read/Write) ----
1138c2ecf20Sopenharmony_ci */
1148c2ecf20Sopenharmony_ci/* Enable Status */
1158c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_ULOCK			BIT(0)
1168c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_BADF			BIT(1)
1178c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_LOWF			BIT(2)
1188c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_NOSIGNAL			BIT(3)
1198c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_IFS_MASK			GENMASK(27, 16)
1208c2ecf20Sopenharmony_ci#define SPDIFRX_RSR_IFS(reg)			\
1218c2ecf20Sopenharmony_ci	(((reg) & SPDIFRX_RSR_IFS_MASK) >> 16)
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/*
1248c2ecf20Sopenharmony_ci *  ---- Version Register (Read-only) ----
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ci#define SPDIFRX_VERSION_MASK		GENMASK(11, 0)
1278c2ecf20Sopenharmony_ci#define SPDIFRX_VERSION_MFN_MASK	GENMASK(18, 16)
1288c2ecf20Sopenharmony_ci#define SPDIFRX_VERSION_MFN(reg)	(((reg) & SPDIFRX_VERSION_MFN_MASK) >> 16)
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic bool mchp_spdifrx_readable_reg(struct device *dev, unsigned int reg)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	switch (reg) {
1338c2ecf20Sopenharmony_ci	case SPDIFRX_MR:
1348c2ecf20Sopenharmony_ci	case SPDIFRX_IMR:
1358c2ecf20Sopenharmony_ci	case SPDIFRX_ISR:
1368c2ecf20Sopenharmony_ci	case SPDIFRX_RSR:
1378c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 0):
1388c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 1):
1398c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 2):
1408c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 3):
1418c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 4):
1428c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(0, 5):
1438c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 0):
1448c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 1):
1458c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 2):
1468c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 3):
1478c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 4):
1488c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(0, 5):
1498c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 0):
1508c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 1):
1518c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 2):
1528c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 3):
1538c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 4):
1548c2ecf20Sopenharmony_ci	case SPDIFRX_CHSR(1, 5):
1558c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 0):
1568c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 1):
1578c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 2):
1588c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 3):
1598c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 4):
1608c2ecf20Sopenharmony_ci	case SPDIFRX_CHUD(1, 5):
1618c2ecf20Sopenharmony_ci	case SPDIFRX_WPMR:
1628c2ecf20Sopenharmony_ci	case SPDIFRX_WPSR:
1638c2ecf20Sopenharmony_ci	case SPDIFRX_VERSION:
1648c2ecf20Sopenharmony_ci		return true;
1658c2ecf20Sopenharmony_ci	default:
1668c2ecf20Sopenharmony_ci		return false;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic bool mchp_spdifrx_writeable_reg(struct device *dev, unsigned int reg)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	switch (reg) {
1738c2ecf20Sopenharmony_ci	case SPDIFRX_CR:
1748c2ecf20Sopenharmony_ci	case SPDIFRX_MR:
1758c2ecf20Sopenharmony_ci	case SPDIFRX_IER:
1768c2ecf20Sopenharmony_ci	case SPDIFRX_IDR:
1778c2ecf20Sopenharmony_ci	case SPDIFRX_WPMR:
1788c2ecf20Sopenharmony_ci		return true;
1798c2ecf20Sopenharmony_ci	default:
1808c2ecf20Sopenharmony_ci		return false;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic bool mchp_spdifrx_precious_reg(struct device *dev, unsigned int reg)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	switch (reg) {
1878c2ecf20Sopenharmony_ci	case SPDIFRX_ISR:
1888c2ecf20Sopenharmony_ci	case SPDIFRX_RHR:
1898c2ecf20Sopenharmony_ci		return true;
1908c2ecf20Sopenharmony_ci	default:
1918c2ecf20Sopenharmony_ci		return false;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic const struct regmap_config mchp_spdifrx_regmap_config = {
1968c2ecf20Sopenharmony_ci	.reg_bits = 32,
1978c2ecf20Sopenharmony_ci	.reg_stride = 4,
1988c2ecf20Sopenharmony_ci	.val_bits = 32,
1998c2ecf20Sopenharmony_ci	.max_register = SPDIFRX_VERSION,
2008c2ecf20Sopenharmony_ci	.readable_reg = mchp_spdifrx_readable_reg,
2018c2ecf20Sopenharmony_ci	.writeable_reg = mchp_spdifrx_writeable_reg,
2028c2ecf20Sopenharmony_ci	.precious_reg = mchp_spdifrx_precious_reg,
2038c2ecf20Sopenharmony_ci};
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci#define SPDIFRX_GCLK_RATIO_MIN	(12 * 64)
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci#define SPDIFRX_CS_BITS		192
2088c2ecf20Sopenharmony_ci#define SPDIFRX_UD_BITS		192
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci#define SPDIFRX_CHANNELS	2
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistruct mchp_spdifrx_ch_stat {
2138c2ecf20Sopenharmony_ci	unsigned char data[SPDIFRX_CS_BITS / 8];
2148c2ecf20Sopenharmony_ci	struct completion done;
2158c2ecf20Sopenharmony_ci};
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistruct mchp_spdifrx_user_data {
2188c2ecf20Sopenharmony_ci	unsigned char data[SPDIFRX_UD_BITS / 8];
2198c2ecf20Sopenharmony_ci	struct completion done;
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistruct mchp_spdifrx_mixer_control {
2238c2ecf20Sopenharmony_ci		struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
2248c2ecf20Sopenharmony_ci		struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
2258c2ecf20Sopenharmony_ci		bool ulock;
2268c2ecf20Sopenharmony_ci		bool badf;
2278c2ecf20Sopenharmony_ci		bool signal;
2288c2ecf20Sopenharmony_ci};
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistruct mchp_spdifrx_dev {
2318c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data	capture;
2328c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control	control;
2338c2ecf20Sopenharmony_ci	struct mutex				mlock;
2348c2ecf20Sopenharmony_ci	struct device				*dev;
2358c2ecf20Sopenharmony_ci	struct regmap				*regmap;
2368c2ecf20Sopenharmony_ci	struct clk				*pclk;
2378c2ecf20Sopenharmony_ci	struct clk				*gclk;
2388c2ecf20Sopenharmony_ci	unsigned int				fmt;
2398c2ecf20Sopenharmony_ci	unsigned int				trigger_enabled;
2408c2ecf20Sopenharmony_ci	unsigned int				gclk_enabled:1;
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic void mchp_spdifrx_channel_status_read(struct mchp_spdifrx_dev *dev,
2448c2ecf20Sopenharmony_ci					     int channel)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
2478c2ecf20Sopenharmony_ci	u8 *ch_stat = &ctrl->ch_stat[channel].data[0];
2488c2ecf20Sopenharmony_ci	u32 val;
2498c2ecf20Sopenharmony_ci	int i;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat[channel].data) / 4; i++) {
2528c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_CHSR(channel, i), &val);
2538c2ecf20Sopenharmony_ci		*ch_stat++ = val & 0xFF;
2548c2ecf20Sopenharmony_ci		*ch_stat++ = (val >> 8) & 0xFF;
2558c2ecf20Sopenharmony_ci		*ch_stat++ = (val >> 16) & 0xFF;
2568c2ecf20Sopenharmony_ci		*ch_stat++ = (val >> 24) & 0xFF;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev,
2618c2ecf20Sopenharmony_ci						int channel)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
2648c2ecf20Sopenharmony_ci	u8 *user_data = &ctrl->user_data[channel].data[0];
2658c2ecf20Sopenharmony_ci	u32 val;
2668c2ecf20Sopenharmony_ci	int i;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ctrl->user_data[channel].data) / 4; i++) {
2698c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_CHUD(channel, i), &val);
2708c2ecf20Sopenharmony_ci		*user_data++ = val & 0xFF;
2718c2ecf20Sopenharmony_ci		*user_data++ = (val >> 8) & 0xFF;
2728c2ecf20Sopenharmony_ci		*user_data++ = (val >> 16) & 0xFF;
2738c2ecf20Sopenharmony_ci		*user_data++ = (val >> 24) & 0xFF;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = dev_id;
2808c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
2818c2ecf20Sopenharmony_ci	u32 sr, imr, pending;
2828c2ecf20Sopenharmony_ci	irqreturn_t ret = IRQ_NONE;
2838c2ecf20Sopenharmony_ci	int ch;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	regmap_read(dev->regmap, SPDIFRX_ISR, &sr);
2868c2ecf20Sopenharmony_ci	regmap_read(dev->regmap, SPDIFRX_IMR, &imr);
2878c2ecf20Sopenharmony_ci	pending = sr & imr;
2888c2ecf20Sopenharmony_ci	dev_dbg(dev->dev, "ISR: %#x, IMR: %#x, pending: %#x\n", sr, imr,
2898c2ecf20Sopenharmony_ci		pending);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (!pending)
2928c2ecf20Sopenharmony_ci		return IRQ_NONE;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (pending & SPDIFRX_IR_BLOCKEND) {
2958c2ecf20Sopenharmony_ci		for (ch = 0; ch < SPDIFRX_CHANNELS; ch++) {
2968c2ecf20Sopenharmony_ci			mchp_spdifrx_channel_user_data_read(dev, ch);
2978c2ecf20Sopenharmony_ci			complete(&ctrl->user_data[ch].done);
2988c2ecf20Sopenharmony_ci		}
2998c2ecf20Sopenharmony_ci		regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
3008c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	for (ch = 0; ch < SPDIFRX_CHANNELS; ch++) {
3048c2ecf20Sopenharmony_ci		if (pending & SPDIFRX_IR_CSC(ch)) {
3058c2ecf20Sopenharmony_ci			mchp_spdifrx_channel_status_read(dev, ch);
3068c2ecf20Sopenharmony_ci			complete(&ctrl->ch_stat[ch].done);
3078c2ecf20Sopenharmony_ci			regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_CSC(ch));
3088c2ecf20Sopenharmony_ci			ret = IRQ_HANDLED;
3098c2ecf20Sopenharmony_ci		}
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (pending & SPDIFRX_IR_OVERRUN) {
3138c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "Overrun detected\n");
3148c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return ret;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic int mchp_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd,
3218c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
3248c2ecf20Sopenharmony_ci	int ret = 0;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	switch (cmd) {
3278c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
3288c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
3298c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3308c2ecf20Sopenharmony_ci		mutex_lock(&dev->mlock);
3318c2ecf20Sopenharmony_ci		/* Enable overrun interrupts */
3328c2ecf20Sopenharmony_ci		regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_OVERRUN);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		/* Enable receiver. */
3358c2ecf20Sopenharmony_ci		regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
3368c2ecf20Sopenharmony_ci				   SPDIFRX_MR_RXEN_ENABLE);
3378c2ecf20Sopenharmony_ci		dev->trigger_enabled = true;
3388c2ecf20Sopenharmony_ci		mutex_unlock(&dev->mlock);
3398c2ecf20Sopenharmony_ci		break;
3408c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
3418c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
3428c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3438c2ecf20Sopenharmony_ci		mutex_lock(&dev->mlock);
3448c2ecf20Sopenharmony_ci		/* Disable overrun interrupts */
3458c2ecf20Sopenharmony_ci		regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_OVERRUN);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci		/* Disable receiver. */
3488c2ecf20Sopenharmony_ci		regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
3498c2ecf20Sopenharmony_ci				   SPDIFRX_MR_RXEN_DISABLE);
3508c2ecf20Sopenharmony_ci		dev->trigger_enabled = false;
3518c2ecf20Sopenharmony_ci		mutex_unlock(&dev->mlock);
3528c2ecf20Sopenharmony_ci		break;
3538c2ecf20Sopenharmony_ci	default:
3548c2ecf20Sopenharmony_ci		ret = -EINVAL;
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return ret;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
3618c2ecf20Sopenharmony_ci				  struct snd_pcm_hw_params *params,
3628c2ecf20Sopenharmony_ci				  struct snd_soc_dai *dai)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
3658c2ecf20Sopenharmony_ci	u32 mr = 0;
3668c2ecf20Sopenharmony_ci	int ret;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
3698c2ecf20Sopenharmony_ci		__func__, params_rate(params), params_format(params),
3708c2ecf20Sopenharmony_ci		params_width(params), params_channels(params));
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3738c2ecf20Sopenharmony_ci		dev_err(dev->dev, "Playback is not supported\n");
3748c2ecf20Sopenharmony_ci		return -EINVAL;
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	if (params_channels(params) != SPDIFRX_CHANNELS) {
3788c2ecf20Sopenharmony_ci		dev_err(dev->dev, "unsupported number of channels: %d\n",
3798c2ecf20Sopenharmony_ci			params_channels(params));
3808c2ecf20Sopenharmony_ci		return -EINVAL;
3818c2ecf20Sopenharmony_ci	}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	switch (params_format(params)) {
3848c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S16_BE:
3858c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S20_3BE:
3868c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_3BE:
3878c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_BE:
3888c2ecf20Sopenharmony_ci		mr |= SPDIFRX_MR_ENDIAN_BIG;
3898c2ecf20Sopenharmony_ci		fallthrough;
3908c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S16_LE:
3918c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S20_3LE:
3928c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_3LE:
3938c2ecf20Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_LE:
3948c2ecf20Sopenharmony_ci		mr |= SPDIFRX_MR_DATAWIDTH(params_width(params));
3958c2ecf20Sopenharmony_ci		break;
3968c2ecf20Sopenharmony_ci	default:
3978c2ecf20Sopenharmony_ci		dev_err(dev->dev, "unsupported PCM format: %d\n",
3988c2ecf20Sopenharmony_ci			params_format(params));
3998c2ecf20Sopenharmony_ci		return -EINVAL;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
4038c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
4048c2ecf20Sopenharmony_ci		dev_err(dev->dev, "PCM already running\n");
4058c2ecf20Sopenharmony_ci		ret = -EBUSY;
4068c2ecf20Sopenharmony_ci		goto unlock;
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	if (dev->gclk_enabled) {
4108c2ecf20Sopenharmony_ci		clk_disable_unprepare(dev->gclk);
4118c2ecf20Sopenharmony_ci		dev->gclk_enabled = 0;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci	ret = clk_set_min_rate(dev->gclk, params_rate(params) *
4148c2ecf20Sopenharmony_ci					  SPDIFRX_GCLK_RATIO_MIN + 1);
4158c2ecf20Sopenharmony_ci	if (ret) {
4168c2ecf20Sopenharmony_ci		dev_err(dev->dev,
4178c2ecf20Sopenharmony_ci			"unable to set gclk min rate: rate %u * ratio %u + 1\n",
4188c2ecf20Sopenharmony_ci			params_rate(params), SPDIFRX_GCLK_RATIO_MIN);
4198c2ecf20Sopenharmony_ci		goto unlock;
4208c2ecf20Sopenharmony_ci	}
4218c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(dev->gclk);
4228c2ecf20Sopenharmony_ci	if (ret) {
4238c2ecf20Sopenharmony_ci		dev_err(dev->dev, "unable to enable gclk: %d\n", ret);
4248c2ecf20Sopenharmony_ci		goto unlock;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci	dev->gclk_enabled = 1;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	dev_dbg(dev->dev, "GCLK range min set to %d\n",
4298c2ecf20Sopenharmony_ci		params_rate(params) * SPDIFRX_GCLK_RATIO_MIN + 1);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, SPDIFRX_MR, mr);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ciunlock:
4348c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	return ret;
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_cistatic int mchp_spdifrx_hw_free(struct snd_pcm_substream *substream,
4408c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
4458c2ecf20Sopenharmony_ci	if (dev->gclk_enabled) {
4468c2ecf20Sopenharmony_ci		clk_disable_unprepare(dev->gclk);
4478c2ecf20Sopenharmony_ci		dev->gclk_enabled = 0;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
4508c2ecf20Sopenharmony_ci	return 0;
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops mchp_spdifrx_dai_ops = {
4548c2ecf20Sopenharmony_ci	.trigger	= mchp_spdifrx_trigger,
4558c2ecf20Sopenharmony_ci	.hw_params	= mchp_spdifrx_hw_params,
4568c2ecf20Sopenharmony_ci	.hw_free	= mchp_spdifrx_hw_free,
4578c2ecf20Sopenharmony_ci};
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci#define MCHP_SPDIF_RATES	SNDRV_PCM_RATE_8000_192000
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci#define MCHP_SPDIF_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE |	\
4628c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_U16_BE |	\
4638c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S20_3LE |	\
4648c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S20_3BE |	\
4658c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_3LE |	\
4668c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_3BE |	\
4678c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_LE |	\
4688c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_BE	\
4698c2ecf20Sopenharmony_ci				)
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic int mchp_spdifrx_info(struct snd_kcontrol *kcontrol,
4728c2ecf20Sopenharmony_ci			     struct snd_ctl_elem_info *uinfo)
4738c2ecf20Sopenharmony_ci{
4748c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
4758c2ecf20Sopenharmony_ci	uinfo->count = 1;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	return 0;
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,
4818c2ecf20Sopenharmony_ci			       int channel,
4828c2ecf20Sopenharmony_ci			       struct snd_ctl_elem_value *uvalue)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
4858c2ecf20Sopenharmony_ci	struct mchp_spdifrx_ch_stat *ch_stat = &ctrl->ch_stat[channel];
4868c2ecf20Sopenharmony_ci	int ret = 0;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	/*
4918c2ecf20Sopenharmony_ci	 * We may reach this point with both clocks enabled but the receiver
4928c2ecf20Sopenharmony_ci	 * still disabled. To void waiting for completion and return with
4938c2ecf20Sopenharmony_ci	 * timeout check the dev->trigger_enabled.
4948c2ecf20Sopenharmony_ci	 *
4958c2ecf20Sopenharmony_ci	 * To retrieve data:
4968c2ecf20Sopenharmony_ci	 * - if the receiver is enabled CSC IRQ will update the data in software
4978c2ecf20Sopenharmony_ci	 *   caches (ch_stat->data)
4988c2ecf20Sopenharmony_ci	 * - otherwise we just update it here the software caches with latest
4998c2ecf20Sopenharmony_ci	 *   available information and return it; in this case we don't need
5008c2ecf20Sopenharmony_ci	 *   spin locking as the IRQ is disabled and will not be raised from
5018c2ecf20Sopenharmony_ci	 *   anywhere else.
5028c2ecf20Sopenharmony_ci	 */
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
5058c2ecf20Sopenharmony_ci		reinit_completion(&ch_stat->done);
5068c2ecf20Sopenharmony_ci		regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_CSC(channel));
5078c2ecf20Sopenharmony_ci		/* Check for new data available */
5088c2ecf20Sopenharmony_ci		ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
5098c2ecf20Sopenharmony_ci								msecs_to_jiffies(100));
5108c2ecf20Sopenharmony_ci		/* Valid stream might not be present */
5118c2ecf20Sopenharmony_ci		if (ret <= 0) {
5128c2ecf20Sopenharmony_ci			dev_dbg(dev->dev, "channel status for channel %d timeout\n",
5138c2ecf20Sopenharmony_ci				channel);
5148c2ecf20Sopenharmony_ci			regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_CSC(channel));
5158c2ecf20Sopenharmony_ci			ret = ret ? : -ETIMEDOUT;
5168c2ecf20Sopenharmony_ci			goto unlock;
5178c2ecf20Sopenharmony_ci		} else {
5188c2ecf20Sopenharmony_ci			ret = 0;
5198c2ecf20Sopenharmony_ci		}
5208c2ecf20Sopenharmony_ci	} else {
5218c2ecf20Sopenharmony_ci		/* Update software cache with latest channel status. */
5228c2ecf20Sopenharmony_ci		mchp_spdifrx_channel_status_read(dev, channel);
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	memcpy(uvalue->value.iec958.status, ch_stat->data,
5268c2ecf20Sopenharmony_ci	       sizeof(ch_stat->data));
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ciunlock:
5298c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
5308c2ecf20Sopenharmony_ci	return ret;
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistatic int mchp_spdifrx_cs1_get(struct snd_kcontrol *kcontrol,
5348c2ecf20Sopenharmony_ci				struct snd_ctl_elem_value *uvalue)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
5378c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	return mchp_spdifrx_cs_get(dev, 0, uvalue);
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic int mchp_spdifrx_cs2_get(struct snd_kcontrol *kcontrol,
5438c2ecf20Sopenharmony_ci				struct snd_ctl_elem_value *uvalue)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
5468c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	return mchp_spdifrx_cs_get(dev, 1, uvalue);
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_cistatic int mchp_spdifrx_cs_mask(struct snd_kcontrol *kcontrol,
5528c2ecf20Sopenharmony_ci				struct snd_ctl_elem_value *uvalue)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	memset(uvalue->value.iec958.status, 0xff,
5558c2ecf20Sopenharmony_ci	       sizeof(uvalue->value.iec958.status));
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return 0;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
5618c2ecf20Sopenharmony_ci				       int channel,
5628c2ecf20Sopenharmony_ci				       struct snd_ctl_elem_value *uvalue)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
5658c2ecf20Sopenharmony_ci	struct mchp_spdifrx_user_data *user_data = &ctrl->user_data[channel];
5668c2ecf20Sopenharmony_ci	int ret = 0;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	/*
5718c2ecf20Sopenharmony_ci	 * We may reach this point with both clocks enabled but the receiver
5728c2ecf20Sopenharmony_ci	 * still disabled. To void waiting for completion to just timeout we
5738c2ecf20Sopenharmony_ci	 * check here the dev->trigger_enabled flag.
5748c2ecf20Sopenharmony_ci	 *
5758c2ecf20Sopenharmony_ci	 * To retrieve data:
5768c2ecf20Sopenharmony_ci	 * - if the receiver is enabled we need to wait for blockend IRQ to read
5778c2ecf20Sopenharmony_ci	 *   data to and update it for us in software caches
5788c2ecf20Sopenharmony_ci	 * - otherwise reading the SPDIFRX_CHUD() registers is enough.
5798c2ecf20Sopenharmony_ci	 */
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
5828c2ecf20Sopenharmony_ci		reinit_completion(&user_data->done);
5838c2ecf20Sopenharmony_ci		regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_BLOCKEND);
5848c2ecf20Sopenharmony_ci		ret = wait_for_completion_interruptible_timeout(&user_data->done,
5858c2ecf20Sopenharmony_ci								msecs_to_jiffies(100));
5868c2ecf20Sopenharmony_ci		/* Valid stream might not be present. */
5878c2ecf20Sopenharmony_ci		if (ret <= 0) {
5888c2ecf20Sopenharmony_ci			dev_dbg(dev->dev, "user data for channel %d timeout\n",
5898c2ecf20Sopenharmony_ci				channel);
5908c2ecf20Sopenharmony_ci			regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND);
5918c2ecf20Sopenharmony_ci			ret = ret ? : -ETIMEDOUT;
5928c2ecf20Sopenharmony_ci			goto unlock;
5938c2ecf20Sopenharmony_ci		} else {
5948c2ecf20Sopenharmony_ci			ret = 0;
5958c2ecf20Sopenharmony_ci		}
5968c2ecf20Sopenharmony_ci	} else {
5978c2ecf20Sopenharmony_ci		/* Update software cache with last available data. */
5988c2ecf20Sopenharmony_ci		mchp_spdifrx_channel_user_data_read(dev, channel);
5998c2ecf20Sopenharmony_ci	}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	memcpy(uvalue->value.iec958.subcode, user_data->data,
6028c2ecf20Sopenharmony_ci	       sizeof(user_data->data));
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ciunlock:
6058c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
6068c2ecf20Sopenharmony_ci	return ret;
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic int mchp_spdifrx_subcode_ch1_get(struct snd_kcontrol *kcontrol,
6108c2ecf20Sopenharmony_ci					struct snd_ctl_elem_value *uvalue)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
6138c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	return mchp_spdifrx_subcode_ch_get(dev, 0, uvalue);
6168c2ecf20Sopenharmony_ci}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_cistatic int mchp_spdifrx_subcode_ch2_get(struct snd_kcontrol *kcontrol,
6198c2ecf20Sopenharmony_ci					struct snd_ctl_elem_value *uvalue)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
6228c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	return mchp_spdifrx_subcode_ch_get(dev, 1, uvalue);
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistatic int mchp_spdifrx_boolean_info(struct snd_kcontrol *kcontrol,
6288c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_info *uinfo)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
6318c2ecf20Sopenharmony_ci	uinfo->count = 1;
6328c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0;
6338c2ecf20Sopenharmony_ci	uinfo->value.integer.max = 1;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return 0;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic int mchp_spdifrx_ulock_get(struct snd_kcontrol *kcontrol,
6398c2ecf20Sopenharmony_ci				  struct snd_ctl_elem_value *uvalue)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
6428c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
6438c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
6448c2ecf20Sopenharmony_ci	u32 val;
6458c2ecf20Sopenharmony_ci	bool ulock_old = ctrl->ulock;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	/*
6508c2ecf20Sopenharmony_ci	 * The RSR.ULOCK has wrong value if both pclk and gclk are enabled
6518c2ecf20Sopenharmony_ci	 * and the receiver is disabled. Thus we take into account the
6528c2ecf20Sopenharmony_ci	 * dev->trigger_enabled here to return a real status.
6538c2ecf20Sopenharmony_ci	 */
6548c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
6558c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_RSR, &val);
6568c2ecf20Sopenharmony_ci		ctrl->ulock = !(val & SPDIFRX_RSR_ULOCK);
6578c2ecf20Sopenharmony_ci	} else {
6588c2ecf20Sopenharmony_ci		ctrl->ulock = 0;
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	uvalue->value.integer.value[0] = ctrl->ulock;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return ulock_old != ctrl->ulock;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic int mchp_spdifrx_badf_get(struct snd_kcontrol *kcontrol,
6698c2ecf20Sopenharmony_ci				 struct snd_ctl_elem_value *uvalue)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
6728c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
6738c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
6748c2ecf20Sopenharmony_ci	u32 val;
6758c2ecf20Sopenharmony_ci	bool badf_old = ctrl->badf;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	/*
6808c2ecf20Sopenharmony_ci	 * The RSR.ULOCK has wrong value if both pclk and gclk are enabled
6818c2ecf20Sopenharmony_ci	 * and the receiver is disabled. Thus we take into account the
6828c2ecf20Sopenharmony_ci	 * dev->trigger_enabled here to return a real status.
6838c2ecf20Sopenharmony_ci	 */
6848c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
6858c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_RSR, &val);
6868c2ecf20Sopenharmony_ci		ctrl->badf = !!(val & SPDIFRX_RSR_BADF);
6878c2ecf20Sopenharmony_ci	} else {
6888c2ecf20Sopenharmony_ci		ctrl->badf = 0;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	uvalue->value.integer.value[0] = ctrl->badf;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	return badf_old != ctrl->badf;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_cistatic int mchp_spdifrx_signal_get(struct snd_kcontrol *kcontrol,
6998c2ecf20Sopenharmony_ci				   struct snd_ctl_elem_value *uvalue)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
7028c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
7038c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
7048c2ecf20Sopenharmony_ci	u32 val = ~0U, loops = 10;
7058c2ecf20Sopenharmony_ci	int ret;
7068c2ecf20Sopenharmony_ci	bool signal_old = ctrl->signal;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	/*
7118c2ecf20Sopenharmony_ci	 * To get the signal we need to have receiver enabled. This
7128c2ecf20Sopenharmony_ci	 * could be enabled also from trigger() function thus we need to
7138c2ecf20Sopenharmony_ci	 * take care of not disabling the receiver when it runs.
7148c2ecf20Sopenharmony_ci	 */
7158c2ecf20Sopenharmony_ci	if (!dev->trigger_enabled) {
7168c2ecf20Sopenharmony_ci		ret = clk_prepare_enable(dev->gclk);
7178c2ecf20Sopenharmony_ci		if (ret)
7188c2ecf20Sopenharmony_ci			goto unlock;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci		regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
7218c2ecf20Sopenharmony_ci				   SPDIFRX_MR_RXEN_ENABLE);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci		/* Wait for RSR.ULOCK bit. */
7248c2ecf20Sopenharmony_ci		while (--loops) {
7258c2ecf20Sopenharmony_ci			regmap_read(dev->regmap, SPDIFRX_RSR, &val);
7268c2ecf20Sopenharmony_ci			if (!(val & SPDIFRX_RSR_ULOCK))
7278c2ecf20Sopenharmony_ci				break;
7288c2ecf20Sopenharmony_ci			usleep_range(100, 150);
7298c2ecf20Sopenharmony_ci		}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci		regmap_update_bits(dev->regmap, SPDIFRX_MR, SPDIFRX_MR_RXEN_MASK,
7328c2ecf20Sopenharmony_ci				   SPDIFRX_MR_RXEN_DISABLE);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		clk_disable_unprepare(dev->gclk);
7358c2ecf20Sopenharmony_ci	} else {
7368c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_RSR, &val);
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ciunlock:
7408c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	if (!(val & SPDIFRX_RSR_ULOCK))
7438c2ecf20Sopenharmony_ci		ctrl->signal = !(val & SPDIFRX_RSR_NOSIGNAL);
7448c2ecf20Sopenharmony_ci	else
7458c2ecf20Sopenharmony_ci		ctrl->signal = 0;
7468c2ecf20Sopenharmony_ci	uvalue->value.integer.value[0] = ctrl->signal;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return signal_old != ctrl->signal;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_cistatic int mchp_spdifrx_rate_info(struct snd_kcontrol *kcontrol,
7528c2ecf20Sopenharmony_ci				  struct snd_ctl_elem_info *uinfo)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7558c2ecf20Sopenharmony_ci	uinfo->count = 1;
7568c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0;
7578c2ecf20Sopenharmony_ci	uinfo->value.integer.max = 192000;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	return 0;
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic int mchp_spdifrx_rate_get(struct snd_kcontrol *kcontrol,
7638c2ecf20Sopenharmony_ci				 struct snd_ctl_elem_value *ucontrol)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
7668c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
7678c2ecf20Sopenharmony_ci	u32 val;
7688c2ecf20Sopenharmony_ci	int rate;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	mutex_lock(&dev->mlock);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	/*
7738c2ecf20Sopenharmony_ci	 * The RSR.ULOCK has wrong value if both pclk and gclk are enabled
7748c2ecf20Sopenharmony_ci	 * and the receiver is disabled. Thus we take into account the
7758c2ecf20Sopenharmony_ci	 * dev->trigger_enabled here to return a real status.
7768c2ecf20Sopenharmony_ci	 */
7778c2ecf20Sopenharmony_ci	if (dev->trigger_enabled) {
7788c2ecf20Sopenharmony_ci		regmap_read(dev->regmap, SPDIFRX_RSR, &val);
7798c2ecf20Sopenharmony_ci		/* If the receiver is not locked, ISF data is invalid. */
7808c2ecf20Sopenharmony_ci		if (val & SPDIFRX_RSR_ULOCK || !(val & SPDIFRX_RSR_IFS_MASK)) {
7818c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[0] = 0;
7828c2ecf20Sopenharmony_ci			goto unlock;
7838c2ecf20Sopenharmony_ci		}
7848c2ecf20Sopenharmony_ci	} else {
7858c2ecf20Sopenharmony_ci		/* Reveicer is not locked, IFS data is invalid. */
7868c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[0] = 0;
7878c2ecf20Sopenharmony_ci		goto unlock;
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	rate = clk_get_rate(dev->gclk);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = rate / (32 * SPDIFRX_RSR_IFS(val));
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ciunlock:
7958c2ecf20Sopenharmony_ci	mutex_unlock(&dev->mlock);
7968c2ecf20Sopenharmony_ci	return 0;
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_cistatic struct snd_kcontrol_new mchp_spdifrx_ctrls[] = {
8008c2ecf20Sopenharmony_ci	/* Channel status controller */
8018c2ecf20Sopenharmony_ci	{
8028c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8038c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT)
8048c2ecf20Sopenharmony_ci			" Channel 1",
8058c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8068c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8078c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_info,
8088c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_cs1_get,
8098c2ecf20Sopenharmony_ci	},
8108c2ecf20Sopenharmony_ci	{
8118c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8128c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT)
8138c2ecf20Sopenharmony_ci			" Channel 2",
8148c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8158c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8168c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_info,
8178c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_cs2_get,
8188c2ecf20Sopenharmony_ci	},
8198c2ecf20Sopenharmony_ci	{
8208c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8218c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
8228c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ,
8238c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_info,
8248c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_cs_mask,
8258c2ecf20Sopenharmony_ci	},
8268c2ecf20Sopenharmony_ci	/* User bits controller */
8278c2ecf20Sopenharmony_ci	{
8288c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8298c2ecf20Sopenharmony_ci		.name = "IEC958 Subcode Capture Default Channel 1",
8308c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8318c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8328c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_info,
8338c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_subcode_ch1_get,
8348c2ecf20Sopenharmony_ci	},
8358c2ecf20Sopenharmony_ci	{
8368c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8378c2ecf20Sopenharmony_ci		.name = "IEC958 Subcode Capture Default Channel 2",
8388c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8398c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8408c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_info,
8418c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_subcode_ch2_get,
8428c2ecf20Sopenharmony_ci	},
8438c2ecf20Sopenharmony_ci	/* Lock status */
8448c2ecf20Sopenharmony_ci	{
8458c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8468c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Unlocked",
8478c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8488c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8498c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_boolean_info,
8508c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_ulock_get,
8518c2ecf20Sopenharmony_ci	},
8528c2ecf20Sopenharmony_ci	/* Bad format */
8538c2ecf20Sopenharmony_ci	{
8548c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8558c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE)"Bad Format",
8568c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8578c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8588c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_boolean_info,
8598c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_badf_get,
8608c2ecf20Sopenharmony_ci	},
8618c2ecf20Sopenharmony_ci	/* Signal */
8628c2ecf20Sopenharmony_ci	{
8638c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8648c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Signal",
8658c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8668c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8678c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_boolean_info,
8688c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_signal_get,
8698c2ecf20Sopenharmony_ci	},
8708c2ecf20Sopenharmony_ci	/* Sampling rate */
8718c2ecf20Sopenharmony_ci	{
8728c2ecf20Sopenharmony_ci		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
8738c2ecf20Sopenharmony_ci		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
8748c2ecf20Sopenharmony_ci		.access = SNDRV_CTL_ELEM_ACCESS_READ |
8758c2ecf20Sopenharmony_ci			SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8768c2ecf20Sopenharmony_ci		.info = mchp_spdifrx_rate_info,
8778c2ecf20Sopenharmony_ci		.get = mchp_spdifrx_rate_get,
8788c2ecf20Sopenharmony_ci	},
8798c2ecf20Sopenharmony_ci};
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic int mchp_spdifrx_dai_probe(struct snd_soc_dai *dai)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
8848c2ecf20Sopenharmony_ci	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
8858c2ecf20Sopenharmony_ci	int ch;
8868c2ecf20Sopenharmony_ci	int err;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	err = clk_prepare_enable(dev->pclk);
8898c2ecf20Sopenharmony_ci	if (err) {
8908c2ecf20Sopenharmony_ci		dev_err(dev->dev,
8918c2ecf20Sopenharmony_ci			"failed to enable the peripheral clock: %d\n", err);
8928c2ecf20Sopenharmony_ci		return err;
8938c2ecf20Sopenharmony_ci	}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	snd_soc_dai_init_dma_data(dai, NULL, &dev->capture);
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	/* Software reset the IP */
8988c2ecf20Sopenharmony_ci	regmap_write(dev->regmap, SPDIFRX_CR, SPDIFRX_CR_SWRST);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	/* Default configuration */
9018c2ecf20Sopenharmony_ci	regmap_write(dev->regmap, SPDIFRX_MR,
9028c2ecf20Sopenharmony_ci		     SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 |
9038c2ecf20Sopenharmony_ci		     SPDIFRX_MR_SBMODE_DISCARD |
9048c2ecf20Sopenharmony_ci		     SPDIFRX_MR_AUTORST_NOACTION |
9058c2ecf20Sopenharmony_ci		     SPDIFRX_MR_PACK_DISABLED);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	for (ch = 0; ch < SPDIFRX_CHANNELS; ch++) {
9088c2ecf20Sopenharmony_ci		init_completion(&ctrl->ch_stat[ch].done);
9098c2ecf20Sopenharmony_ci		init_completion(&ctrl->user_data[ch].done);
9108c2ecf20Sopenharmony_ci	}
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	/* Add controls */
9138c2ecf20Sopenharmony_ci	snd_soc_add_dai_controls(dai, mchp_spdifrx_ctrls,
9148c2ecf20Sopenharmony_ci				 ARRAY_SIZE(mchp_spdifrx_ctrls));
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	return 0;
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_cistatic int mchp_spdifrx_dai_remove(struct snd_soc_dai *dai)
9208c2ecf20Sopenharmony_ci{
9218c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev = snd_soc_dai_get_drvdata(dai);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	/* Disable interrupts */
9248c2ecf20Sopenharmony_ci	regmap_write(dev->regmap, SPDIFRX_IDR, GENMASK(14, 0));
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	clk_disable_unprepare(dev->pclk);
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	return 0;
9298c2ecf20Sopenharmony_ci}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver mchp_spdifrx_dai = {
9328c2ecf20Sopenharmony_ci	.name = "mchp-spdifrx",
9338c2ecf20Sopenharmony_ci	.probe	= mchp_spdifrx_dai_probe,
9348c2ecf20Sopenharmony_ci	.remove	= mchp_spdifrx_dai_remove,
9358c2ecf20Sopenharmony_ci	.capture = {
9368c2ecf20Sopenharmony_ci		.stream_name = "S/PDIF Capture",
9378c2ecf20Sopenharmony_ci		.channels_min = SPDIFRX_CHANNELS,
9388c2ecf20Sopenharmony_ci		.channels_max = SPDIFRX_CHANNELS,
9398c2ecf20Sopenharmony_ci		.rates = MCHP_SPDIF_RATES,
9408c2ecf20Sopenharmony_ci		.formats = MCHP_SPDIF_FORMATS,
9418c2ecf20Sopenharmony_ci	},
9428c2ecf20Sopenharmony_ci	.ops = &mchp_spdifrx_dai_ops,
9438c2ecf20Sopenharmony_ci};
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver mchp_spdifrx_component = {
9468c2ecf20Sopenharmony_ci	.name		= "mchp-spdifrx",
9478c2ecf20Sopenharmony_ci};
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cistatic const struct of_device_id mchp_spdifrx_dt_ids[] = {
9508c2ecf20Sopenharmony_ci	{
9518c2ecf20Sopenharmony_ci		.compatible = "microchip,sama7g5-spdifrx",
9528c2ecf20Sopenharmony_ci	},
9538c2ecf20Sopenharmony_ci	{ /* sentinel */ }
9548c2ecf20Sopenharmony_ci};
9558c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mchp_spdifrx_dt_ids);
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cistatic int mchp_spdifrx_probe(struct platform_device *pdev)
9588c2ecf20Sopenharmony_ci{
9598c2ecf20Sopenharmony_ci	struct mchp_spdifrx_dev *dev;
9608c2ecf20Sopenharmony_ci	struct resource *mem;
9618c2ecf20Sopenharmony_ci	struct regmap *regmap;
9628c2ecf20Sopenharmony_ci	void __iomem *base;
9638c2ecf20Sopenharmony_ci	int irq;
9648c2ecf20Sopenharmony_ci	int err;
9658c2ecf20Sopenharmony_ci	u32 vers;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	/* Get memory for driver data. */
9688c2ecf20Sopenharmony_ci	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
9698c2ecf20Sopenharmony_ci	if (!dev)
9708c2ecf20Sopenharmony_ci		return -ENOMEM;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	/* Map I/O registers. */
9738c2ecf20Sopenharmony_ci	base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
9748c2ecf20Sopenharmony_ci	if (IS_ERR(base))
9758c2ecf20Sopenharmony_ci		return PTR_ERR(base);
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	regmap = devm_regmap_init_mmio(&pdev->dev, base,
9788c2ecf20Sopenharmony_ci				       &mchp_spdifrx_regmap_config);
9798c2ecf20Sopenharmony_ci	if (IS_ERR(regmap))
9808c2ecf20Sopenharmony_ci		return PTR_ERR(regmap);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	/* Request IRQ. */
9838c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
9848c2ecf20Sopenharmony_ci	if (irq < 0)
9858c2ecf20Sopenharmony_ci		return irq;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	err = devm_request_irq(&pdev->dev, irq, mchp_spdif_interrupt, 0,
9888c2ecf20Sopenharmony_ci			       dev_name(&pdev->dev), dev);
9898c2ecf20Sopenharmony_ci	if (err)
9908c2ecf20Sopenharmony_ci		return err;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	/* Get the peripheral clock */
9938c2ecf20Sopenharmony_ci	dev->pclk = devm_clk_get(&pdev->dev, "pclk");
9948c2ecf20Sopenharmony_ci	if (IS_ERR(dev->pclk)) {
9958c2ecf20Sopenharmony_ci		err = PTR_ERR(dev->pclk);
9968c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to get the peripheral clock: %d\n",
9978c2ecf20Sopenharmony_ci			err);
9988c2ecf20Sopenharmony_ci		return err;
9998c2ecf20Sopenharmony_ci	}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	/* Get the generated clock */
10028c2ecf20Sopenharmony_ci	dev->gclk = devm_clk_get(&pdev->dev, "gclk");
10038c2ecf20Sopenharmony_ci	if (IS_ERR(dev->gclk)) {
10048c2ecf20Sopenharmony_ci		err = PTR_ERR(dev->gclk);
10058c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
10068c2ecf20Sopenharmony_ci			"failed to get the PMC generated clock: %d\n", err);
10078c2ecf20Sopenharmony_ci		return err;
10088c2ecf20Sopenharmony_ci	}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	/*
10118c2ecf20Sopenharmony_ci	 * Signal control need a valid rate on gclk. hw_params() configures
10128c2ecf20Sopenharmony_ci	 * it propertly but requesting signal before any hw_params() has been
10138c2ecf20Sopenharmony_ci	 * called lead to invalid value returned for signal. Thus, configure
10148c2ecf20Sopenharmony_ci	 * gclk at a valid rate, here, in initialization, to simplify the
10158c2ecf20Sopenharmony_ci	 * control path.
10168c2ecf20Sopenharmony_ci	 */
10178c2ecf20Sopenharmony_ci	clk_set_min_rate(dev->gclk, 48000 * SPDIFRX_GCLK_RATIO_MIN + 1);
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	mutex_init(&dev->mlock);
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	dev->dev = &pdev->dev;
10228c2ecf20Sopenharmony_ci	dev->regmap = regmap;
10238c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, dev);
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	dev->capture.addr	= (dma_addr_t)mem->start + SPDIFRX_RHR;
10268c2ecf20Sopenharmony_ci	dev->capture.maxburst	= 1;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
10298c2ecf20Sopenharmony_ci	if (err) {
10308c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to register PMC: %d\n", err);
10318c2ecf20Sopenharmony_ci		return err;
10328c2ecf20Sopenharmony_ci	}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	err = devm_snd_soc_register_component(&pdev->dev,
10358c2ecf20Sopenharmony_ci					      &mchp_spdifrx_component,
10368c2ecf20Sopenharmony_ci					      &mchp_spdifrx_dai, 1);
10378c2ecf20Sopenharmony_ci	if (err) {
10388c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "fail to register dai\n");
10398c2ecf20Sopenharmony_ci		return err;
10408c2ecf20Sopenharmony_ci	}
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	regmap_read(regmap, SPDIFRX_VERSION, &vers);
10438c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "hw version: %#lx\n", vers & SPDIFRX_VERSION_MASK);
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	return 0;
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_cistatic struct platform_driver mchp_spdifrx_driver = {
10498c2ecf20Sopenharmony_ci	.probe	= mchp_spdifrx_probe,
10508c2ecf20Sopenharmony_ci	.driver	= {
10518c2ecf20Sopenharmony_ci		.name	= "mchp_spdifrx",
10528c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(mchp_spdifrx_dt_ids),
10538c2ecf20Sopenharmony_ci	},
10548c2ecf20Sopenharmony_ci};
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_cimodule_platform_driver(mchp_spdifrx_driver);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ciMODULE_AUTHOR("Codrin Ciubotariu <codrin.ciubotariu@microchip.com>");
10598c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Microchip S/PDIF RX Controller Driver");
10608c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1061