Re: [PATCH v2 6/6] Add a codec driver for SI476X MFD

2012-10-08 Thread Mark Brown
On Fri, Oct 05, 2012 at 06:55:02PM -0700, Andrey Smirnov wrote:

> This commit add a sound codec driver for Silicon Laboratories 476x
> series of AM/FM radio chips.

Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 6/6] Add a codec driver for SI476X MFD

2012-10-05 Thread Andrey Smirnov
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