From 63b81694ef7736849dcf7f7daf0becc6ebc02844 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Mon, 14 May 2018 16:28:48 +0300 Subject: [PATCH] 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 Reviewed-by: Daniel Baluta --- sound/soc/fsl/fsl_sai.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++- sound/soc/fsl/fsl_sai.h | 59 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 2 deletions(-) --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -29,6 +29,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*/ @@ -422,6 +424,48 @@ static int fsl_sai_set_dai_fmt(struct sn 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); @@ -502,6 +546,15 @@ static int fsl_sai_set_bclk(struct snd_s 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); @@ -1001,6 +1054,8 @@ static struct reg_default fsl_sai_v3_reg {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) @@ -1041,6 +1096,10 @@ static bool fsl_sai_readable_reg(struct 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; @@ -1056,6 +1115,8 @@ static bool fsl_sai_volatile_reg(struct return true; switch (reg) { + case FSL_SAI_VERID: + case FSL_SAI_PARAM: case FSL_SAI_TFR0: case FSL_SAI_TFR1: case FSL_SAI_TFR2: @@ -1108,6 +1169,8 @@ static bool fsl_sai_writeable_reg(struct 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; @@ -1133,7 +1196,7 @@ static const struct regmap_config fsl_sa .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, --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -17,6 +17,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 */ @@ -39,8 +41,12 @@ #define FSL_SAI_TFR5 0x54 /* SAI Transmit FIFO */ #define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO */ #define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO */ -#define FSL_SAI_TFR 0x40 /* 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 */ @@ -64,6 +70,13 @@ #define FSL_SAI_RFR6 0xd8 /* SAI Receive FIFO */ #define FSL_SAI_RFR7 0xdc /* 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)) @@ -109,6 +122,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 */ @@ -144,6 +158,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) @@ -181,6 +222,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; @@ -212,6 +266,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