// SPDX-License-Identifier: GPL-2.0
//
// Driver for Microchip S/PDIF RX Controller
//
// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
//
// Author: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
/*
* ---- S/PDIF Receiver Controller Register map ----
*/
#define SPDIFRX_CR 0x00 /* Control Register */
#define SPDIFRX_MR 0x04 /* Mode Register */
#define SPDIFRX_IER 0x10 /* Interrupt Enable Register */
#define SPDIFRX_IDR 0x14 /* Interrupt Disable Register */
#define SPDIFRX_IMR 0x18 /* Interrupt Mask Register */
#define SPDIFRX_ISR 0x1c /* Interrupt Status Register */
#define SPDIFRX_RSR 0x20 /* Status Register */
#define SPDIFRX_RHR 0x24 /* Holding Register */
#define SPDIFRX_CHSR(channel, reg) \
(0x30 + (channel) * 0x30 + (reg) * 4) /* Channel x Status Registers */
#define SPDIFRX_CHUD(channel, reg) \
(0x48 + (channel) * 0x30 + (reg) * 4) /* Channel x User Data Registers */
#define SPDIFRX_WPMR 0xE4 /* Write Protection Mode Register */
#define SPDIFRX_WPSR 0xE8 /* Write Protection Status Register */
#define SPDIFRX_VERSION 0xFC /* Version Register */
/*
* ---- Control Register (Write-only) ----
*/
#define SPDIFRX_CR_SWRST BIT(0) /* Software Reset */
/*
* ---- Mode Register (Read/Write) ----
*/
/* Receive Enable */
#define SPDIFRX_MR_RXEN_MASK GENMASK(0, 0)
#define SPDIFRX_MR_RXEN_DISABLE (0 << 0) /* SPDIF Receiver Disabled */
#define SPDIFRX_MR_RXEN_ENABLE (1 << 0) /* SPDIF Receiver Enabled */
/* Validity Bit Mode */
#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)
#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
(0 << 1) /* Load sample regardless of validity bit value */
#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
(1 << 1) /* Load sample only if validity bit is 0 */
/* Data Word Endian Mode */
#define SPDIFRX_MR_ENDIAN_MASK GENMASK(2, 2)
#define SPDIFRX_MR_ENDIAN_LITTLE (0 << 2) /* Little Endian Mode */
#define SPDIFRX_MR_ENDIAN_BIG (1 << 2) /* Big Endian Mode */
/* Parity Bit Mode */
#define SPDIFRX_MR_PBMODE_MASK GENMASK(3, 3)
#define SPDIFRX_MR_PBMODE_PARCHECK (0 << 3) /* Parity Check Enabled */
#define SPDIFRX_MR_PBMODE_NOPARCHECK (1 << 3) /* Parity Check Disabled */
/* Sample Data Width */
#define SPDIFRX_MR_DATAWIDTH_MASK GENMASK(5, 4)
#define SPDIFRX_MR_DATAWIDTH(width) \
(((6 - (width) / 4) << 4) & SPDIFRX_MR_DATAWIDTH_MASK)
/* Packed Data Mode in Receive Holding Register */
#define SPDIFRX_MR_PACK_MASK GENMASK(7, 7)
#define SPDIFRX_MR_PACK_DISABLED (0 << 7)
#define SPDIFRX_MR_PACK_ENABLED (1 << 7)
/* Start of Block Bit Mode */
#define SPDIFRX_MR_SBMODE_MASK GENMASK(8, 8)
#define SPDIFRX_MR_SBMODE_ALWAYS_LOAD (0 << 8)
#define SPDIFRX_MR_SBMODE_DISCARD (1 << 8)
/* Consecutive Preamble Error Threshold Automatic Restart */
#define SPDIFRX_MR_AUTORST_MASK GENMASK(24, 24)
#define SPDIFRX_MR_AUTORST_NOACTION (0 << 24)
#define SPDIFRX_MR_AUTORST_UNLOCK_ON_PRE_ERR (1 << 24)
/*
* ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----
*/
#define SPDIFRX_IR_RXRDY BIT(0)
#define SPDIFRX_IR_LOCKED BIT(1)
#define SPDIFRX_IR_LOSS BIT(2)
#define SPDIFRX_IR_BLOCKEND BIT(3)
#define SPDIFRX_IR_SFE BIT(4)
#define SPDIFRX_IR_PAR_ERR BIT(5)
#define SPDIFRX_IR_OVERRUN BIT(6)
#define SPDIFRX_IR_RXFULL BIT(7)
#define SPDIFRX_IR_CSC(ch) BIT((ch) + 8)
#define SPDIFRX_IR_SECE BIT(10)
#define SPDIFRX_IR_BLOCKST BIT(11)
#define SPDIFRX_IR_NRZ_ERR BIT(12)
#define SPDIFRX_IR_PRE_ERR BIT(13)
#define SPDIFRX_IR_CP_ERR BIT(14)
/*
* ---- Receiver Status Register (Read/Write) ----
*/
/* Enable Status */
#define SPDIFRX_RSR_ULOCK BIT(0)
#define SPDIFRX_RSR_BADF BIT(1)
#define SPDIFRX_RSR_LOWF BIT(2)
#define SPDIFRX_RSR_NOSIGNAL BIT(3)
#define SPDIFRX_RSR_IFS_MASK GENMASK(27, 16)
#define SPDIFRX_RSR_IFS(reg) \
(((reg) & SPDIFRX_RSR_IFS_MASK) >> 16)
/*
* ---- Version Register (Read-only) ----
*/
#define SPDIFRX_VERSION_MASK GENMASK(11, 0)
#define SPDIFRX_VERSION_MFN_MASK GENMASK(18, 16)
#define SPDIFRX_VERSION_MFN(reg) (((reg) & SPDIFRX_VERSION_MFN_MASK) >> 16)
static bool mchp_spdifrx_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case SPDIFRX_MR:
case SPDIFRX_IMR:
case SPDIFRX_ISR:
case SPDIFRX_RSR:
case SPDIFRX_CHSR(0, 0):
case SPDIFRX_CHSR(0, 1):
case SPDIFRX_CHSR(0, 2):
case SPDIFRX_CHSR(0, 3):
case SPDIFRX_CHSR(0, 4):
case SPDIFRX_CHSR(0, 5):
case SPDIFRX_CHUD(0, 0):
case SPDIFRX_CHUD(0, 1):
case SPDIFRX_CHUD(0, 2):
case SPDIFRX_CHUD(0, 3):
case SPDIFRX_CHUD(0, 4):
case SPDIFRX_CHUD(0, 5):
case SPDIFRX_CHSR(1, 0):
case SPDIFRX_CHSR(1, 1):
case SPDIFRX_CHSR(1, 2):
case SPDIFRX_CHSR(1, 3):
case SPDIFRX_CHSR(1, 4):
case SPDIFRX_CHSR(1, 5):
case SPDIFRX_CHUD(1, 0):
case SPDIFRX_CHUD(1, 1):
case SPDIFRX_CHUD(1, 2):
case SPDIFRX_CHUD(1, 3):
case SPDIFRX_CHUD(1, 4):
case SPDIFRX_CHUD(1, 5):
case SPDIFRX_WPMR:
case SPDIFRX_WPSR:
case SPDIFRX_VERSION:
return