/* * Copyright 2012 Freescale Semiconductor, Inc. * Copyright 2012 Linaro Ltd. * * 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 #include #include #include #include #include #include #include #include "imx-audmux.h" #define DAI_NAME_SIZE 32 #define MUX_PORT_MAX 7 struct imx_es8328_data { struct device *dev; struct snd_soc_dai_link dai; struct snd_soc_card card; char codec_dai_name[DAI_NAME_SIZE]; char platform_name[DAI_NAME_SIZE]; int jack_gpio; }; static struct snd_soc_jack_gpio headset_jack_gpios[] = { { .gpio = -1, .name = "headset-gpio", .report = SND_JACK_HEADSET, .invert = 0, .debounce_time = 200, }, }; static struct snd_soc_jack headset_jack; static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd) { struct imx_es8328_data *data = container_of(rtd->card, struct imx_es8328_data, card); int ret = 0; /* Headphone jack detection */ if (gpio_is_valid(data->jack_gpio)) { ret = snd_soc_card_jack_new(rtd->card, "Headphone", SND_JACK_HEADPHONE | SND_JACK_BTN_0, &headset_jack, NULL, 0); if (ret) return ret; headset_jack_gpios[0].gpio = data->jack_gpio; ret = snd_soc_jack_add_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios), headset_jack_gpios); } return ret; } static const struct snd_soc_dapm_widget imx_es8328_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_SPK("Speaker", NULL), SND_SOC_DAPM_REGULATOR_SUPPLY("audio-amp", 1, 0), }; static int imx_es8328_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct device_node *ssi_np = NULL, *codec_np = NULL; struct platform_device *ssi_pdev; struct imx_es8328_data *data; u32 int_port, ext_port; int ret; struct device *dev = &pdev->dev; ret = of_property_read_u32(np, "mux-int-port", &int_port); if (ret) { dev_err(dev, "mux-int-port missing or invalid\n"); goto fail; } if (int_port > MUX_PORT_MAX || int_port == 0) { dev_err(dev, "mux-int-port: hardware only has %d mux ports\n", MUX_PORT_MAX); goto fail; } ret = of_property_read_u32(np, "mux-ext-port", &ext_port); if (ret) { dev_err(dev, "mux-ext-port missing or invalid\n"); goto fail; } if (ext_port > MUX_PORT_MAX || ext_port == 0) { dev_err(dev, "mux-ext-port: hardware only has %d mux ports\n", MUX_PORT_MAX); ret = -EINVAL; goto fail; } /* * The port numbering in the hardware manual starts at 1, while * the audmux API expects it starts at 0. */ int_port--; ext_port--; ret = imx_audmux_v2_configure_port(int_port, IMX_AUDMUX_V2_PTCR_SYN | IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | IMX_AUDMUX_V2_PTCR_TFSDIR | IMX_AUDMUX_V2_PTCR_TCLKDIR, IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); if (ret) { dev_err(dev, "audmux internal port setup failed\n"); return ret; } ret = imx_audmux_v2_configure_port(ext_port, IMX_AUDMUX_V2_PTCR_SYN, IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); if (ret) { dev_err(dev, "audmux external port setup failed\n"); return ret; } ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0); codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); if (!ssi_np || !codec_np) { dev_err(dev, "phandle missing or invalid\n"); ret = -EINVAL; goto fail; } ssi_pdev = of_find_device_by_node(ssi_np); if (!ssi_pdev) { dev_err(dev, "failed to find SSI platform device\n"); ret = -EINVAL; goto fail; } data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { ret = -ENOMEM; goto fail; } data->dev = dev; data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); data->dai.name = "hifi"; data->dai.stream_name = "hifi"; data->dai.codec_dai_name = "es8328-hifi-analog"; data->dai.codec_of_node = codec_np; data->dai.cpu_of_node = ssi_np; data->dai.platform_of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; data->card.dev = dev; data->card.dapm_widgets = imx_es8328_dapm_widgets; data->card.num_dapm_widgets = ARRAY_SIZE(imx_es8328_dapm_widgets); ret = snd_soc_of_parse_card_name(&data->card, "model"); if (ret) { dev_err(dev, "Unable to parse card name\n"); goto fail; } ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); if (ret) { dev_err(dev, "Unable to parse routing: %d\n", ret); goto fail; } data->card.num_links = 1; data->card.owner = THIS_MODULE; data->card.dai_link = &data->dai; ret = snd_soc_register_card(&data->card); if (ret) { dev_err(dev, "Unable to register: %d\n", ret); goto fail; } platform_set_drvdata(pdev, data); fail: of_node_put(ssi_np); of_node_put(codec_np); return ret; } static int imx_es8328_remove(struct platform_device *pdev) { struct imx_es8328_data *data = platform_get_drvdata(pdev); snd_soc_jack_free_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios), headset_jack_gpios); snd_soc_unregister_card(&data->card); return 0; } static const struct of_device_id imx_es8328_dt_ids[] = { { .compatible = "fsl,imx-audio-es8328", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_es8328_dt_ids); static struct platform_driver imx_es8328_driver = { .driver = { .name = "imx-es8328", .of_match_table = imx_es8328_dt_ids, }, .probe = imx_es8328_probe, .remove = imx_es8328_remove, }; module_platform_driver(imx_es8328_driver); MODULE_AUTHOR("Sean Cross "); MODULE_DESCRIPTION("Kosagi i.MX6 ES8328 ASoC machine driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:imx-audio-es8328"); 3e0b8dd2ddc104717'>1b9ec81258827001c869f003e0b8dd2ddc104717 (diff)
Merge tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC fixes from Arnd Bergmann: "This is a rather large set of bugfixes, as we just returned from the Christmas break. Most of these are relatively unimportant fixes for regressions introduced during the merge window, and about half of the changes are for mach-omap2. A couple of patches are just cleanups and dead code removal that I would not normally have considered for merging after -rc2, but I decided to take them along with the fixes this time. Notable fixes include: - removing the skeleton.dtsi include broke a number of machines, and we have to put empty /chosen nodes back to be able to pass kernel command lines as before - enabling Samsung platforms no longer hardwires CONFIG_HZ to 200, as it had been for no good reason for a long time" * tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (46 commits) MAINTAINERS: extend PSCI entry to cover the newly add PSCI checker code drivers: psci: annotate timer on stack to silence odebug messages ARM64: defconfig: enable DRM_MESON as module ARM64: dts: meson-gx: Add Graphic Controller nodes ARM64: dts: meson-gxl: fix GPIO include ARM: dts: imx6: Disable "weim" node in the dtsi files ARM: dts: qcom: apq8064: Add missing scm clock ARM: davinci: da8xx: Fix sleeping function called from invalid context ARM: davinci: Make __clk_{enable,disable} functions public ARM: davinci: da850: don't add emac clock to lookup table twice ARM: davinci: da850: fix infinite loop in clk_set_rate() ARM: i.MX: remove map_io callback ARM: dts: vf610-zii-dev-rev-b: Add missing newline ARM: dts: imx6qdl-nitrogen6x: remove duplicate iomux entry ARM: dts: imx31: fix AVIC base address ARM: dts: am572x-idk: Add gpios property to control PCIE_RESETn arm64: dts: vexpress: Support GICC_DIR operations ARM: dts: vexpress: Support GICC_DIR operations firmware: arm_scpi: fix reading sensor values on pre-1.0 SCPI firmwares arm64: dts: msm8996: Add required memory carveouts ...
Diffstat (limited to 'include/trace/events')