diff options
| -rw-r--r-- | Documentation/devicetree/bindings/sound/imx-audio-spdif.txt | 34 | ||||
| -rw-r--r-- | sound/soc/fsl/Kconfig | 11 | ||||
| -rw-r--r-- | sound/soc/fsl/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/fsl/imx-spdif.c | 148 |
4 files changed, 195 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt new file mode 100644 index 000000000000..7d13479f9c3c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | Freescale i.MX audio complex with S/PDIF transceiver | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible : "fsl,imx-audio-spdif" | ||
| 6 | |||
| 7 | - model : The user-visible name of this sound complex | ||
| 8 | |||
| 9 | - spdif-controller : The phandle of the i.MX S/PDIF controller | ||
| 10 | |||
| 11 | |||
| 12 | Optional properties: | ||
| 13 | |||
| 14 | - spdif-out : This is a boolean property. If present, the transmitting | ||
| 15 | function of S/PDIF will be enabled, indicating there's a physical | ||
| 16 | S/PDIF out connector/jack on the board or it's connecting to some | ||
| 17 | other IP block, such as an HDMI encoder/display-controller. | ||
| 18 | |||
| 19 | - spdif-in : This is a boolean property. If present, the receiving | ||
| 20 | function of S/PDIF will be enabled, indicating there's a physical | ||
| 21 | S/PDIF in connector/jack on the board. | ||
| 22 | |||
| 23 | * Note: At least one of these two properties should be set in the DT binding. | ||
| 24 | |||
| 25 | |||
| 26 | Example: | ||
| 27 | |||
| 28 | sound-spdif { | ||
| 29 | compatible = "fsl,imx-audio-spdif"; | ||
| 30 | model = "imx-spdif"; | ||
| 31 | spdif-controller = <&spdif>; | ||
| 32 | spdif-out; | ||
| 33 | spdif-in; | ||
| 34 | }; | ||
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index cd088cc8c866..a70838034600 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
| @@ -193,6 +193,17 @@ config SND_SOC_IMX_SGTL5000 | |||
| 193 | Say Y if you want to add support for SoC audio on an i.MX board with | 193 | Say Y if you want to add support for SoC audio on an i.MX board with |
| 194 | a sgtl5000 codec. | 194 | a sgtl5000 codec. |
| 195 | 195 | ||
| 196 | config SND_SOC_IMX_SPDIF | ||
| 197 | tristate "SoC Audio support for i.MX boards with S/PDIF" | ||
| 198 | select SND_SOC_IMX_PCM_DMA | ||
| 199 | select SND_SOC_FSL_SPDIF | ||
| 200 | select SND_SOC_FSL_UTILS | ||
| 201 | select SND_SOC_SPDIF | ||
| 202 | help | ||
| 203 | SoC Audio support for i.MX boards with S/PDIF | ||
| 204 | Say Y if you want to add support for SoC audio on an i.MX board with | ||
| 205 | a S/DPDIF. | ||
| 206 | |||
| 196 | config SND_SOC_IMX_MC13783 | 207 | config SND_SOC_IMX_MC13783 |
| 197 | tristate "SoC Audio support for I.MX boards with mc13783" | 208 | tristate "SoC Audio support for I.MX boards with mc13783" |
| 198 | depends on MFD_MC13783 && ARM | 209 | depends on MFD_MC13783 && ARM |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 4b5970e014dd..e2aaff717f8a 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
| @@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | |||
| 45 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 45 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
| 46 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o | 46 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o |
| 47 | snd-soc-imx-wm8962-objs := imx-wm8962.o | 47 | snd-soc-imx-wm8962-objs := imx-wm8962.o |
| 48 | snd-soc-imx-spdif-objs :=imx-spdif.o | ||
| 48 | snd-soc-imx-mc13783-objs := imx-mc13783.o | 49 | snd-soc-imx-mc13783-objs := imx-mc13783.o |
| 49 | 50 | ||
| 50 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | 51 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o |
| @@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | |||
| 53 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 54 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
| 54 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o | 55 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o |
| 55 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o | 56 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o |
| 57 | obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o | ||
| 56 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o | 58 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o |
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c new file mode 100644 index 000000000000..816013b0ebba --- /dev/null +++ b/sound/soc/fsl/imx-spdif.c | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
| 3 | * | ||
| 4 | * The code contained herein is licensed under the GNU General Public | ||
| 5 | * License. You may obtain a copy of the GNU General Public License | ||
| 6 | * Version 2 or later at the following locations: | ||
| 7 | * | ||
| 8 | * http://www.opensource.org/licenses/gpl-license.html | ||
| 9 | * http://www.gnu.org/copyleft/gpl.html | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of_platform.h> | ||
| 14 | #include <sound/soc.h> | ||
| 15 | |||
| 16 | struct imx_spdif_data { | ||
| 17 | struct snd_soc_dai_link dai[2]; | ||
| 18 | struct snd_soc_card card; | ||
| 19 | struct platform_device *txdev; | ||
| 20 | struct platform_device *rxdev; | ||
| 21 | }; | ||
| 22 | |||
| 23 | static int imx_spdif_audio_probe(struct platform_device *pdev) | ||
| 24 | { | ||
| 25 | struct device_node *spdif_np, *np = pdev->dev.of_node; | ||
| 26 | struct imx_spdif_data *data; | ||
| 27 | int ret = 0, num_links = 0; | ||
| 28 | |||
| 29 | spdif_np = of_parse_phandle(np, "spdif-controller", 0); | ||
| 30 | if (!spdif_np) { | ||
| 31 | dev_err(&pdev->dev, "failed to find spdif-controller\n"); | ||
| 32 | ret = -EINVAL; | ||
| 33 | goto end; | ||
| 34 | } | ||
| 35 | |||
| 36 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
| 37 | if (!data) { | ||
| 38 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
| 39 | ret = -ENOMEM; | ||
| 40 | goto end; | ||
| 41 | } | ||
| 42 | |||
| 43 | if (of_property_read_bool(np, "spdif-out")) { | ||
| 44 | data->dai[num_links].name = "S/PDIF TX"; | ||
| 45 | data->dai[num_links].stream_name = "S/PDIF PCM Playback"; | ||
| 46 | data->dai[num_links].codec_dai_name = "dit-hifi"; | ||
| 47 | data->dai[num_links].codec_name = "spdif-dit"; | ||
| 48 | data->dai[num_links].cpu_of_node = spdif_np; | ||
| 49 | data->dai[num_links].platform_of_node = spdif_np; | ||
| 50 | num_links++; | ||
| 51 | |||
| 52 | data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0); | ||
| 53 | if (IS_ERR(data->txdev)) { | ||
| 54 | ret = PTR_ERR(data->txdev); | ||
| 55 | dev_err(&pdev->dev, "register dit failed: %d\n", ret); | ||
| 56 | goto end; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (of_property_read_bool(np, "spdif-in")) { | ||
| 61 | data->dai[num_links].name = "S/PDIF RX"; | ||
| 62 | data->dai[num_links].stream_name = "S/PDIF PCM Capture"; | ||
| 63 | data->dai[num_links].codec_dai_name = "dir-hifi"; | ||
| 64 | data->dai[num_links].codec_name = "spdif-dir"; | ||
| 65 | data->dai[num_links].cpu_of_node = spdif_np; | ||
| 66 | data->dai[num_links].platform_of_node = spdif_np; | ||
| 67 | num_links++; | ||
| 68 | |||
| 69 | data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0); | ||
| 70 | if (IS_ERR(data->rxdev)) { | ||
| 71 | ret = PTR_ERR(data->rxdev); | ||
| 72 | dev_err(&pdev->dev, "register dir failed: %d\n", ret); | ||
| 73 | goto error_dit; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | if (!num_links) { | ||
| 78 | dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); | ||
| 79 | goto error_dir; | ||
| 80 | } | ||
| 81 | |||
| 82 | data->card.dev = &pdev->dev; | ||
| 83 | data->card.num_links = num_links; | ||
| 84 | data->card.dai_link = data->dai; | ||
| 85 | |||
| 86 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | ||
| 87 | if (ret) | ||
| 88 | goto error_dir; | ||
| 89 | |||
| 90 | ret = snd_soc_register_card(&data->card); | ||
| 91 | if (ret) { | ||
| 92 | dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); | ||
| 93 | goto error_dir; | ||
| 94 | } | ||
| 95 | |||
| 96 | platform_set_drvdata(pdev, data); | ||
| 97 | |||
| 98 | goto end; | ||
| 99 | |||
| 100 | error_dir: | ||
| 101 | if (data->rxdev) | ||
| 102 | platform_device_unregister(data->rxdev); | ||
| 103 | error_dit: | ||
| 104 | if (data->txdev) | ||
| 105 | platform_device_unregister(data->txdev); | ||
| 106 | end: | ||
| 107 | if (spdif_np) | ||
| 108 | of_node_put(spdif_np); | ||
| 109 | |||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int imx_spdif_audio_remove(struct platform_device *pdev) | ||
| 114 | { | ||
| 115 | struct imx_spdif_data *data = platform_get_drvdata(pdev); | ||
| 116 | |||
| 117 | if (data->rxdev) | ||
| 118 | platform_device_unregister(data->rxdev); | ||
| 119 | if (data->txdev) | ||
| 120 | platform_device_unregister(data->txdev); | ||
| 121 | |||
| 122 | snd_soc_unregister_card(&data->card); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static const struct of_device_id imx_spdif_dt_ids[] = { | ||
| 128 | { .compatible = "fsl,imx-audio-spdif", }, | ||
| 129 | { /* sentinel */ } | ||
| 130 | }; | ||
| 131 | MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids); | ||
| 132 | |||
| 133 | static struct platform_driver imx_spdif_driver = { | ||
| 134 | .driver = { | ||
| 135 | .name = "imx-spdif", | ||
| 136 | .owner = THIS_MODULE, | ||
| 137 | .of_match_table = imx_spdif_dt_ids, | ||
| 138 | }, | ||
| 139 | .probe = imx_spdif_audio_probe, | ||
| 140 | .remove = imx_spdif_audio_remove, | ||
| 141 | }; | ||
| 142 | |||
| 143 | module_platform_driver(imx_spdif_driver); | ||
| 144 | |||
| 145 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
| 146 | MODULE_DESCRIPTION("Freescale i.MX S/PDIF machine driver"); | ||
| 147 | MODULE_LICENSE("GPL v2"); | ||
| 148 | MODULE_ALIAS("platform:imx-spdif"); | ||
