This commit add a sound codec driver for Silicon Laboratories 476x
series of AM/FM radio chips.
Signed-off-by: Andrey Smirnov
---
sound/soc/codecs/Kconfig |4 +
sound/soc/codecs/Makefile |2 +
sound/soc/codecs/si476x.c | 255 +
3 files changed, 261 insertions(+)
create mode 100644 sound/soc/codecs/si476x.c
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9f8e859..37b2911 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
+ select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -272,6 +273,9 @@ config SND_SOC_RT5631
config SND_SOC_SGTL5000
tristate
+config SND_SOC_SI476X
+ tristate
+
config SND_SOC_SIGMADSP
tristate
select CRC32
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 34148bb..d9ed4e4 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -44,6 +44,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-tx-objs := spdif_transciever.o
snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -161,6 +162,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF)+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644
index 000..38145ba
--- /dev/null
+++ b/sound/soc/codecs/si476x.c
@@ -0,0 +1,255 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+enum si476x_audio_registers {
+ SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
+ SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE= 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+ SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11,
+ SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK((0b111 <<
SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+ (0b111 <<
SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b110)
+
+enum si476x_daudio_formats {
+ SI476X_DAUDIO_MODE_I2S = (0x0 << 1),
+ SI476X_DAUDIO_MODE_DSP_A= (0x6 << 1),
+ SI476X_DAUDIO_MODE_DSP_B= (0x7 << 1),
+ SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1),
+ SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1),
+
+ SI476X_DAUDIO_MODE_IB = (1 << 5),
+ SI476X_DAUDIO_MODE_IF = (1 << 6),
+};
+
+enum si476x_pcm_format {
+ SI476X_PCM_FORMAT_S8= 2,
+ SI476X_PCM_FORMAT_S16_LE= 4,
+ SI476X_PCM_FORMAT_S20_3LE = 5,
+ SI476X_PCM_FORMAT_S24_LE= 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_get_property(core, reg);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int val)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_set_property(core, reg, val);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ int err;
+ u16 format = 0;
+
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+ return -EINVAL;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ format |= SI476X_DAUDIO_MODE_DSP_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ format |= SI476X_DAUDIO_MODE_DSP_B;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ format |= SI476X_DAUDIO_MODE_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ format |= SI476X_DAUDIO_MODE_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format |= SI476X_DAU