summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/fsl_sai.c
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2020-04-15 13:14:26 +0800
committerShengjiu Wang <shengjiu.wang@nxp.com>2020-04-17 12:06:39 +0800
commit02d362f8d6dac7bd2357edf30420db8648860c77 (patch)
treed66812ad6a7215cfa6e78a86f2e4b01bb55c5da0 /sound/soc/fsl/fsl_sai.c
parentec7568ce2f85e3f86119cbedc482dc280b8151fa (diff)
MLK-23792-1: ASoC: fsl_sai: Monitor spdif rx clock in imx8mm
As we use one spare sai instance to monitor the spdif rx clock, there isn't belong to a sound card, we can't access the registers by amixer controls. So remove the amixer controls, replace them with the device attribute. And add an additional device attribute for enablement of monitorring spdif. This feature only be supported on imx8mm. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
Diffstat (limited to 'sound/soc/fsl/fsl_sai.c')
-rw-r--r--sound/soc/fsl/fsl_sai.c117
1 files changed, 32 insertions, 85 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 305af70660d9..0991e24fa45f 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -991,90 +991,6 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
.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, &regval);
-
- 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);
@@ -1113,7 +1029,6 @@ static int fsl_sai_dai_resume(struct snd_soc_dai *cpu_dai)
}
static struct snd_soc_dai_driver fsl_sai_dai = {
- .pcm_new = fsl_sai_pcm_new,
.probe = fsl_sai_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
@@ -1276,6 +1191,14 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
case FSL_SAI_RDR5:
case FSL_SAI_RDR6:
case FSL_SAI_RDR7:
+ case FSL_SAI_TTCTN:
+ case FSL_SAI_TTCTL:
+ case FSL_SAI_TBCTN:
+ case FSL_SAI_TTCAP:
+ case FSL_SAI_RTCTN:
+ case FSL_SAI_RTCTL:
+ case FSL_SAI_RBCTN:
+ case FSL_SAI_RTCAP:
return true;
default:
return false;
@@ -1600,6 +1523,25 @@ static int fsl_sai_probe(struct platform_device *pdev)
FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
}
+ if (sai->verid.timestamp_en) {
+ if (of_find_property(np, "fsl,sai-monitor-spdif", NULL) &&
+ of_device_is_compatible(np, "fsl,imx8mm-sai")) {
+ sai->regmap_gpr = syscon_regmap_lookup_by_compatible("fsl,imx8mm-iomuxc-gpr");
+ if (IS_ERR(sai->regmap_gpr))
+ dev_warn(&pdev->dev, "cannot find iomuxc registers\n");
+
+ sai->gpr_idx = of_alias_get_id(np, "sai");
+ if (sai->gpr_idx < 0)
+ dev_warn(&pdev->dev, "cannot find sai alias id\n");
+
+ if (sai->gpr_idx > 0 && !IS_ERR(sai->regmap_gpr))
+ sai->monitor_spdif = true;
+ }
+
+ if (sysfs_create_group(&pdev->dev.kobj, fsl_sai_get_dev_attribute_group(sai->monitor_spdif)))
+ dev_err(&pdev->dev, "fail to create sys group\n");
+ }
+
clk_disable_unprepare(sai->bus_clk);
sai->dma_params_rx.chan_name = "rx";
@@ -1628,8 +1570,13 @@ static int fsl_sai_probe(struct platform_device *pdev)
static int fsl_sai_remove(struct platform_device *pdev)
{
+ struct fsl_sai *sai = dev_get_drvdata(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
+ if (sai->verid.timestamp_en)
+ sysfs_remove_group(&pdev->dev.kobj, fsl_sai_get_dev_attribute_group(sai->monitor_spdif));
+
return 0;
}