1
0
Fork 0

MLK-17531-1: ASoC: fsl: sai: add support for SAI v3.01

a) Add support for new SAI (VERID, PARAM, MCTL, MDIV) registers
   available in i.MX 850d (SAI v3.00) and i.MX 845s (SAI v3.01).
b) Handle SAI MCLK register as function of SAI IP version.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
pull/10/head
Viorel Suman 2018-05-14 16:28:48 +03:00 committed by Jason Liu
parent 902f497c5c
commit 9365905648
2 changed files with 122 additions and 2 deletions

View File

@ -35,6 +35,8 @@
#define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
FSL_SAI_CSR_FEIE)
#define FSL_SAI_VERID_0301 0x0301
static struct fsl_sai_soc_data fsl_sai_vf610 = {
.imx = false,
/*dataline is mask, not index*/
@ -426,6 +428,48 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
return ret;
}
static int fsl_sai_check_ver(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
unsigned char offset = sai->soc->reg_offset;
unsigned int val;
if (FSL_SAI_TCSR(offset) == FSL_SAI_VERID)
return 0;
if (sai->verid.loaded)
return 0;
sai->verid.loaded = true;
regmap_read(sai->regmap, FSL_SAI_VERID, &val);
dev_dbg(cpu_dai->dev, "VERID: 0x%016X\n", val);
sai->verid.id = (val & FSL_SAI_VER_ID_MASK) >> FSL_SAI_VER_ID_SHIFT;
sai->verid.extfifo_en = (val & FSL_SAI_VER_EFIFO_EN);
sai->verid.timestamp_en = (val & FSL_SAI_VER_TSTMP_EN);
regmap_read(sai->regmap, FSL_SAI_PARAM, &val);
dev_dbg(cpu_dai->dev, "PARAM: 0x%016X\n", val);
/* max slots per frame, power of 2 */
sai->param.spf = 1 <<
((val & FSL_SAI_PAR_SPF_MASK) >> FSL_SAI_PAR_SPF_SHIFT);
/* words per fifo, power of 2 */
sai->param.wpf = 1 <<
((val & FSL_SAI_PAR_WPF_MASK) >> FSL_SAI_PAR_WPF_SHIFT);
/* number of datalines implemented */
sai->param.dln = val & FSL_SAI_PAR_DLN_MASK;
dev_dbg(cpu_dai->dev,
"Version: 0x%08X, SPF: %u, WPF: %u, DLN: %u\n",
sai->verid.id, sai->param.spf, sai->param.wpf, sai->param.dln
);
return 0;
}
static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
@ -506,6 +550,15 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
FSL_SAI_CR2_DIV_MASK, savediv - 1);
}
fsl_sai_check_ver(dai);
switch (sai->verid.id) {
case FSL_SAI_VERID_0301:
/* SAI is in master mode at this point, so enable MCLK */
regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
break;
}
dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n",
sai->mclk_id[tx], savediv, savesub);
@ -996,6 +1049,8 @@ static struct reg_default fsl_sai_v3_reg_defaults[] = {
{FSL_SAI_RCR4(8), 0},
{FSL_SAI_RCR5(8), 0},
{FSL_SAI_RMR, 0},
{FSL_SAI_MCTL, 0},
{FSL_SAI_MDIV, 0},
};
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
@ -1036,6 +1091,10 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_RFR6:
case FSL_SAI_RFR7:
case FSL_SAI_RMR:
case FSL_SAI_MCTL:
case FSL_SAI_MDIV:
case FSL_SAI_VERID:
case FSL_SAI_PARAM:
return true;
default:
return false;
@ -1051,6 +1110,8 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
return true;
switch (reg) {
case FSL_SAI_VERID:
case FSL_SAI_PARAM:
case FSL_SAI_TFR0:
case FSL_SAI_TFR1:
case FSL_SAI_TFR2:
@ -1103,6 +1164,8 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_TDR7:
case FSL_SAI_TMR:
case FSL_SAI_RMR:
case FSL_SAI_MCTL:
case FSL_SAI_MDIV:
return true;
default:
return false;
@ -1128,7 +1191,7 @@ static const struct regmap_config fsl_sai_v3_regmap_config = {
.reg_stride = 4,
.val_bits = 32,
.max_register = FSL_SAI_RMR,
.max_register = FSL_SAI_MDIV,
.reg_defaults = fsl_sai_v3_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(fsl_sai_v3_reg_defaults),
.readable_reg = fsl_sai_readable_reg,

View File

@ -20,6 +20,8 @@
SNDRV_PCM_FMTBIT_DSD_U32_LE)
/* SAI Register Map Register */
#define FSL_SAI_VERID 0x00 /* SAI Version ID Register */
#define FSL_SAI_PARAM 0x04 /* SAI Parameter Register */
#define FSL_SAI_TCSR(offset) (0x00 + offset) /* SAI Transmit Control */
#define FSL_SAI_TCR1(offset) (0x04 + offset) /* SAI Transmit Configuration 1 */
#define FSL_SAI_TCR2(offset) (0x08 + offset) /* SAI Transmit Configuration 2 */
@ -43,6 +45,11 @@
#define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO */
#define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO */
#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */
#define FSL_SAI_TTCTL 0x70 /* SAI Transmit Timestamp Control Register */
#define FSL_SAI_TTCTN 0x74 /* SAI Transmit Timestamp Counter Register */
#define FSL_SAI_TBCTN 0x78 /* SAI Transmit Bit Counter Register */
#define FSL_SAI_TTCAP 0x7C /* SAI Transmit Timestamp Capture */
#define FSL_SAI_RCSR(offset) (0x80 + offset) /* SAI Receive Control */
#define FSL_SAI_RCR1(offset) (0x84 + offset) /* SAI Receive Configuration 1 */
#define FSL_SAI_RCR2(offset) (0x88 + offset) /* SAI Receive Configuration 2 */
@ -65,8 +72,14 @@
#define FSL_SAI_RFR5 0xd4 /* SAI Receive FIFO */
#define FSL_SAI_RFR6 0xd8 /* SAI Receive FIFO */
#define FSL_SAI_RFR7 0xdc /* SAI Receive FIFO */
#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */
#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
#define FSL_SAI_RTCTL 0xf0 /* SAI Receive Timestamp Control Register */
#define FSL_SAI_RTCTN 0xf4 /* SAI Receive Timestamp Counter Register */
#define FSL_SAI_RBCTN 0xf8 /* SAI Receive Bit Counter Register */
#define FSL_SAI_RTCAP 0xfc /* SAI Receive Timestamp Capture */
#define FSL_SAI_MCTL 0x100 /* SAI MCLK Control Register */
#define FSL_SAI_MDIV 0x104 /* SAI MCLK Divide Register */
#define FSL_SAI_xCSR(tx, off) (tx ? FSL_SAI_TCSR(off) : FSL_SAI_RCSR(off))
#define FSL_SAI_xCR1(tx, off) (tx ? FSL_SAI_TCR1(off) : FSL_SAI_RCR1(off))
@ -114,6 +127,7 @@
#define FSL_SAI_CR2_MSEL(ID) ((ID) << 26)
#define FSL_SAI_CR2_BCP BIT(25)
#define FSL_SAI_CR2_BCD_MSTR BIT(24)
#define FSL_SAI_CR2_BCBP BIT(23) /* BCLK bypass */
#define FSL_SAI_CR2_DIV_MASK 0xff
/* SAI Transmit and Receive Configuration 3 Register */
@ -149,6 +163,33 @@
#define FSL_SAI_CR5_FBT(x) ((x) << 8)
#define FSL_SAI_CR5_FBT_MASK (0x1f << 8)
/* SAI MCLK Control Register */
#define FSL_SAI_MCTL_MCLK_EN BIT(30) /* MCLK Enable */
#define FSL_SAI_MCTL_MSEL_MASK (0x3 << 24)
#define FSL_SAI_MCTL_MSEL(ID) ((ID) << 24)
#define FSL_SAI_MCTL_MSEL_BUS 0
#define FSL_SAI_MCTL_MSEL_MCLK1 BIT(24)
#define FSL_SAI_MCTL_MSEL_MCLK2 BIT(25)
#define FSL_SAI_MCTL_MSEL_MCLK3 (BIT(24) | BIT(25))
#define FSL_SAI_MCTL_DIV_EN BIT(23)
#define FSL_SAI_MCTL_DIV_MASK 0xFF
/* SAI VERID Register */
#define FSL_SAI_VER_ID_SHIFT 16
#define FSL_SAI_VER_ID_MASK (0xFFFF << FSL_SAI_VER_ID_SHIFT)
#define FSL_SAI_VER_EFIFO_EN BIT(0)
#define FSL_SAI_VER_TSTMP_EN BIT(1)
/* SAI PARAM Register */
#define FSL_SAI_PAR_SPF_SHIFT 16
#define FSL_SAI_PAR_SPF_MASK (0x0F << FSL_SAI_PAR_SPF_SHIFT)
#define FSL_SAI_PAR_WPF_SHIFT 8
#define FSL_SAI_PAR_WPF_MASK (0x0F << FSL_SAI_PAR_WPF_SHIFT)
#define FSL_SAI_PAR_DLN_MASK (0x0F)
/* SAI MCLK Divide Register */
#define FSL_SAI_MDIV_MASK 0xFFFFF
/* SAI type */
#define FSL_SAI_DMA BIT(0)
#define FSL_SAI_USE_AC97 BIT(1)
@ -186,6 +227,19 @@ struct fsl_sai_soc_data {
bool constrain_period_size;
};
struct fsl_sai_verid {
u32 id;
bool timestamp_en;
bool extfifo_en;
bool loaded;
};
struct fsl_sai_param {
u32 spf; /* max slots per frame */
u32 wpf; /* words in fifo */
u32 dln; /* number of datalines implemented */
};
struct fsl_sai {
struct platform_device *pdev;
struct regmap *regmap;
@ -217,6 +271,9 @@ struct fsl_sai {
struct pm_qos_request pm_qos_req;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_state;
struct fsl_sai_verid verid;
struct fsl_sai_param param;
};
#define TX 1