document.write('<script src="https://cdn.jsdelivr.net/highlight.js/9.0.0/highlight.min.js" type="text/javascript"></script>');
document.write('<link media="all" type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/9.0.0/styles/default.min.css">');
document.write('<link media="all" type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/9.0.0/styles/tomorrow.min.css">');
document.write('<style>#pastee-NVViP3MFuhVKzts1-content { margin-top: 0px !important; background-color: #f7f7f9; border: 1px solid #e1e1e8; white-space: pre-wrap; } #pastee-NVViP3MFuhVKzts1-content > code { margin-top: 0px !important; }</style>');
document.write('Paste provided by <a href="https://pastee.dev">Paste.ee</a> - <a href="https://pastee.dev/p/VuZbg">View Original</a> - <a href="https://pastee.dev/r/VuZbg/0">View Raw</a> - <a href="https://pastee.dev/d/VuZbg/0">Download</a><br />');
document.write('<pre id="pastee-NVViP3MFuhVKzts1-content"><code>/*\n * Copyright (c) 2015 exceet electronics GmbH\n * Author: Frieder Schrempf &lt;frieder.schrempf@exceet.de&gt;\n *\n * Recording not tested !!!\n *\n * Based on imx-wm8962.c\n * Copyright (C) 2012 Freescale Semiconductor, Inc.\n * Copyright (C) 2012 Linaro Ltd.\n *\n * The code contained herein is licensed under the GNU General Public\n * License. You may obtain a copy of the GNU General Public License\n * Version 2 or later at the following locations:\n *\n * http://www.opensource.org/licenses/gpl-license.html\n * http://www.gnu.org/copyleft/gpl.html\n */\n\n#include &lt;linux/module.h&gt;\n#include &lt;linux/of_platform.h&gt;\n#include &lt;linux/i2c.h&gt;\n#include &lt;linux/of_gpio.h&gt;\n#include &lt;linux/slab.h&gt;\n#include &lt;linux/gpio.h&gt;\n#include &lt;linux/clk.h&gt;\n#include &lt;sound/soc.h&gt;\n#include &lt;sound/jack.h&gt;\n#include &lt;sound/control.h&gt;\n#include &lt;sound/pcm_params.h&gt;\n#include &lt;sound/soc-dapm.h&gt;\n#include &lt;linux/pinctrl/consumer.h&gt;\n\n#include &quot;../codecs/wm8510.h&quot;\n#include &quot;imx-audmux.h&quot;\n\n#define DAI_NAME_SIZE	32\n\nstruct imx_wm8510_data {\n	struct snd_soc_dai_link dai;\n	struct snd_soc_card card;\n	char codec_dai_name[DAI_NAME_SIZE];\n	char platform_name[DAI_NAME_SIZE];\n	struct clk *codec_clk;\n	unsigned int mclk_frequency;\n	unsigned int mclk_source;\n};\n\nstruct imx_priv {\n	bool amic_mono;\n	bool dmic_mono;\n	struct snd_soc_codec *codec;\n	struct platform_device *pdev;\n	struct snd_pcm_substream *first_stream;\n	struct snd_card *snd_card;\n};\nstatic struct imx_priv card_priv;\n\nstatic const struct snd_soc_dapm_widget imx_wm8510_dapm_widgets[] = {\n	SND_SOC_DAPM_MIC(&quot;Int Mic&quot;, NULL),\n	SND_SOC_DAPM_SPK(&quot;Ext Spk&quot;, NULL),\n};\n\nstatic int imx_hifi_hw_params(struct snd_pcm_substream *substream,\n				     struct snd_pcm_hw_params *params)\n{\n	struct snd_soc_pcm_runtime *rtd = substream-&gt;private_data;\n	struct snd_soc_dai *cpu_dai = rtd-&gt;cpu_dai;\n	struct snd_soc_dai *codec_dai = rtd-&gt;codec_dai;\n	struct imx_priv *priv = &amp;card_priv;\n	struct device *dev = &amp;priv-&gt;pdev-&gt;dev;\n	struct snd_soc_card *card = codec_dai-&gt;codec-&gt;card;\n	struct imx_wm8510_data *data = snd_soc_card_get_drvdata(card);\n	unsigned int channels = params_channels(params);\n	unsigned int sample_rate = params_rate(params);\n	snd_pcm_format_t sample_format = params_format(params);\n	u32 dai_format, pll_out = 0, bclk = 0, mclk_div = 0;\n	int ret = 0;\n\n\n	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |\n	SND_SOC_DAIFMT_CBM_CFM;\n\n	/* set codec DAI configuration */\n	ret = snd_soc_dai_set_fmt(codec_dai, dai_format);\n	if (ret &lt; 0) {\n		pr_err(&quot;imx-wm8510: Failed to set CODEC DAI CONFIGURATION fmt (%d)\n&quot;, ret);\n		return ret;\n	}\n\n	/* set i.MX active slot mask */\n	snd_soc_dai_set_tdm_slot(cpu_dai,\n				 channels == 1 ? 0xfffffffe : 0xfffffffc,\n				 channels == 1 ? 0xfffffffe : 0xfffffffc,\n				 2, 32);\n\n	dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |\n		SND_SOC_DAIFMT_CBM_CFM;\n\n	/* set cpu DAI configuration */\n	ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);\n	if (ret &lt; 0) {\n		pr_err(&quot;imx-wm8510: Failed to set CPU DAI CONFIGURATION fmt (%d)\n&quot;, ret);\n		return ret;\n	}\n\n	/*\n	* Figure out PLL and BCLK dividers for WM8510\n	*/\n	switch (sample_rate) {\n	case 48000:\n		pll_out = 24576000;\n		mclk_div = WM8510_MCLKDIV_2;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	case 44100:\n		pll_out = 22579200;\n		mclk_div = WM8510_MCLKDIV_2;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	case 22050:\n		pll_out = 22579200;\n		mclk_div = WM8510_MCLKDIV_4;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	case 16000:\n		pll_out = 24576000;\n		mclk_div = WM8510_MCLKDIV_6;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	case 11025:\n		pll_out = 22579200;\n		mclk_div = WM8510_MCLKDIV_8;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	case 8000:\n		pll_out = 24576000;\n		mclk_div = WM8510_MCLKDIV_12;\n		bclk = WM8510_BCLKDIV_8;\n		break;\n\n	default:\n		pr_warning(&quot;imx-wm8510: Unsupported sample rate %d\n&quot;,sample_rate);\n		return -EINVAL;\n	}\n\n	ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);\n	if (ret &lt; 0) {\n		pr_warning(&quot;imx-wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n&quot;, ret);\n		return ret;\n	}\n\n	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, data-&gt;mclk_frequency, pll_out);\n	if (ret &lt; 0)\n		pr_err(&quot;imx-wm8510: Failed to start PLL: %d\n&quot;, ret);\n\n\n	ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);\n	if (ret &lt; 0) {\n		pr_warning(&quot;imx-wm8510: Failed to set CODEC MCLKDIV (%d)\n&quot;,ret);\n		return ret;\n	}\n\n	return 0;\n}\n\nstatic struct snd_soc_ops imx_hifi_ops = {\n	.hw_params = imx_hifi_hw_params,\n};\n\nstatic int imx_wm8510_probe(struct platform_device *pdev)\n{\n	struct device_node *np = pdev-&gt;dev.of_node;\n	struct device_node *cpu_np, *codec_np;\n	struct platform_device *cpu_pdev;\n	struct imx_priv *priv = &amp;card_priv;\n	struct i2c_client *codec_dev;\n	struct imx_wm8510_data *data;\n	int int_port, ext_port;\n	int ret;\n\n	priv-&gt;pdev = pdev;\n\n	cpu_np = of_parse_phandle(pdev-&gt;dev.of_node, &quot;cpu-dai&quot;, 0);\n	if (!cpu_np) {\n		dev_err(&amp;pdev-&gt;dev, &quot;cpu dai phandle missing or invalid\n&quot;);\n		ret = -EINVAL;\n		goto fail;\n	}\n\n	if (!strstr(cpu_np-&gt;name, &quot;ssi&quot;))\n		goto audmux_bypass;\n\n	ret = of_property_read_u32(np, &quot;mux-int-port&quot;, &amp;int_port);\n	if (ret) {\n		dev_err(&amp;pdev-&gt;dev, &quot;mux-int-port missing or invalid\n&quot;);\n		return ret;\n	}\n	ret = of_property_read_u32(np, &quot;mux-ext-port&quot;, &amp;ext_port);\n	if (ret) {\n		dev_err(&amp;pdev-&gt;dev, &quot;mux-ext-port missing or invalid\n&quot;);\n		return ret;\n	}\n\n	/*\n	 * The port numbering in the hardware manual starts at 1, while\n	 * the audmux API expects it starts at 0.\n	 */\n	int_port--;\n	ext_port--;\n	ret = imx_audmux_v2_configure_port(int_port,\n			IMX_AUDMUX_V2_PTCR_SYN |\n			IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |\n			IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |\n			IMX_AUDMUX_V2_PTCR_TFSDIR |\n			IMX_AUDMUX_V2_PTCR_TCLKDIR,\n			IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));\n	if (ret) {\n		dev_err(&amp;pdev-&gt;dev, &quot;audmux internal port setup failed\n&quot;);\n		return ret;\n	}\n	imx_audmux_v2_configure_port(ext_port,\n			IMX_AUDMUX_V2_PTCR_SYN,\n			IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));\n	if (ret) {\n		dev_err(&amp;pdev-&gt;dev, &quot;audmux external port setup failed\n&quot;);\n		return ret;\n	}\n\n	audmux_bypass:\n	codec_np = of_parse_phandle(pdev-&gt;dev.of_node, &quot;audio-codec&quot;, 0);\n	if (!codec_np) {\n		dev_err(&amp;pdev-&gt;dev, &quot;phandle missing or invalid\n&quot;);\n		ret = -EINVAL;\n		goto fail;\n	}\n\n	cpu_pdev = of_find_device_by_node(cpu_np);\n	if (!cpu_pdev) {\n		dev_err(&amp;pdev-&gt;dev, &quot;failed to find SSI platform device\n&quot;);\n		ret = -EINVAL;\n		goto fail;\n	}\n	codec_dev = of_find_i2c_device_by_node(codec_np);\n	if (!codec_dev) {\n		dev_err(&amp;pdev-&gt;dev, &quot;failed to find codec platform device\n&quot;);\n		ret = -EINVAL;\n		goto fail;\n	}\n\n	priv-&gt;first_stream = NULL;\n\n	data = devm_kzalloc(&amp;pdev-&gt;dev, sizeof(*data), GFP_KERNEL);\n	if (!data) {\n		ret = -ENOMEM;\n		goto fail;\n	}\n\n	\n	data-&gt;codec_clk = devm_clk_get(&amp;codec_dev-&gt;dev, &quot;audio_mclk&quot;);\n	if (IS_ERR(data-&gt;codec_clk)) {\n		ret = PTR_ERR(data-&gt;codec_clk);\n		dev_err(&amp;codec_dev-&gt;dev, &quot;failed to get codec clk: %d\n&quot;, ret);\n		goto fail;\n	}\n\n	ret = of_property_read_u32(codec_dev-&gt;dev.of_node, &quot;mclk_frequency&quot;, (u32 *) &amp;(data-&gt;mclk_frequency));\n	if (ret) {\n		dev_err(&amp;codec_dev-&gt;dev, &quot;mclk missing or invalid\n&quot;);\n		return ret;\n	}\n\n	data-&gt;mclk_frequency = clk_get_rate(data-&gt;codec_clk);\n	ret = clk_prepare_enable(data-&gt;codec_clk);\n	if (ret) {\n		dev_err(&amp;codec_dev-&gt;dev, &quot;failed to enable mclk\n&quot;);\n		return ret;\n	}\n\n	priv-&gt;amic_mono = of_property_read_bool(codec_np, &quot;amic-mono&quot;);\n	priv-&gt;dmic_mono = of_property_read_bool(codec_np, &quot;dmic-mono&quot;);\n\n	data-&gt;dai.name = &quot;WM8510&quot;;\n	data-&gt;dai.stream_name = &quot;WM8510 PCM&quot;;\n	data-&gt;dai.codec_dai_name = &quot;wm8510-hifi&quot;;\n	data-&gt;dai.codec_of_node = codec_np;\n	data-&gt;dai.cpu_dai_name = dev_name(&amp;cpu_pdev-&gt;dev);\n	data-&gt;dai.platform_of_node = cpu_np;\n	data-&gt;dai.ops = &amp;imx_hifi_ops;\n	data-&gt;dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |\n			    SND_SOC_DAIFMT_CBM_CFM;\n\n	data-&gt;card.dev = &amp;pdev-&gt;dev;\n	ret = snd_soc_of_parse_card_name(&amp;data-&gt;card, &quot;model&quot;);\n	if (ret)\n		goto fail;\n	ret = snd_soc_of_parse_audio_routing(&amp;data-&gt;card, &quot;audio-routing&quot;);\n	if (ret)\n		goto fail;\n	data-&gt;card.num_links = 1;\n	data-&gt;card.dai_link = &amp;data-&gt;dai;\n	data-&gt;card.dapm_widgets = imx_wm8510_dapm_widgets;\n	data-&gt;card.num_dapm_widgets = ARRAY_SIZE(imx_wm8510_dapm_widgets);\n\n	platform_set_drvdata(pdev, &amp;data-&gt;card);\n	snd_soc_card_set_drvdata(&amp;data-&gt;card, data);\n\n	ret = snd_soc_register_card(&amp;data-&gt;card);\n	if (ret) {\n		dev_err(&amp;pdev-&gt;dev, &quot;snd_soc_register_card failed (%d)\n&quot;, ret);\n		goto fail;\n	}\n\n	priv-&gt;snd_card = data-&gt;card.snd_card;\n\nfail:\n	if (cpu_np)\n		of_node_put(cpu_np);\n	if (codec_np)\n		of_node_put(codec_np);\n\n	return ret;\n}\n\nstatic int imx_wm8510_remove(struct platform_device *pdev)\n{\n	struct snd_soc_card *card = platform_get_drvdata(pdev);\n\n	snd_soc_unregister_card(card);\n\n	return 0;\n}\n\nstatic const struct of_device_id imx_wm8510_dt_ids[] = {\n	{ .compatible = &quot;fsl,imx-audio-wm8510&quot;, },\n	{ /* sentinel */ }\n};\nMODULE_DEVICE_TABLE(of, imx_wm8510_dt_ids);\n\nstatic struct platform_driver imx_wm8510_driver = {\n	.driver = {\n		.name = &quot;imx-wm8510&quot;,\n		.owner = THIS_MODULE,\n		.pm = &amp;snd_soc_pm_ops,\n		.of_match_table = imx_wm8510_dt_ids,\n	},\n	.probe = imx_wm8510_probe,\n	.remove = imx_wm8510_remove,\n};\nmodule_platform_driver(imx_wm8510_driver);\n\nMODULE_AUTHOR(&quot;exceet electronics GmbH&quot;);\nMODULE_DESCRIPTION(&quot;Freescale i.MX WM8510 ASoC machine driver&quot;);\nMODULE_LICENSE(&quot;GPL v2&quot;);\nMODULE_ALIAS(&quot;platform:imx-wm8510&quot;);\n</code></pre>');

function initEmbeddedPaste_NVViP3MFuhVKzts1() {
	hljs.highlightBlock(document.getElementById('pastee-NVViP3MFuhVKzts1-content'));
}

addEventListener('DOMContentLoaded', initEmbeddedPaste_NVViP3MFuhVKzts1, false);
addEventListener('load', initEmbeddedPaste_NVViP3MFuhVKzts1, false);