diff options
| author | Mark Brown <broonie@linaro.org> | 2013-08-30 06:04:23 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-08-30 06:04:23 -0400 |
| commit | 0f97b69a9feb1b0f21d25925715de142838fcc32 (patch) | |
| tree | 2e7556672199d5152af5c41387571aaef87ea4bf | |
| parent | 812e6bbf2caea2c2e55b5838f1148f4a577944ee (diff) | |
| parent | 2f82cdbafd53a01e3a3995a618b650653eed9c1a (diff) | |
Merge remote-tracking branch 'asoc/topic/fsl' into tmp
| -rw-r--r-- | Documentation/devicetree/bindings/sound/imx-audio-spdif.txt | 34 | ||||
| -rw-r--r-- | sound/soc/fsl/Kconfig | 10 | ||||
| -rw-r--r-- | sound/soc/fsl/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/fsl/fsl_spdif.c | 17 | ||||
| -rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 1 | ||||
| -rw-r--r-- | sound/soc/fsl/imx-spdif.c | 148 |
6 files changed, 197 insertions, 15 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..704e246f5b1e 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
| @@ -193,6 +193,16 @@ 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_SPDIF | ||
| 201 | help | ||
| 202 | SoC Audio support for i.MX boards with S/PDIF | ||
| 203 | Say Y if you want to add support for SoC audio on an i.MX board with | ||
| 204 | a S/DPDIF. | ||
| 205 | |||
| 196 | config SND_SOC_IMX_MC13783 | 206 | config SND_SOC_IMX_MC13783 |
| 197 | tristate "SoC Audio support for I.MX boards with mc13783" | 207 | tristate "SoC Audio support for I.MX boards with mc13783" |
| 198 | depends on MFD_MC13783 && ARM | 208 | 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/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 42a43820d993..e93dc0dfb0d9 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
| @@ -555,7 +555,6 @@ struct snd_soc_dai_ops fsl_spdif_dai_ops = { | |||
| 555 | 555 | ||
| 556 | 556 | ||
| 557 | /* | 557 | /* |
| 558 | * ============================================ | ||
| 559 | * FSL SPDIF IEC958 controller(mixer) functions | 558 | * FSL SPDIF IEC958 controller(mixer) functions |
| 560 | * | 559 | * |
| 561 | * Channel status get/put control | 560 | * Channel status get/put control |
| @@ -563,7 +562,6 @@ struct snd_soc_dai_ops fsl_spdif_dai_ops = { | |||
| 563 | * Valid bit value get control | 562 | * Valid bit value get control |
| 564 | * DPLL lock status get control | 563 | * DPLL lock status get control |
| 565 | * User bit sync mode selection control | 564 | * User bit sync mode selection control |
| 566 | * ============================================ | ||
| 567 | */ | 565 | */ |
| 568 | 566 | ||
| 569 | static int fsl_spdif_info(struct snd_kcontrol *kcontrol, | 567 | static int fsl_spdif_info(struct snd_kcontrol *kcontrol, |
| @@ -942,11 +940,7 @@ static const struct snd_soc_component_driver fsl_spdif_component = { | |||
| 942 | .name = "fsl-spdif", | 940 | .name = "fsl-spdif", |
| 943 | }; | 941 | }; |
| 944 | 942 | ||
| 945 | /* | 943 | /* FSL SPDIF REGMAP */ |
| 946 | * ================ | ||
| 947 | * FSL SPDIF REGMAP | ||
| 948 | * ================ | ||
| 949 | */ | ||
| 950 | 944 | ||
| 951 | static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) | 945 | static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) |
| 952 | { | 946 | { |
| @@ -1119,10 +1113,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
| 1119 | } | 1113 | } |
| 1120 | 1114 | ||
| 1121 | regs = devm_ioremap_resource(&pdev->dev, res); | 1115 | regs = devm_ioremap_resource(&pdev->dev, res); |
| 1122 | if (IS_ERR(regs)) { | 1116 | if (IS_ERR(regs)) |
| 1123 | dev_err(&pdev->dev, "could not map device resources\n"); | ||
| 1124 | return PTR_ERR(regs); | 1117 | return PTR_ERR(regs); |
| 1125 | } | ||
| 1126 | 1118 | ||
| 1127 | spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, | 1119 | spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, |
| 1128 | "core", regs, &fsl_spdif_regmap_config); | 1120 | "core", regs, &fsl_spdif_regmap_config); |
| @@ -1184,7 +1176,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
| 1184 | &spdif_priv->cpu_dai_drv, 1); | 1176 | &spdif_priv->cpu_dai_drv, 1); |
| 1185 | if (ret) { | 1177 | if (ret) { |
| 1186 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | 1178 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); |
| 1187 | goto error_dev; | 1179 | return ret; |
| 1188 | } | 1180 | } |
| 1189 | 1181 | ||
| 1190 | ret = imx_pcm_dma_init(pdev); | 1182 | ret = imx_pcm_dma_init(pdev); |
| @@ -1197,8 +1189,6 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
| 1197 | 1189 | ||
| 1198 | error_component: | 1190 | error_component: |
| 1199 | snd_soc_unregister_component(&pdev->dev); | 1191 | snd_soc_unregister_component(&pdev->dev); |
| 1200 | error_dev: | ||
| 1201 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 1202 | 1192 | ||
| 1203 | return ret; | 1193 | return ret; |
| 1204 | } | 1194 | } |
| @@ -1207,7 +1197,6 @@ static int fsl_spdif_remove(struct platform_device *pdev) | |||
| 1207 | { | 1197 | { |
| 1208 | imx_pcm_dma_exit(pdev); | 1198 | imx_pcm_dma_exit(pdev); |
| 1209 | snd_soc_unregister_component(&pdev->dev); | 1199 | snd_soc_unregister_component(&pdev->dev); |
| 1210 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 1211 | 1200 | ||
| 1212 | return 0; | 1201 | return 0; |
| 1213 | } | 1202 | } |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 5cf626c4dc96..c6b743978d5e 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
| @@ -1114,7 +1114,6 @@ error_dai: | |||
| 1114 | snd_soc_unregister_component(&pdev->dev); | 1114 | snd_soc_unregister_component(&pdev->dev); |
| 1115 | 1115 | ||
| 1116 | error_dev: | 1116 | error_dev: |
| 1117 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 1118 | device_remove_file(&pdev->dev, dev_attr); | 1117 | device_remove_file(&pdev->dev, dev_attr); |
| 1119 | 1118 | ||
| 1120 | error_clk: | 1119 | error_clk: |
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"); | ||
