| From 599235bd9d22c8cad90b0a7621b46d70cca94d31 Mon Sep 17 00:00:00 2001 |
| From: Viorel Suman <viorel.suman@nxp.com> |
| Date: Wed, 5 Jun 2019 13:46:32 +0000 |
| Subject: [PATCH] MLK-21957-3: ASoC: fsl_sai: add bitcount and timestamp |
| controls |
| |
| Bitcount and timestamp support added in SAI IP recently. |
| Add the related controls in SAI driver. |
| |
| Signed-off-by: Viorel Suman <viorel.suman@nxp.com> |
| --- |
| sound/soc/fsl/fsl_sai.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++- |
| sound/soc/fsl/fsl_sai.h | 6 +++ |
| 2 files changed, 102 insertions(+), 1 deletion(-) |
| |
| --- a/sound/soc/fsl/fsl_sai.c |
| +++ b/sound/soc/fsl/fsl_sai.c |
| @@ -992,6 +992,90 @@ static const struct snd_soc_dai_ops fsl_ |
| .shutdown = fsl_sai_shutdown, |
| }; |
| |
| +static const char |
| + *en_sl[] = { "Disabled", "Enabled", }, |
| + *inc_sl[] = { "On enabled and bitcount increment", "On enabled", }; |
| + |
| +static const struct soc_enum tstmp_enum[] = { |
| +SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 0, ARRAY_SIZE(en_sl), en_sl), |
| +SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 0, ARRAY_SIZE(en_sl), en_sl), |
| +SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl), |
| +SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl), |
| +}; |
| + |
| +int fsl_sai_get_reg(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
| + struct soc_mreg_control *mc = |
| + (struct soc_mreg_control *)kcontrol->private_value; |
| + bool pm_active = pm_runtime_active(component->dev); |
| + unsigned int regval; |
| + int ret; |
| + |
| + if (pm_active) |
| + regcache_cache_bypass(component->regmap, true); |
| + |
| + ret = snd_soc_component_read(component, mc->regbase, ®val); |
| + |
| + if (pm_active) |
| + regcache_cache_bypass(component->regmap, false); |
| + |
| + if (ret < 0) |
| + return ret; |
| + |
| + ucontrol->value.integer.value[0] = regval; |
| + |
| + return 0; |
| +} |
| + |
| +#define SOC_SINGLE_REG_RO(xname, xreg) \ |
| +{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \ |
| + .access = SNDRV_CTL_ELEM_ACCESS_READ | \ |
| + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
| + .info = snd_soc_info_xr_sx, .get = fsl_sai_get_reg, \ |
| + .private_value = (unsigned long)&(struct soc_mreg_control) \ |
| + { .regbase = xreg, .regcount = 1, .nbits = 32, \ |
| + .invert = 0, .min = 0, .max = 0xffffffff, } } |
| + |
| +static const struct snd_kcontrol_new fsl_sai_pb_ctrls[] = { |
| + SOC_ENUM("Playback Timestamp Control", tstmp_enum[0]), |
| + SOC_ENUM("Playback Timestamp Increment", tstmp_enum[2]), |
| + SOC_SINGLE("Playback Timestamp Reset", FSL_SAI_TTCTL, 8, 1, 0), |
| + SOC_SINGLE("Playback Bit Counter Reset", FSL_SAI_TTCTL, 9, 1, 0), |
| + SOC_SINGLE_REG_RO("Playback Timestamp Counter", FSL_SAI_TTCTN), |
| + SOC_SINGLE_REG_RO("Playback Bit Counter", FSL_SAI_TBCTN), |
| + SOC_SINGLE_REG_RO("Playback Latched Timestamp Counter", FSL_SAI_TTCAP), |
| +}; |
| + |
| +static const struct snd_kcontrol_new fsl_sai_cp_ctrls[] = { |
| + SOC_ENUM("Capture Timestamp Control", tstmp_enum[1]), |
| + SOC_ENUM("Capture Timestamp Increment", tstmp_enum[3]), |
| + SOC_SINGLE("Capture Timestamp Reset", FSL_SAI_RTCTL, 8, 1, 0), |
| + SOC_SINGLE("Capture Bit Counter Reset", FSL_SAI_RTCTL, 9, 1, 0), |
| + SOC_SINGLE_REG_RO("Capture Timestamp Counter", FSL_SAI_RTCTN), |
| + SOC_SINGLE_REG_RO("Capture Bit Counter", FSL_SAI_RBCTN), |
| + SOC_SINGLE_REG_RO("Capture Latched Timestamp Counter", FSL_SAI_RTCAP), |
| +}; |
| + |
| +static int fsl_sai_pcm_new(struct snd_soc_pcm_runtime *rtd, |
| + struct snd_soc_dai *dai) |
| +{ |
| + struct fsl_sai *sai = dev_get_drvdata(dai->dev); |
| + struct snd_pcm *pcm = rtd->pcm; |
| + bool ts_enabled = sai->verid.timestamp_en; |
| + struct snd_soc_component *comp = dai->component; |
| + |
| + if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) |
| + snd_soc_add_component_controls(comp, fsl_sai_pb_ctrls, |
| + ARRAY_SIZE(fsl_sai_pb_ctrls)); |
| + |
| + if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) |
| + snd_soc_add_component_controls(comp, fsl_sai_cp_ctrls, |
| + ARRAY_SIZE(fsl_sai_cp_ctrls)); |
| + return 0; |
| +} |
| + |
| static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) |
| { |
| struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); |
| @@ -1030,6 +1114,7 @@ static int fsl_sai_dai_resume(struct snd |
| } |
| |
| static struct snd_soc_dai_driver fsl_sai_dai_template = { |
| + .pcm_new = fsl_sai_pcm_new, |
| .probe = fsl_sai_dai_probe, |
| .playback = { |
| .stream_name = "CPU-Playback", |
| @@ -1054,7 +1139,7 @@ static struct snd_soc_dai_driver fsl_sai |
| }; |
| |
| static const struct snd_soc_component_driver fsl_component = { |
| - .name = "fsl-sai", |
| + .name = "fsl-sai", |
| }; |
| |
| static struct reg_default fsl_sai_v2_reg_defaults[] = { |
| @@ -1141,6 +1226,14 @@ static bool fsl_sai_readable_reg(struct |
| case FSL_SAI_MDIV: |
| case FSL_SAI_VERID: |
| case FSL_SAI_PARAM: |
| + case FSL_SAI_TTCTN: |
| + case FSL_SAI_RTCTN: |
| + case FSL_SAI_TTCTL: |
| + case FSL_SAI_TBCTN: |
| + case FSL_SAI_TTCAP: |
| + case FSL_SAI_RTCTL: |
| + case FSL_SAI_RBCTN: |
| + case FSL_SAI_RTCAP: |
| return true; |
| default: |
| return false; |
| @@ -1214,6 +1307,8 @@ static bool fsl_sai_writeable_reg(struct |
| case FSL_SAI_RMR: |
| case FSL_SAI_MCTL: |
| case FSL_SAI_MDIV: |
| + case FSL_SAI_TTCTL: |
| + case FSL_SAI_RTCTL: |
| return true; |
| default: |
| return false; |
| --- a/sound/soc/fsl/fsl_sai.h |
| +++ b/sound/soc/fsl/fsl_sai.h |
| @@ -210,6 +210,12 @@ |
| |
| #define SAI_FLAG_PMQOS BIT(0) |
| |
| +/* SAI timestamp and bitcounter */ |
| +#define FSL_SAI_xTCTL_TSEN BIT(0) |
| +#define FSL_SAI_xTCTL_TSINC BIT(1) |
| +#define FSL_SAI_xTCTL_RTSC BIT(8) |
| +#define FSL_SAI_xTCTL_RBC BIT(9) |
| + |
| struct fsl_sai_soc_data { |
| unsigned int fifo_depth; |
| unsigned int fifos; |