]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00276567-7 ASoC: fsl: Add si476x machine driver
authorNicolin Chen <b42378@freescale.com>
Fri, 23 Aug 2013 11:55:00 +0000 (19:55 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 20 Aug 2014 08:06:23 +0000 (10:06 +0200)
Add si476x machine dirver for i.MX series SoC and binding doc.

Signed-off-by: Nicolin Chen <b42378@freescale.com>
Documentation/devicetree/bindings/sound/imx-audio-si476x.txt [new file with mode: 0644]
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/imx-si476x.c [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-si476x.txt b/Documentation/devicetree/bindings/sound/imx-audio-si476x.txt
new file mode 100644 (file)
index 0000000..53cd34a
--- /dev/null
@@ -0,0 +1,24 @@
+Freescale i.MX audio complex with si476x codec
+
+Required properties:
+- compatible : "fsl,imx-audio-si476x"
+- model : The user-visible name of this sound complex
+- ssi-controller : The phandle of the i.MX SSI controller
+
+- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
+- mux-ext-port : The external port of the i.MX audio muxer
+
+Note: The AUDMUX port numbering should start at 1, which is consistent with
+hardware manual.
+
+Example:
+
+sound {
+       compatible = "fsl,imx-audio-si476x",
+                    "fsl,imx-tuner-si476x";
+       model = "imx-radio-si476x";
+
+       ssi-controller = <&ssi1>;
+       mux-int-port = <2>;
+       mux-ext-port = <5>;
+};
index ec0215b22f1bb71aca095a189992844256513240..c8729814e337241ca97d19b09b2a095f01d802e7 100644 (file)
@@ -269,6 +269,18 @@ config SND_SOC_IMX_MC13783
        select SND_SOC_MC13783
        select SND_SOC_IMX_PCM_DMA
 
+config SND_SOC_IMX_SI476X
+       tristate "SoC Audio support for i.MX boards with si476x"
+       select SND_SOC_IMX_PCM_DMA
+       select SND_SOC_IMX_AUDMUX
+       select SND_SOC_FSL_SSI
+       select SND_SOC_FSL_UTILS
+       select SND_SOC_SI476X
+       help
+         SoC Audio support for i.MX boards with SI476x
+         Say Y if you want to add support for Soc audio for the AMFM Tuner chip
+         SI476x module.
+
 endif # SND_IMX_SOC
 
 endmenu
index a1b362a2e47c9b65182c7af45e97e7e5a73f699e..a5dd4c2588382cb05d0a894cf7c42fdd34d08e46 100644 (file)
@@ -53,6 +53,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-wm8962-objs := imx-wm8962.o
 snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-mc13783-objs := imx-mc13783.o
+snd-soc-imx-si476x-objs := imx-si476x.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
@@ -63,3 +64,4 @@ obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
 obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
 obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
 obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
+obj-$(CONFIG_SND_SOC_IMX_SI476X) += snd-soc-imx-si476x.o
diff --git a/sound/soc/fsl/imx-si476x.c b/sound/soc/fsl/imx-si476x.c
new file mode 100644 (file)
index 0000000..d3febf8
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <sound/soc.h>
+
+#include "imx-audmux.h"
+
+static int imx_audmux_config(int slave, int master)
+{
+       unsigned int ptcr, pdcr;
+       slave = slave - 1;
+       master = master - 1;
+
+       ptcr = IMX_AUDMUX_V2_PTCR_SYN |
+               IMX_AUDMUX_V2_PTCR_TFSDIR |
+               IMX_AUDMUX_V2_PTCR_TFSEL(slave) |
+               IMX_AUDMUX_V2_PTCR_TCLKDIR |
+               IMX_AUDMUX_V2_PTCR_TCSEL(slave);
+       pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
+       imx_audmux_v2_configure_port(master, ptcr, pdcr);
+
+       ptcr = IMX_AUDMUX_V2_PTCR_SYN;
+       pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
+       imx_audmux_v2_configure_port(slave, ptcr, pdcr);
+
+       return 0;
+}
+
+static int imx_si476x_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       u32 channels = params_channels(params);
+       u32 rate = params_rate(params);
+       u32 bclk = rate * channels * 32;
+       int ret = 0;
+
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+                       | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+       if (ret) {
+               dev_err(cpu_dai->dev, "failed to set dai fmt\n");
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, bclk, SND_SOC_CLOCK_OUT);
+       if (ret)
+               dev_err(cpu_dai->dev, "failed to set sysclk\n");
+
+       return ret;
+}
+
+static struct snd_soc_ops imx_si476x_ops = {
+       .hw_params = imx_si476x_hw_params,
+};
+
+static struct snd_soc_dai_link imx_dai = {
+       .name = "imx-si476x",
+       .stream_name = "imx-si476x",
+       .codec_dai_name = "si476x-codec",
+       .codec_name = "si476x-codec.99",
+       .ops = &imx_si476x_ops,
+};
+
+static struct snd_soc_card snd_soc_card_imx_3stack = {
+       .name = "imx-audio-si476x",
+       .dai_link = &imx_dai,
+       .num_links = 1,
+};
+
+static int imx_si476x_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &snd_soc_card_imx_3stack;
+       struct device_node *ssi_np, *np = pdev->dev.of_node;
+       struct platform_device *ssi_pdev;
+       int int_port, ext_port, ret;
+
+       ret = of_property_read_u32(np, "mux-int-port", &int_port);
+       if (ret) {
+               dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
+       if (ret) {
+               dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
+               return ret;
+       }
+
+       imx_audmux_config(int_port, ext_port);
+
+       ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+       if (!ssi_np) {
+               dev_err(&pdev->dev, "phandle missing or invalid\n");
+               return -EINVAL;
+       }
+
+       ssi_pdev = of_find_device_by_node(ssi_np);
+       if (!ssi_pdev) {
+               dev_err(&pdev->dev, "failed to find SSI platform device\n");
+               ret = -EINVAL;
+               goto end;
+       }
+
+       card->dev = &pdev->dev;
+       card->dai_link->cpu_dai_name = dev_name(&ssi_pdev->dev);
+       card->dai_link->platform_of_node = ssi_np;
+
+       ret = snd_soc_register_card(card);
+       if (ret)
+               dev_err(&pdev->dev, "Failed to register card: %d\n", ret);
+
+end:
+       if (ssi_np)
+               of_node_put(ssi_np);
+
+       return ret;
+}
+
+static int imx_si476x_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &snd_soc_card_imx_3stack;
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+static const struct of_device_id imx_si476x_dt_ids[] = {
+       { .compatible = "fsl,imx-audio-si476x", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_si476x_dt_ids);
+
+static struct platform_driver imx_si476x_driver = {
+       .driver = {
+               .name = "imx-tuner-si476x",
+               .owner = THIS_MODULE,
+               .of_match_table = imx_si476x_dt_ids,
+       },
+       .probe = imx_si476x_probe,
+       .remove = imx_si476x_remove,
+};
+
+module_platform_driver(imx_si476x_driver);
+
+/* Module information */
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ALSA SoC i.MX si476x");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-tuner-si476x");