diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index f7191cc7ca5d..1bf56a052c08 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ struct rk_spdif_dev { struct snd_dmaengine_dai_dma_data playback_dma_data; struct regmap *regmap; + bool non_pcm; }; static const struct of_device_id rk_spdif_match[] __maybe_unused = { @@ -141,6 +143,20 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + if (spdif->non_pcm) { + cs[0] |= IEC958_AES0_NONAUDIO; + for (i = 0; i < AES_IEC958_STATUS_SIZE / 2; i++) + regmap_write(spdif->regmap, SPDIF_VLDFRn(i), 0xffffffff); + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_VFE_MASK, + SPDIF_CFGR_VFE_EN); + } else { + cs[0] &= ~IEC958_AES0_NONAUDIO; + for (i = 0; i < AES_IEC958_STATUS_SIZE / 2; i++) + regmap_write(spdif->regmap, SPDIF_VLDFRn(i), 0x0); + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_VFE_MASK, + SPDIF_CFGR_VFE_DIS); + } + for (i = 0; i < CS_BYTE / 2; i++) regmap_write(spdif->regmap, SPDIF_CHNSRn(i), CS_FRAME(fc[i])); @@ -275,8 +291,46 @@ static struct snd_soc_dai_driver rk_spdif_dai = { .ops = &rk_spdif_dai_ops, }; +static const char * const non_pcm_text[] = { "pcm", "non pcm" }; +static const struct soc_enum __maybe_unused non_pcm_switch = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(non_pcm_text), non_pcm_text); + +static int rk_spdif_non_pcm_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_spdif_dev *spdif = snd_soc_component_get_drvdata(component); + + ucontrol->value.enumerated.item[0] = spdif->non_pcm; + + return 0; +} + +static int rk_spdif_non_pcm_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_spdif_dev *spdif = snd_soc_component_get_drvdata(component); + bool non_pcm; + + non_pcm = !!ucontrol->value.enumerated.item[0]; + if (non_pcm == spdif->non_pcm) + return 0; + + spdif->non_pcm = non_pcm; + + return 1; +} + +static const struct snd_kcontrol_new rk_spdif_controls[] = { + SOC_ENUM_EXT("AUDIO MODE", non_pcm_switch, + rk_spdif_non_pcm_get, rk_spdif_non_pcm_put), +}; + static const struct snd_soc_component_driver rk_spdif_component = { .name = "rockchip-spdif", + .controls = rk_spdif_controls, + .num_controls = ARRAY_SIZE(rk_spdif_controls), .legacy_dai_naming = 1, }; diff --git a/sound/soc/rockchip/rockchip_spdif.h b/sound/soc/rockchip/rockchip_spdif.h index 5c656bd8fd18..4f089006fdf6 100644 --- a/sound/soc/rockchip/rockchip_spdif.h +++ b/sound/soc/rockchip/rockchip_spdif.h @@ -25,6 +25,10 @@ #define SPDIF_CFGR_CSE_EN BIT(6) #define SPDIF_CFGR_CSE_DIS 0 +#define SPDIF_CFGR_VFE_MASK BIT(4) +#define SPDIF_CFGR_VFE_EN BIT(4) +#define SPDIF_CFGR_VFE_DIS 0 + #define SPDIF_CFGR_ADJ_MASK BIT(3) #define SPDIF_CFGR_ADJ_LEFT_J BIT(3) #define SPDIF_CFGR_ADJ_RIGHT_J 0