xref: /openbmc/linux/sound/soc/ti/j721e-evm.c (revision 82d28b67)
16748d055SPeter Ujfalusi // SPDX-License-Identifier: GPL-2.0
26748d055SPeter Ujfalusi /*
36748d055SPeter Ujfalusi  *  Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
46748d055SPeter Ujfalusi  *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
56748d055SPeter Ujfalusi  */
66748d055SPeter Ujfalusi 
76748d055SPeter Ujfalusi #include <linux/clk.h>
86748d055SPeter Ujfalusi #include <linux/module.h>
96748d055SPeter Ujfalusi #include <linux/of.h>
106748d055SPeter Ujfalusi #include <linux/platform_device.h>
116748d055SPeter Ujfalusi 
126748d055SPeter Ujfalusi #include <sound/core.h>
136748d055SPeter Ujfalusi #include <sound/pcm.h>
146748d055SPeter Ujfalusi #include <sound/pcm_params.h>
156748d055SPeter Ujfalusi #include <sound/soc.h>
166748d055SPeter Ujfalusi 
176748d055SPeter Ujfalusi #include "davinci-mcasp.h"
186748d055SPeter Ujfalusi 
196748d055SPeter Ujfalusi /*
206748d055SPeter Ujfalusi  * Maximum number of configuration entries for prefixes:
216748d055SPeter Ujfalusi  * CPB: 2 (mcasp10 + codec)
226748d055SPeter Ujfalusi  * IVI: 3 (mcasp0 + 2x codec)
236748d055SPeter Ujfalusi  */
246748d055SPeter Ujfalusi #define J721E_CODEC_CONF_COUNT	5
256748d055SPeter Ujfalusi 
266748d055SPeter Ujfalusi #define J721E_AUDIO_DOMAIN_CPB	0
276748d055SPeter Ujfalusi #define J721E_AUDIO_DOMAIN_IVI	1
286748d055SPeter Ujfalusi 
296748d055SPeter Ujfalusi #define J721E_CLK_PARENT_48000	0
306748d055SPeter Ujfalusi #define J721E_CLK_PARENT_44100	1
316748d055SPeter Ujfalusi 
326748d055SPeter Ujfalusi #define J721E_MAX_CLK_HSDIV	128
336748d055SPeter Ujfalusi #define PCM1368A_MAX_SYSCLK	36864000
346748d055SPeter Ujfalusi 
356748d055SPeter Ujfalusi #define J721E_DAI_FMT		(SND_SOC_DAIFMT_RIGHT_J | \
366748d055SPeter Ujfalusi 				 SND_SOC_DAIFMT_NB_NF |   \
376748d055SPeter Ujfalusi 				 SND_SOC_DAIFMT_CBS_CFS)
386748d055SPeter Ujfalusi 
396748d055SPeter Ujfalusi enum j721e_board_type {
406748d055SPeter Ujfalusi 	J721E_BOARD_CPB = 1,
416748d055SPeter Ujfalusi 	J721E_BOARD_CPB_IVI,
426748d055SPeter Ujfalusi };
436748d055SPeter Ujfalusi 
446748d055SPeter Ujfalusi struct j721e_audio_match_data {
456748d055SPeter Ujfalusi 	enum j721e_board_type board_type;
466748d055SPeter Ujfalusi 	int num_links;
476748d055SPeter Ujfalusi 	unsigned int pll_rates[2];
486748d055SPeter Ujfalusi };
496748d055SPeter Ujfalusi 
506748d055SPeter Ujfalusi static unsigned int ratios_for_pcm3168a[] = {
516748d055SPeter Ujfalusi 	256,
526748d055SPeter Ujfalusi 	512,
536748d055SPeter Ujfalusi 	768,
546748d055SPeter Ujfalusi };
556748d055SPeter Ujfalusi 
566748d055SPeter Ujfalusi struct j721e_audio_clocks {
576748d055SPeter Ujfalusi 	struct clk *target;
586748d055SPeter Ujfalusi 	struct clk *parent[2];
596748d055SPeter Ujfalusi };
606748d055SPeter Ujfalusi 
616748d055SPeter Ujfalusi struct j721e_audio_domain {
626748d055SPeter Ujfalusi 	struct j721e_audio_clocks codec;
636748d055SPeter Ujfalusi 	struct j721e_audio_clocks mcasp;
646748d055SPeter Ujfalusi 	int parent_clk_id;
656748d055SPeter Ujfalusi 
666748d055SPeter Ujfalusi 	int active;
676748d055SPeter Ujfalusi 	unsigned int active_link;
686748d055SPeter Ujfalusi 	unsigned int rate;
696748d055SPeter Ujfalusi };
706748d055SPeter Ujfalusi 
716748d055SPeter Ujfalusi struct j721e_priv {
726748d055SPeter Ujfalusi 	struct device *dev;
736748d055SPeter Ujfalusi 	struct snd_soc_card card;
746748d055SPeter Ujfalusi 	struct snd_soc_dai_link *dai_links;
756748d055SPeter Ujfalusi 	struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT];
766748d055SPeter Ujfalusi 	struct snd_interval rate_range;
776748d055SPeter Ujfalusi 	const struct j721e_audio_match_data *match_data;
786748d055SPeter Ujfalusi 	u32 pll_rates[2];
796748d055SPeter Ujfalusi 	unsigned int hsdiv_rates[2];
806748d055SPeter Ujfalusi 
816748d055SPeter Ujfalusi 	struct j721e_audio_domain audio_domains[2];
826748d055SPeter Ujfalusi 
836748d055SPeter Ujfalusi 	struct mutex mutex;
846748d055SPeter Ujfalusi };
856748d055SPeter Ujfalusi 
866748d055SPeter Ujfalusi static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = {
876748d055SPeter Ujfalusi 	SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL),
886748d055SPeter Ujfalusi 	SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL),
896748d055SPeter Ujfalusi 	SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL),
906748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("CPB Line Out", NULL),
916748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL),
926748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL),
936748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("CPB Line In", NULL),
946748d055SPeter Ujfalusi };
956748d055SPeter Ujfalusi 
966748d055SPeter Ujfalusi static const struct snd_soc_dapm_route j721e_cpb_dapm_routes[] = {
976748d055SPeter Ujfalusi 	{"CPB Stereo HP 1", NULL, "codec-1 AOUT1L"},
986748d055SPeter Ujfalusi 	{"CPB Stereo HP 1", NULL, "codec-1 AOUT1R"},
996748d055SPeter Ujfalusi 	{"CPB Stereo HP 2", NULL, "codec-1 AOUT2L"},
1006748d055SPeter Ujfalusi 	{"CPB Stereo HP 2", NULL, "codec-1 AOUT2R"},
1016748d055SPeter Ujfalusi 	{"CPB Stereo HP 3", NULL, "codec-1 AOUT3L"},
1026748d055SPeter Ujfalusi 	{"CPB Stereo HP 3", NULL, "codec-1 AOUT3R"},
1036748d055SPeter Ujfalusi 	{"CPB Line Out", NULL, "codec-1 AOUT4L"},
1046748d055SPeter Ujfalusi 	{"CPB Line Out", NULL, "codec-1 AOUT4R"},
1056748d055SPeter Ujfalusi 
1066748d055SPeter Ujfalusi 	{"codec-1 AIN1L", NULL, "CPB Stereo Mic 1"},
1076748d055SPeter Ujfalusi 	{"codec-1 AIN1R", NULL, "CPB Stereo Mic 1"},
1086748d055SPeter Ujfalusi 	{"codec-1 AIN2L", NULL, "CPB Stereo Mic 2"},
1096748d055SPeter Ujfalusi 	{"codec-1 AIN2R", NULL, "CPB Stereo Mic 2"},
1106748d055SPeter Ujfalusi 	{"codec-1 AIN3L", NULL, "CPB Line In"},
1116748d055SPeter Ujfalusi 	{"codec-1 AIN3R", NULL, "CPB Line In"},
1126748d055SPeter Ujfalusi };
1136748d055SPeter Ujfalusi 
1146748d055SPeter Ujfalusi static const struct snd_soc_dapm_widget j721e_ivi_codec_a_dapm_widgets[] = {
1156748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI A Line Out 1", NULL),
1166748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI A Line Out 2", NULL),
1176748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI A Line Out 3", NULL),
1186748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI A Line Out 4", NULL),
1196748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("IVI A Stereo Mic 1", NULL),
1206748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("IVI A Stereo Mic 2", NULL),
1216748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI A Line In", NULL),
1226748d055SPeter Ujfalusi };
1236748d055SPeter Ujfalusi 
1246748d055SPeter Ujfalusi static const struct snd_soc_dapm_route j721e_codec_a_dapm_routes[] = {
1256748d055SPeter Ujfalusi 	{"IVI A Line Out 1", NULL, "codec-a AOUT1L"},
1266748d055SPeter Ujfalusi 	{"IVI A Line Out 1", NULL, "codec-a AOUT1R"},
1276748d055SPeter Ujfalusi 	{"IVI A Line Out 2", NULL, "codec-a AOUT2L"},
1286748d055SPeter Ujfalusi 	{"IVI A Line Out 2", NULL, "codec-a AOUT2R"},
1296748d055SPeter Ujfalusi 	{"IVI A Line Out 3", NULL, "codec-a AOUT3L"},
1306748d055SPeter Ujfalusi 	{"IVI A Line Out 3", NULL, "codec-a AOUT3R"},
1316748d055SPeter Ujfalusi 	{"IVI A Line Out 4", NULL, "codec-a AOUT4L"},
1326748d055SPeter Ujfalusi 	{"IVI A Line Out 4", NULL, "codec-a AOUT4R"},
1336748d055SPeter Ujfalusi 
1346748d055SPeter Ujfalusi 	{"codec-a AIN1L", NULL, "IVI A Stereo Mic 1"},
1356748d055SPeter Ujfalusi 	{"codec-a AIN1R", NULL, "IVI A Stereo Mic 1"},
1366748d055SPeter Ujfalusi 	{"codec-a AIN2L", NULL, "IVI A Stereo Mic 2"},
1376748d055SPeter Ujfalusi 	{"codec-a AIN2R", NULL, "IVI A Stereo Mic 2"},
1386748d055SPeter Ujfalusi 	{"codec-a AIN3L", NULL, "IVI A Line In"},
1396748d055SPeter Ujfalusi 	{"codec-a AIN3R", NULL, "IVI A Line In"},
1406748d055SPeter Ujfalusi };
1416748d055SPeter Ujfalusi 
1426748d055SPeter Ujfalusi static const struct snd_soc_dapm_widget j721e_ivi_codec_b_dapm_widgets[] = {
1436748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI B Line Out 1", NULL),
1446748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI B Line Out 2", NULL),
1456748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI B Line Out 3", NULL),
1466748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI B Line Out 4", NULL),
1476748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("IVI B Stereo Mic 1", NULL),
1486748d055SPeter Ujfalusi 	SND_SOC_DAPM_MIC("IVI B Stereo Mic 2", NULL),
1496748d055SPeter Ujfalusi 	SND_SOC_DAPM_LINE("IVI B Line In", NULL),
1506748d055SPeter Ujfalusi };
1516748d055SPeter Ujfalusi 
1526748d055SPeter Ujfalusi static const struct snd_soc_dapm_route j721e_codec_b_dapm_routes[] = {
1536748d055SPeter Ujfalusi 	{"IVI B Line Out 1", NULL, "codec-b AOUT1L"},
1546748d055SPeter Ujfalusi 	{"IVI B Line Out 1", NULL, "codec-b AOUT1R"},
1556748d055SPeter Ujfalusi 	{"IVI B Line Out 2", NULL, "codec-b AOUT2L"},
1566748d055SPeter Ujfalusi 	{"IVI B Line Out 2", NULL, "codec-b AOUT2R"},
1576748d055SPeter Ujfalusi 	{"IVI B Line Out 3", NULL, "codec-b AOUT3L"},
1586748d055SPeter Ujfalusi 	{"IVI B Line Out 3", NULL, "codec-b AOUT3R"},
1596748d055SPeter Ujfalusi 	{"IVI B Line Out 4", NULL, "codec-b AOUT4L"},
1606748d055SPeter Ujfalusi 	{"IVI B Line Out 4", NULL, "codec-b AOUT4R"},
1616748d055SPeter Ujfalusi 
1626748d055SPeter Ujfalusi 	{"codec-b AIN1L", NULL, "IVI B Stereo Mic 1"},
1636748d055SPeter Ujfalusi 	{"codec-b AIN1R", NULL, "IVI B Stereo Mic 1"},
1646748d055SPeter Ujfalusi 	{"codec-b AIN2L", NULL, "IVI B Stereo Mic 2"},
1656748d055SPeter Ujfalusi 	{"codec-b AIN2R", NULL, "IVI B Stereo Mic 2"},
1666748d055SPeter Ujfalusi 	{"codec-b AIN3L", NULL, "IVI B Line In"},
1676748d055SPeter Ujfalusi 	{"codec-b AIN3R", NULL, "IVI B Line In"},
1686748d055SPeter Ujfalusi };
1696748d055SPeter Ujfalusi 
1706748d055SPeter Ujfalusi static int j721e_configure_refclk(struct j721e_priv *priv,
1716748d055SPeter Ujfalusi 				  unsigned int audio_domain, unsigned int rate)
1726748d055SPeter Ujfalusi {
1736748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain = &priv->audio_domains[audio_domain];
1746748d055SPeter Ujfalusi 	unsigned int scki;
1756748d055SPeter Ujfalusi 	int ret = -EINVAL;
1766748d055SPeter Ujfalusi 	int i, clk_id;
1776748d055SPeter Ujfalusi 
1786748d055SPeter Ujfalusi 	if (!(rate % 8000) && priv->pll_rates[J721E_CLK_PARENT_48000])
1796748d055SPeter Ujfalusi 		clk_id = J721E_CLK_PARENT_48000;
1806748d055SPeter Ujfalusi 	else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_44100])
1816748d055SPeter Ujfalusi 		clk_id = J721E_CLK_PARENT_44100;
1826748d055SPeter Ujfalusi 	else
1836748d055SPeter Ujfalusi 		return ret;
1846748d055SPeter Ujfalusi 
1856748d055SPeter Ujfalusi 	for (i = 0; i < ARRAY_SIZE(ratios_for_pcm3168a); i++) {
1866748d055SPeter Ujfalusi 		scki = ratios_for_pcm3168a[i] * rate;
1876748d055SPeter Ujfalusi 
1886748d055SPeter Ujfalusi 		if (priv->pll_rates[clk_id] / scki <= J721E_MAX_CLK_HSDIV) {
1896748d055SPeter Ujfalusi 			ret = 0;
1906748d055SPeter Ujfalusi 			break;
1916748d055SPeter Ujfalusi 		}
1926748d055SPeter Ujfalusi 	}
1936748d055SPeter Ujfalusi 
1946748d055SPeter Ujfalusi 	if (ret) {
1956748d055SPeter Ujfalusi 		dev_err(priv->dev, "No valid clock configuration for %u Hz\n",
1966748d055SPeter Ujfalusi 			rate);
1976748d055SPeter Ujfalusi 		return ret;
1986748d055SPeter Ujfalusi 	}
1996748d055SPeter Ujfalusi 
200*82d28b67SPeter Ujfalusi 	if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) {
2016748d055SPeter Ujfalusi 		dev_dbg(priv->dev,
2026748d055SPeter Ujfalusi 			"%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
2036748d055SPeter Ujfalusi 			audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI",
2046748d055SPeter Ujfalusi 			rate,
2056748d055SPeter Ujfalusi 			clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15",
2066748d055SPeter Ujfalusi 			ratios_for_pcm3168a[i], scki);
2076748d055SPeter Ujfalusi 
2086748d055SPeter Ujfalusi 		if (domain->parent_clk_id != clk_id) {
2096748d055SPeter Ujfalusi 			ret = clk_set_parent(domain->codec.target,
2106748d055SPeter Ujfalusi 					     domain->codec.parent[clk_id]);
2116748d055SPeter Ujfalusi 			if (ret)
2126748d055SPeter Ujfalusi 				return ret;
2136748d055SPeter Ujfalusi 
2146748d055SPeter Ujfalusi 			ret = clk_set_parent(domain->mcasp.target,
2156748d055SPeter Ujfalusi 					     domain->mcasp.parent[clk_id]);
2166748d055SPeter Ujfalusi 			if (ret)
2176748d055SPeter Ujfalusi 				return ret;
2186748d055SPeter Ujfalusi 
2196748d055SPeter Ujfalusi 			domain->parent_clk_id = clk_id;
2206748d055SPeter Ujfalusi 		}
2216748d055SPeter Ujfalusi 
2226748d055SPeter Ujfalusi 		ret = clk_set_rate(domain->codec.target, scki);
2236748d055SPeter Ujfalusi 		if (ret) {
2246748d055SPeter Ujfalusi 			dev_err(priv->dev, "codec set rate failed for %u Hz\n",
2256748d055SPeter Ujfalusi 				scki);
2266748d055SPeter Ujfalusi 			return ret;
2276748d055SPeter Ujfalusi 		}
2286748d055SPeter Ujfalusi 
2296748d055SPeter Ujfalusi 		ret = clk_set_rate(domain->mcasp.target, scki);
2306748d055SPeter Ujfalusi 		if (!ret) {
2316748d055SPeter Ujfalusi 			priv->hsdiv_rates[domain->parent_clk_id] = scki;
2326748d055SPeter Ujfalusi 		} else {
2336748d055SPeter Ujfalusi 			dev_err(priv->dev, "mcasp set rate failed for %u Hz\n",
2346748d055SPeter Ujfalusi 				scki);
2356748d055SPeter Ujfalusi 			return ret;
2366748d055SPeter Ujfalusi 		}
2376748d055SPeter Ujfalusi 	}
2386748d055SPeter Ujfalusi 
2396748d055SPeter Ujfalusi 	return ret;
2406748d055SPeter Ujfalusi }
2416748d055SPeter Ujfalusi 
2426748d055SPeter Ujfalusi static int j721e_rule_rate(struct snd_pcm_hw_params *params,
2436748d055SPeter Ujfalusi 			   struct snd_pcm_hw_rule *rule)
2446748d055SPeter Ujfalusi {
2456748d055SPeter Ujfalusi 	struct snd_interval *t = rule->private;
2466748d055SPeter Ujfalusi 
2476748d055SPeter Ujfalusi 	return snd_interval_refine(hw_param_interval(params, rule->var), t);
2486748d055SPeter Ujfalusi }
2496748d055SPeter Ujfalusi 
2506748d055SPeter Ujfalusi static int j721e_audio_startup(struct snd_pcm_substream *substream)
2516748d055SPeter Ujfalusi {
25202cde14aSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
2536748d055SPeter Ujfalusi 	struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card);
2546748d055SPeter Ujfalusi 	unsigned int domain_id = rtd->dai_link->id;
2556748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain = &priv->audio_domains[domain_id];
2566748d055SPeter Ujfalusi 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
2576748d055SPeter Ujfalusi 	struct snd_soc_dai *codec_dai;
2586748d055SPeter Ujfalusi 	unsigned int active_rate;
2596748d055SPeter Ujfalusi 	int ret = 0;
2606748d055SPeter Ujfalusi 	int i;
2616748d055SPeter Ujfalusi 
2626748d055SPeter Ujfalusi 	mutex_lock(&priv->mutex);
2636748d055SPeter Ujfalusi 
2646748d055SPeter Ujfalusi 	domain->active++;
2656748d055SPeter Ujfalusi 
2666748d055SPeter Ujfalusi 	if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate)
2676748d055SPeter Ujfalusi 		active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate;
2686748d055SPeter Ujfalusi 	else
2696748d055SPeter Ujfalusi 		active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate;
2706748d055SPeter Ujfalusi 
2716748d055SPeter Ujfalusi 	if (active_rate)
2726748d055SPeter Ujfalusi 		ret = snd_pcm_hw_constraint_single(substream->runtime,
2736748d055SPeter Ujfalusi 						   SNDRV_PCM_HW_PARAM_RATE,
2746748d055SPeter Ujfalusi 						   active_rate);
2756748d055SPeter Ujfalusi 	else
2766748d055SPeter Ujfalusi 		ret = snd_pcm_hw_rule_add(substream->runtime, 0,
2776748d055SPeter Ujfalusi 					  SNDRV_PCM_HW_PARAM_RATE,
2786748d055SPeter Ujfalusi 					  j721e_rule_rate, &priv->rate_range,
2796748d055SPeter Ujfalusi 					  SNDRV_PCM_HW_PARAM_RATE, -1);
2806748d055SPeter Ujfalusi 
2816748d055SPeter Ujfalusi 
2826748d055SPeter Ujfalusi 	if (ret)
28378d2a05eSPeter Ujfalusi 		goto out;
2846748d055SPeter Ujfalusi 
2856748d055SPeter Ujfalusi 	/* Reset TDM slots to 32 */
2866748d055SPeter Ujfalusi 	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
2876748d055SPeter Ujfalusi 	if (ret && ret != -ENOTSUPP)
28878d2a05eSPeter Ujfalusi 		goto out;
2896748d055SPeter Ujfalusi 
2906748d055SPeter Ujfalusi 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
2916748d055SPeter Ujfalusi 		ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32);
2926748d055SPeter Ujfalusi 		if (ret && ret != -ENOTSUPP)
29378d2a05eSPeter Ujfalusi 			goto out;
2946748d055SPeter Ujfalusi 	}
2956748d055SPeter Ujfalusi 
29678d2a05eSPeter Ujfalusi 	if (ret == -ENOTSUPP)
29778d2a05eSPeter Ujfalusi 		ret = 0;
29878d2a05eSPeter Ujfalusi out:
29978d2a05eSPeter Ujfalusi 	if (ret)
30078d2a05eSPeter Ujfalusi 		domain->active--;
30178d2a05eSPeter Ujfalusi 	mutex_unlock(&priv->mutex);
30278d2a05eSPeter Ujfalusi 
30378d2a05eSPeter Ujfalusi 	return ret;
3046748d055SPeter Ujfalusi }
3056748d055SPeter Ujfalusi 
3066748d055SPeter Ujfalusi static int j721e_audio_hw_params(struct snd_pcm_substream *substream,
3076748d055SPeter Ujfalusi 				 struct snd_pcm_hw_params *params)
3086748d055SPeter Ujfalusi {
30902cde14aSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3106748d055SPeter Ujfalusi 	struct snd_soc_card *card = rtd->card;
3116748d055SPeter Ujfalusi 	struct j721e_priv *priv = snd_soc_card_get_drvdata(card);
3126748d055SPeter Ujfalusi 	unsigned int domain_id = rtd->dai_link->id;
3136748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain = &priv->audio_domains[domain_id];
3146748d055SPeter Ujfalusi 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
3156748d055SPeter Ujfalusi 	struct snd_soc_dai *codec_dai;
3166748d055SPeter Ujfalusi 	unsigned int sysclk_rate;
3176748d055SPeter Ujfalusi 	int slot_width = 32;
3186748d055SPeter Ujfalusi 	int ret;
3196748d055SPeter Ujfalusi 	int i;
3206748d055SPeter Ujfalusi 
3216748d055SPeter Ujfalusi 	mutex_lock(&priv->mutex);
3226748d055SPeter Ujfalusi 
3236748d055SPeter Ujfalusi 	if (domain->rate && domain->rate != params_rate(params)) {
3246748d055SPeter Ujfalusi 		ret = -EINVAL;
3256748d055SPeter Ujfalusi 		goto out;
3266748d055SPeter Ujfalusi 	}
3276748d055SPeter Ujfalusi 
3286748d055SPeter Ujfalusi 	if (params_width(params) == 16)
3296748d055SPeter Ujfalusi 		slot_width = 16;
3306748d055SPeter Ujfalusi 
3316748d055SPeter Ujfalusi 	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width);
3326748d055SPeter Ujfalusi 	if (ret && ret != -ENOTSUPP)
3336748d055SPeter Ujfalusi 		goto out;
3346748d055SPeter Ujfalusi 
3356748d055SPeter Ujfalusi 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
3366748d055SPeter Ujfalusi 		ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2,
3376748d055SPeter Ujfalusi 					       slot_width);
3386748d055SPeter Ujfalusi 		if (ret && ret != -ENOTSUPP)
33959b44649SWei Yongjun 			goto out;
3406748d055SPeter Ujfalusi 	}
3416748d055SPeter Ujfalusi 
3426748d055SPeter Ujfalusi 	ret = j721e_configure_refclk(priv, domain_id, params_rate(params));
3436748d055SPeter Ujfalusi 	if (ret)
3446748d055SPeter Ujfalusi 		goto out;
3456748d055SPeter Ujfalusi 
3466748d055SPeter Ujfalusi 	sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id];
3476748d055SPeter Ujfalusi 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
3486748d055SPeter Ujfalusi 		ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate,
3496748d055SPeter Ujfalusi 					     SND_SOC_CLOCK_IN);
3506748d055SPeter Ujfalusi 		if (ret && ret != -ENOTSUPP) {
3516748d055SPeter Ujfalusi 			dev_err(priv->dev,
3526748d055SPeter Ujfalusi 				"codec set_sysclk failed for %u Hz\n",
3536748d055SPeter Ujfalusi 				sysclk_rate);
3546748d055SPeter Ujfalusi 			goto out;
3556748d055SPeter Ujfalusi 		}
3566748d055SPeter Ujfalusi 	}
3576748d055SPeter Ujfalusi 
3586748d055SPeter Ujfalusi 	ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK,
3596748d055SPeter Ujfalusi 				     sysclk_rate, SND_SOC_CLOCK_IN);
3606748d055SPeter Ujfalusi 
3616748d055SPeter Ujfalusi 	if (ret && ret != -ENOTSUPP) {
3626748d055SPeter Ujfalusi 		dev_err(priv->dev, "mcasp set_sysclk failed for %u Hz\n",
3636748d055SPeter Ujfalusi 			sysclk_rate);
3646748d055SPeter Ujfalusi 	} else {
3656748d055SPeter Ujfalusi 		domain->rate = params_rate(params);
3666748d055SPeter Ujfalusi 		ret = 0;
3676748d055SPeter Ujfalusi 	}
3686748d055SPeter Ujfalusi 
3696748d055SPeter Ujfalusi out:
3706748d055SPeter Ujfalusi 	mutex_unlock(&priv->mutex);
3716748d055SPeter Ujfalusi 	return ret;
3726748d055SPeter Ujfalusi }
3736748d055SPeter Ujfalusi 
3746748d055SPeter Ujfalusi static void j721e_audio_shutdown(struct snd_pcm_substream *substream)
3756748d055SPeter Ujfalusi {
37602cde14aSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3776748d055SPeter Ujfalusi 	struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card);
3786748d055SPeter Ujfalusi 	unsigned int domain_id = rtd->dai_link->id;
3796748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain = &priv->audio_domains[domain_id];
3806748d055SPeter Ujfalusi 
3816748d055SPeter Ujfalusi 	mutex_lock(&priv->mutex);
3826748d055SPeter Ujfalusi 
3836748d055SPeter Ujfalusi 	domain->active--;
3846748d055SPeter Ujfalusi 	if (!domain->active) {
3856748d055SPeter Ujfalusi 		domain->rate = 0;
3866748d055SPeter Ujfalusi 		domain->active_link = 0;
3876748d055SPeter Ujfalusi 	}
3886748d055SPeter Ujfalusi 
3896748d055SPeter Ujfalusi 	mutex_unlock(&priv->mutex);
3906748d055SPeter Ujfalusi }
3916748d055SPeter Ujfalusi 
3926748d055SPeter Ujfalusi static const struct snd_soc_ops j721e_audio_ops = {
3936748d055SPeter Ujfalusi 	.startup = j721e_audio_startup,
3946748d055SPeter Ujfalusi 	.hw_params = j721e_audio_hw_params,
3956748d055SPeter Ujfalusi 	.shutdown = j721e_audio_shutdown,
3966748d055SPeter Ujfalusi };
3976748d055SPeter Ujfalusi 
3986748d055SPeter Ujfalusi static int j721e_audio_init(struct snd_soc_pcm_runtime *rtd)
3996748d055SPeter Ujfalusi {
4006748d055SPeter Ujfalusi 	struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card);
4016748d055SPeter Ujfalusi 	unsigned int domain_id = rtd->dai_link->id;
4026748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain = &priv->audio_domains[domain_id];
4036748d055SPeter Ujfalusi 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
4046748d055SPeter Ujfalusi 	struct snd_soc_dai *codec_dai;
4056748d055SPeter Ujfalusi 	unsigned int sysclk_rate;
4066748d055SPeter Ujfalusi 	int i, ret;
4076748d055SPeter Ujfalusi 
4086748d055SPeter Ujfalusi 	/* Set up initial clock configuration */
4096748d055SPeter Ujfalusi 	ret = j721e_configure_refclk(priv, domain_id, 48000);
4106748d055SPeter Ujfalusi 	if (ret)
4116748d055SPeter Ujfalusi 		return ret;
4126748d055SPeter Ujfalusi 
4136748d055SPeter Ujfalusi 	sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id];
4146748d055SPeter Ujfalusi 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
4156748d055SPeter Ujfalusi 		ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate,
4166748d055SPeter Ujfalusi 					     SND_SOC_CLOCK_IN);
4176748d055SPeter Ujfalusi 		if (ret && ret != -ENOTSUPP)
4186748d055SPeter Ujfalusi 			return ret;
4196748d055SPeter Ujfalusi 	}
4206748d055SPeter Ujfalusi 
4216748d055SPeter Ujfalusi 	ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK,
4226748d055SPeter Ujfalusi 				     sysclk_rate, SND_SOC_CLOCK_IN);
4236748d055SPeter Ujfalusi 	if (ret && ret != -ENOTSUPP)
4246748d055SPeter Ujfalusi 		return ret;
4256748d055SPeter Ujfalusi 
4266748d055SPeter Ujfalusi 	/* Set initial tdm slots */
4276748d055SPeter Ujfalusi 	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
4286748d055SPeter Ujfalusi 	if (ret && ret != -ENOTSUPP)
4296748d055SPeter Ujfalusi 		return ret;
4306748d055SPeter Ujfalusi 
4316748d055SPeter Ujfalusi 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
4326748d055SPeter Ujfalusi 		ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32);
4336748d055SPeter Ujfalusi 		if (ret && ret != -ENOTSUPP)
4346748d055SPeter Ujfalusi 			return ret;
4356748d055SPeter Ujfalusi 	}
4366748d055SPeter Ujfalusi 
4376748d055SPeter Ujfalusi 	return 0;
4386748d055SPeter Ujfalusi }
4396748d055SPeter Ujfalusi 
4406748d055SPeter Ujfalusi static int j721e_audio_init_ivi(struct snd_soc_pcm_runtime *rtd)
4416748d055SPeter Ujfalusi {
4426748d055SPeter Ujfalusi 	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
4436748d055SPeter Ujfalusi 
4446748d055SPeter Ujfalusi 	snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_a_dapm_widgets,
4456748d055SPeter Ujfalusi 				  ARRAY_SIZE(j721e_ivi_codec_a_dapm_widgets));
4466748d055SPeter Ujfalusi 	snd_soc_dapm_add_routes(dapm, j721e_codec_a_dapm_routes,
4476748d055SPeter Ujfalusi 				ARRAY_SIZE(j721e_codec_a_dapm_routes));
4486748d055SPeter Ujfalusi 	snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_b_dapm_widgets,
4496748d055SPeter Ujfalusi 				  ARRAY_SIZE(j721e_ivi_codec_b_dapm_widgets));
4506748d055SPeter Ujfalusi 	snd_soc_dapm_add_routes(dapm, j721e_codec_b_dapm_routes,
4516748d055SPeter Ujfalusi 				ARRAY_SIZE(j721e_codec_b_dapm_routes));
4526748d055SPeter Ujfalusi 
4536748d055SPeter Ujfalusi 	return j721e_audio_init(rtd);
4546748d055SPeter Ujfalusi }
4556748d055SPeter Ujfalusi 
4566748d055SPeter Ujfalusi static int j721e_get_clocks(struct device *dev,
4576748d055SPeter Ujfalusi 			    struct j721e_audio_clocks *clocks, char *prefix)
4586748d055SPeter Ujfalusi {
4596748d055SPeter Ujfalusi 	struct clk *parent;
4606748d055SPeter Ujfalusi 	char *clk_name;
4616748d055SPeter Ujfalusi 	int ret;
4626748d055SPeter Ujfalusi 
4636748d055SPeter Ujfalusi 	clocks->target = devm_clk_get(dev, prefix);
4646748d055SPeter Ujfalusi 	if (IS_ERR(clocks->target)) {
4656748d055SPeter Ujfalusi 		ret = PTR_ERR(clocks->target);
4666748d055SPeter Ujfalusi 		if (ret != -EPROBE_DEFER)
4676748d055SPeter Ujfalusi 			dev_err(dev, "failed to acquire %s: %d\n",
4686748d055SPeter Ujfalusi 				prefix, ret);
4696748d055SPeter Ujfalusi 		return ret;
4706748d055SPeter Ujfalusi 	}
4716748d055SPeter Ujfalusi 
4726748d055SPeter Ujfalusi 	clk_name = kasprintf(GFP_KERNEL, "%s-48000", prefix);
4736748d055SPeter Ujfalusi 	if (clk_name) {
4746748d055SPeter Ujfalusi 		parent = devm_clk_get(dev, clk_name);
4756748d055SPeter Ujfalusi 		kfree(clk_name);
4766748d055SPeter Ujfalusi 		if (IS_ERR(parent)) {
4776748d055SPeter Ujfalusi 			ret = PTR_ERR(parent);
4786748d055SPeter Ujfalusi 			if (ret == -EPROBE_DEFER)
4796748d055SPeter Ujfalusi 				return ret;
4806748d055SPeter Ujfalusi 
4816748d055SPeter Ujfalusi 			dev_dbg(dev, "no 48KHz parent for %s: %d\n", prefix, ret);
4826748d055SPeter Ujfalusi 			parent = NULL;
4836748d055SPeter Ujfalusi 		}
4846748d055SPeter Ujfalusi 		clocks->parent[J721E_CLK_PARENT_48000] = parent;
4856748d055SPeter Ujfalusi 	} else {
4866748d055SPeter Ujfalusi 		return -ENOMEM;
4876748d055SPeter Ujfalusi 	}
4886748d055SPeter Ujfalusi 
4896748d055SPeter Ujfalusi 	clk_name = kasprintf(GFP_KERNEL, "%s-44100", prefix);
4906748d055SPeter Ujfalusi 	if (clk_name) {
4916748d055SPeter Ujfalusi 		parent = devm_clk_get(dev, clk_name);
4926748d055SPeter Ujfalusi 		kfree(clk_name);
4936748d055SPeter Ujfalusi 		if (IS_ERR(parent)) {
4946748d055SPeter Ujfalusi 			ret = PTR_ERR(parent);
4956748d055SPeter Ujfalusi 			if (ret == -EPROBE_DEFER)
4966748d055SPeter Ujfalusi 				return ret;
4976748d055SPeter Ujfalusi 
4986748d055SPeter Ujfalusi 			dev_dbg(dev, "no 44.1KHz parent for %s: %d\n", prefix, ret);
4996748d055SPeter Ujfalusi 			parent = NULL;
5006748d055SPeter Ujfalusi 		}
5016748d055SPeter Ujfalusi 		clocks->parent[J721E_CLK_PARENT_44100] = parent;
5026748d055SPeter Ujfalusi 	} else {
5036748d055SPeter Ujfalusi 		return -ENOMEM;
5046748d055SPeter Ujfalusi 	}
5056748d055SPeter Ujfalusi 
5066748d055SPeter Ujfalusi 	if (!clocks->parent[J721E_CLK_PARENT_44100] &&
5076748d055SPeter Ujfalusi 	    !clocks->parent[J721E_CLK_PARENT_48000]) {
5086748d055SPeter Ujfalusi 		dev_err(dev, "At least one parent clock is needed for %s\n",
5096748d055SPeter Ujfalusi 			prefix);
5106748d055SPeter Ujfalusi 		return -EINVAL;
5116748d055SPeter Ujfalusi 	}
5126748d055SPeter Ujfalusi 
5136748d055SPeter Ujfalusi 	return 0;
5146748d055SPeter Ujfalusi }
5156748d055SPeter Ujfalusi 
5166748d055SPeter Ujfalusi static const struct j721e_audio_match_data j721e_cpb_data = {
5176748d055SPeter Ujfalusi 	.board_type = J721E_BOARD_CPB,
5186748d055SPeter Ujfalusi 	.num_links = 2, /* CPB pcm3168a */
5196748d055SPeter Ujfalusi 	.pll_rates = {
5206748d055SPeter Ujfalusi 		[J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */
5216748d055SPeter Ujfalusi 		[J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */
5226748d055SPeter Ujfalusi 	},
5236748d055SPeter Ujfalusi };
5246748d055SPeter Ujfalusi 
5256748d055SPeter Ujfalusi static const struct j721e_audio_match_data j721e_cpb_ivi_data = {
5266748d055SPeter Ujfalusi 	.board_type = J721E_BOARD_CPB_IVI,
5276748d055SPeter Ujfalusi 	.num_links = 4, /* CPB pcm3168a + 2x pcm3168a on IVI */
5286748d055SPeter Ujfalusi 	.pll_rates = {
5296748d055SPeter Ujfalusi 		[J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */
5306748d055SPeter Ujfalusi 		[J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */
5316748d055SPeter Ujfalusi 	},
5326748d055SPeter Ujfalusi };
5336748d055SPeter Ujfalusi 
53418c140f4SPeter Ujfalusi static const struct j721e_audio_match_data j7200_cpb_data = {
53518c140f4SPeter Ujfalusi 	.board_type = J721E_BOARD_CPB,
53618c140f4SPeter Ujfalusi 	.num_links = 2, /* CPB pcm3168a */
53718c140f4SPeter Ujfalusi 	.pll_rates = {
53818c140f4SPeter Ujfalusi 		[J721E_CLK_PARENT_48000] = 2359296000u, /* PLL4 */
53918c140f4SPeter Ujfalusi 	},
54018c140f4SPeter Ujfalusi };
54118c140f4SPeter Ujfalusi 
5426748d055SPeter Ujfalusi static const struct of_device_id j721e_audio_of_match[] = {
5436748d055SPeter Ujfalusi 	{
5446748d055SPeter Ujfalusi 		.compatible = "ti,j721e-cpb-audio",
5456748d055SPeter Ujfalusi 		.data = &j721e_cpb_data,
5466748d055SPeter Ujfalusi 	}, {
5476748d055SPeter Ujfalusi 		.compatible = "ti,j721e-cpb-ivi-audio",
5486748d055SPeter Ujfalusi 		.data = &j721e_cpb_ivi_data,
54918c140f4SPeter Ujfalusi 	}, {
55018c140f4SPeter Ujfalusi 		.compatible = "ti,j7200-cpb-audio",
55118c140f4SPeter Ujfalusi 		.data = &j7200_cpb_data,
5526748d055SPeter Ujfalusi 	},
5536748d055SPeter Ujfalusi 	{ },
5546748d055SPeter Ujfalusi };
5556748d055SPeter Ujfalusi MODULE_DEVICE_TABLE(of, j721e_audio_of_match);
5566748d055SPeter Ujfalusi 
5576748d055SPeter Ujfalusi static int j721e_calculate_rate_range(struct j721e_priv *priv)
5586748d055SPeter Ujfalusi {
5596748d055SPeter Ujfalusi 	const struct j721e_audio_match_data *match_data = priv->match_data;
5606748d055SPeter Ujfalusi 	struct j721e_audio_clocks *domain_clocks;
5616748d055SPeter Ujfalusi 	unsigned int min_rate, max_rate, pll_rate;
5626748d055SPeter Ujfalusi 	struct clk *pll;
5636748d055SPeter Ujfalusi 
5646748d055SPeter Ujfalusi 	domain_clocks = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].mcasp;
5656748d055SPeter Ujfalusi 
5666748d055SPeter Ujfalusi 	pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_44100]);
5676748d055SPeter Ujfalusi 	if (IS_ERR_OR_NULL(pll)) {
5686748d055SPeter Ujfalusi 		priv->pll_rates[J721E_CLK_PARENT_44100] =
5696748d055SPeter Ujfalusi 				match_data->pll_rates[J721E_CLK_PARENT_44100];
5706748d055SPeter Ujfalusi 	} else {
5716748d055SPeter Ujfalusi 		priv->pll_rates[J721E_CLK_PARENT_44100] = clk_get_rate(pll);
5726748d055SPeter Ujfalusi 		clk_put(pll);
5736748d055SPeter Ujfalusi 	}
5746748d055SPeter Ujfalusi 
5756748d055SPeter Ujfalusi 	pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_48000]);
5766748d055SPeter Ujfalusi 	if (IS_ERR_OR_NULL(pll)) {
5776748d055SPeter Ujfalusi 		priv->pll_rates[J721E_CLK_PARENT_48000] =
5786748d055SPeter Ujfalusi 				match_data->pll_rates[J721E_CLK_PARENT_48000];
5796748d055SPeter Ujfalusi 	} else {
5806748d055SPeter Ujfalusi 		priv->pll_rates[J721E_CLK_PARENT_48000] = clk_get_rate(pll);
5816748d055SPeter Ujfalusi 		clk_put(pll);
5826748d055SPeter Ujfalusi 	}
5836748d055SPeter Ujfalusi 
5846748d055SPeter Ujfalusi 	if (!priv->pll_rates[J721E_CLK_PARENT_44100] &&
5856748d055SPeter Ujfalusi 	    !priv->pll_rates[J721E_CLK_PARENT_48000]) {
5866748d055SPeter Ujfalusi 		dev_err(priv->dev, "At least one PLL is needed\n");
5876748d055SPeter Ujfalusi 		return -EINVAL;
5886748d055SPeter Ujfalusi 	}
5896748d055SPeter Ujfalusi 
5906748d055SPeter Ujfalusi 	if (priv->pll_rates[J721E_CLK_PARENT_44100])
5916748d055SPeter Ujfalusi 		pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100];
5926748d055SPeter Ujfalusi 	else
5936748d055SPeter Ujfalusi 		pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000];
5946748d055SPeter Ujfalusi 
5956748d055SPeter Ujfalusi 	min_rate = pll_rate / J721E_MAX_CLK_HSDIV;
5966748d055SPeter Ujfalusi 	min_rate /= ratios_for_pcm3168a[ARRAY_SIZE(ratios_for_pcm3168a) - 1];
5976748d055SPeter Ujfalusi 
5986748d055SPeter Ujfalusi 	if (priv->pll_rates[J721E_CLK_PARENT_48000])
5996748d055SPeter Ujfalusi 		pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000];
6006748d055SPeter Ujfalusi 	else
6016748d055SPeter Ujfalusi 		pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100];
6026748d055SPeter Ujfalusi 
6036748d055SPeter Ujfalusi 	if (pll_rate > PCM1368A_MAX_SYSCLK)
6046748d055SPeter Ujfalusi 		pll_rate = PCM1368A_MAX_SYSCLK;
6056748d055SPeter Ujfalusi 
6066748d055SPeter Ujfalusi 	max_rate = pll_rate / ratios_for_pcm3168a[0];
6076748d055SPeter Ujfalusi 
6086748d055SPeter Ujfalusi 	snd_interval_any(&priv->rate_range);
6096748d055SPeter Ujfalusi 	priv->rate_range.min = min_rate;
6106748d055SPeter Ujfalusi 	priv->rate_range.max = max_rate;
6116748d055SPeter Ujfalusi 
6126748d055SPeter Ujfalusi 	return 0;
6136748d055SPeter Ujfalusi }
6146748d055SPeter Ujfalusi 
6156748d055SPeter Ujfalusi static int j721e_soc_probe_cpb(struct j721e_priv *priv, int *link_idx,
6166748d055SPeter Ujfalusi 			       int *conf_idx)
6176748d055SPeter Ujfalusi {
6186748d055SPeter Ujfalusi 	struct device_node *node = priv->dev->of_node;
6196748d055SPeter Ujfalusi 	struct snd_soc_dai_link_component *compnent;
6206748d055SPeter Ujfalusi 	struct device_node *dai_node, *codec_node;
6216748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain;
6226748d055SPeter Ujfalusi 	int comp_count, comp_idx;
6236748d055SPeter Ujfalusi 	int ret;
6246748d055SPeter Ujfalusi 
6256748d055SPeter Ujfalusi 	dai_node = of_parse_phandle(node, "ti,cpb-mcasp", 0);
6266748d055SPeter Ujfalusi 	if (!dai_node) {
6276748d055SPeter Ujfalusi 		dev_err(priv->dev, "CPB McASP node is not provided\n");
6286748d055SPeter Ujfalusi 		return -EINVAL;
6296748d055SPeter Ujfalusi 	}
6306748d055SPeter Ujfalusi 
6316748d055SPeter Ujfalusi 	codec_node = of_parse_phandle(node, "ti,cpb-codec", 0);
6326748d055SPeter Ujfalusi 	if (!codec_node) {
6336748d055SPeter Ujfalusi 		dev_err(priv->dev, "CPB codec node is not provided\n");
6346748d055SPeter Ujfalusi 		return -EINVAL;
6356748d055SPeter Ujfalusi 	}
6366748d055SPeter Ujfalusi 
6376748d055SPeter Ujfalusi 	domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB];
6386748d055SPeter Ujfalusi 	ret = j721e_get_clocks(priv->dev, &domain->codec, "cpb-codec-scki");
6396748d055SPeter Ujfalusi 	if (ret)
6406748d055SPeter Ujfalusi 		return ret;
6416748d055SPeter Ujfalusi 
6426748d055SPeter Ujfalusi 	ret = j721e_get_clocks(priv->dev, &domain->mcasp, "cpb-mcasp-auxclk");
6436748d055SPeter Ujfalusi 	if (ret)
6446748d055SPeter Ujfalusi 		return ret;
6456748d055SPeter Ujfalusi 
6466748d055SPeter Ujfalusi 	/*
6476748d055SPeter Ujfalusi 	 * Common Processor Board, two links
6486748d055SPeter Ujfalusi 	 * Link 1: McASP10 -> pcm3168a_1 DAC
6496748d055SPeter Ujfalusi 	 * Link 2: McASP10 <- pcm3168a_1 ADC
6506748d055SPeter Ujfalusi 	 */
6516748d055SPeter Ujfalusi 	comp_count = 6;
6526748d055SPeter Ujfalusi 	compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent),
6536748d055SPeter Ujfalusi 				GFP_KERNEL);
6546748d055SPeter Ujfalusi 	if (!compnent)
6556748d055SPeter Ujfalusi 		return -ENOMEM;
6566748d055SPeter Ujfalusi 
6576748d055SPeter Ujfalusi 	comp_idx = 0;
6586748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus = &compnent[comp_idx++];
6596748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_cpus = 1;
6606748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs = &compnent[comp_idx++];
6616748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_codecs = 1;
6626748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms = &compnent[comp_idx++];
6636748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_platforms = 1;
6646748d055SPeter Ujfalusi 
6656748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].name = "CPB PCM3168A Playback";
6666748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog";
6676748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus->of_node = dai_node;
6686748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms->of_node = dai_node;
6696748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs->of_node = codec_node;
6706748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-dac";
6716748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].playback_only = 1;
6726748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB;
6736748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT;
6746748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].init = j721e_audio_init;
6756748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].ops = &j721e_audio_ops;
6766748d055SPeter Ujfalusi 	(*link_idx)++;
6776748d055SPeter Ujfalusi 
6786748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus = &compnent[comp_idx++];
6796748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_cpus = 1;
6806748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs = &compnent[comp_idx++];
6816748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_codecs = 1;
6826748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms = &compnent[comp_idx++];
6836748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_platforms = 1;
6846748d055SPeter Ujfalusi 
6856748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].name = "CPB PCM3168A Capture";
6866748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog";
6876748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus->of_node = dai_node;
6886748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms->of_node = dai_node;
6896748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs->of_node = codec_node;
6906748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-adc";
6916748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].capture_only = 1;
6926748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB;
6936748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT;
6946748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].init = j721e_audio_init;
6956748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].ops = &j721e_audio_ops;
6966748d055SPeter Ujfalusi 	(*link_idx)++;
6976748d055SPeter Ujfalusi 
6986748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].dlc.of_node = codec_node;
6996748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].name_prefix = "codec-1";
7006748d055SPeter Ujfalusi 	(*conf_idx)++;
7016748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].dlc.of_node = dai_node;
7026748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].name_prefix = "McASP10";
7036748d055SPeter Ujfalusi 	(*conf_idx)++;
7046748d055SPeter Ujfalusi 
7056748d055SPeter Ujfalusi 	return 0;
7066748d055SPeter Ujfalusi }
7076748d055SPeter Ujfalusi 
7086748d055SPeter Ujfalusi static int j721e_soc_probe_ivi(struct j721e_priv *priv, int *link_idx,
7096748d055SPeter Ujfalusi 			       int *conf_idx)
7106748d055SPeter Ujfalusi {
7116748d055SPeter Ujfalusi 	struct device_node *node = priv->dev->of_node;
7126748d055SPeter Ujfalusi 	struct snd_soc_dai_link_component *compnent;
7136748d055SPeter Ujfalusi 	struct device_node *dai_node, *codeca_node, *codecb_node;
7146748d055SPeter Ujfalusi 	struct j721e_audio_domain *domain;
7156748d055SPeter Ujfalusi 	int comp_count, comp_idx;
7166748d055SPeter Ujfalusi 	int ret;
7176748d055SPeter Ujfalusi 
7186748d055SPeter Ujfalusi 	if (priv->match_data->board_type != J721E_BOARD_CPB_IVI)
7196748d055SPeter Ujfalusi 		return 0;
7206748d055SPeter Ujfalusi 
7216748d055SPeter Ujfalusi 	dai_node = of_parse_phandle(node, "ti,ivi-mcasp", 0);
7226748d055SPeter Ujfalusi 	if (!dai_node) {
7236748d055SPeter Ujfalusi 		dev_err(priv->dev, "IVI McASP node is not provided\n");
7246748d055SPeter Ujfalusi 		return -EINVAL;
7256748d055SPeter Ujfalusi 	}
7266748d055SPeter Ujfalusi 
7276748d055SPeter Ujfalusi 	codeca_node = of_parse_phandle(node, "ti,ivi-codec-a", 0);
7286748d055SPeter Ujfalusi 	if (!codeca_node) {
7296748d055SPeter Ujfalusi 		dev_err(priv->dev, "IVI codec-a node is not provided\n");
7306748d055SPeter Ujfalusi 		return -EINVAL;
7316748d055SPeter Ujfalusi 	}
7326748d055SPeter Ujfalusi 
7336748d055SPeter Ujfalusi 	codecb_node = of_parse_phandle(node, "ti,ivi-codec-b", 0);
7346748d055SPeter Ujfalusi 	if (!codecb_node) {
7356748d055SPeter Ujfalusi 		dev_warn(priv->dev, "IVI codec-b node is not provided\n");
7366748d055SPeter Ujfalusi 		return 0;
7376748d055SPeter Ujfalusi 	}
7386748d055SPeter Ujfalusi 
7396748d055SPeter Ujfalusi 	domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_IVI];
7406748d055SPeter Ujfalusi 	ret = j721e_get_clocks(priv->dev, &domain->codec, "ivi-codec-scki");
7416748d055SPeter Ujfalusi 	if (ret)
7426748d055SPeter Ujfalusi 		return ret;
7436748d055SPeter Ujfalusi 
7446748d055SPeter Ujfalusi 	ret = j721e_get_clocks(priv->dev, &domain->mcasp, "ivi-mcasp-auxclk");
7456748d055SPeter Ujfalusi 	if (ret)
7466748d055SPeter Ujfalusi 		return ret;
7476748d055SPeter Ujfalusi 
7486748d055SPeter Ujfalusi 	/*
7496748d055SPeter Ujfalusi 	 * IVI extension, two links
7506748d055SPeter Ujfalusi 	 * Link 1: McASP0 -> pcm3168a_a DAC
7516748d055SPeter Ujfalusi 	 *		  \> pcm3168a_b DAC
7526748d055SPeter Ujfalusi 	 * Link 2: McASP0 <- pcm3168a_a ADC
7536748d055SPeter Ujfalusi 	 *		   \ pcm3168a_b ADC
7546748d055SPeter Ujfalusi 	 */
7556748d055SPeter Ujfalusi 	comp_count = 8;
7566748d055SPeter Ujfalusi 	compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent),
7576748d055SPeter Ujfalusi 				GFP_KERNEL);
7586748d055SPeter Ujfalusi 	if (!compnent)
7596748d055SPeter Ujfalusi 		return -ENOMEM;
7606748d055SPeter Ujfalusi 
7616748d055SPeter Ujfalusi 	comp_idx = 0;
7626748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus = &compnent[comp_idx++];
7636748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_cpus = 1;
7646748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms = &compnent[comp_idx++];
7656748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_platforms = 1;
7666748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs = &compnent[comp_idx];
7676748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_codecs = 2;
7686748d055SPeter Ujfalusi 	comp_idx += 2;
7696748d055SPeter Ujfalusi 
7706748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Playback";
7716748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog";
7726748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus->of_node = dai_node;
7736748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms->of_node = dai_node;
7746748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[0].of_node = codeca_node;
7756748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-dac";
7766748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[1].of_node = codecb_node;
7776748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-dac";
7786748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].playback_only = 1;
7796748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI;
7806748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT;
7816748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].init = j721e_audio_init_ivi;
7826748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].ops = &j721e_audio_ops;
7836748d055SPeter Ujfalusi 	(*link_idx)++;
7846748d055SPeter Ujfalusi 
7856748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus = &compnent[comp_idx++];
7866748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_cpus = 1;
7876748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms = &compnent[comp_idx++];
7886748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_platforms = 1;
7896748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs = &compnent[comp_idx];
7906748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].num_codecs = 2;
7916748d055SPeter Ujfalusi 
7926748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Capture";
7936748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog";
7946748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].cpus->of_node = dai_node;
7956748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].platforms->of_node = dai_node;
7966748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[0].of_node = codeca_node;
7976748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-adc";
7986748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[1].of_node = codecb_node;
7996748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-adc";
8006748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].capture_only = 1;
8016748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI;
8026748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT;
8036748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].init = j721e_audio_init;
8046748d055SPeter Ujfalusi 	priv->dai_links[*link_idx].ops = &j721e_audio_ops;
8056748d055SPeter Ujfalusi 	(*link_idx)++;
8066748d055SPeter Ujfalusi 
8076748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].dlc.of_node = codeca_node;
8086748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].name_prefix = "codec-a";
8096748d055SPeter Ujfalusi 	(*conf_idx)++;
8106748d055SPeter Ujfalusi 
8116748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].dlc.of_node = codecb_node;
8126748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].name_prefix = "codec-b";
8136748d055SPeter Ujfalusi 	(*conf_idx)++;
8146748d055SPeter Ujfalusi 
8156748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].dlc.of_node = dai_node;
8166748d055SPeter Ujfalusi 	priv->codec_conf[*conf_idx].name_prefix = "McASP0";
8176748d055SPeter Ujfalusi 	(*conf_idx)++;
8186748d055SPeter Ujfalusi 
8196748d055SPeter Ujfalusi 	return 0;
8206748d055SPeter Ujfalusi }
8216748d055SPeter Ujfalusi 
8226748d055SPeter Ujfalusi static int j721e_soc_probe(struct platform_device *pdev)
8236748d055SPeter Ujfalusi {
8246748d055SPeter Ujfalusi 	struct device_node *node = pdev->dev.of_node;
8256748d055SPeter Ujfalusi 	struct snd_soc_card *card;
8266748d055SPeter Ujfalusi 	const struct of_device_id *match;
8276748d055SPeter Ujfalusi 	struct j721e_priv *priv;
8286748d055SPeter Ujfalusi 	int link_cnt, conf_cnt, ret;
8296748d055SPeter Ujfalusi 
8306748d055SPeter Ujfalusi 	if (!node) {
8316748d055SPeter Ujfalusi 		dev_err(&pdev->dev, "of node is missing.\n");
8326748d055SPeter Ujfalusi 		return -ENODEV;
8336748d055SPeter Ujfalusi 	}
8346748d055SPeter Ujfalusi 
8356748d055SPeter Ujfalusi 	match = of_match_node(j721e_audio_of_match, node);
8366748d055SPeter Ujfalusi 	if (!match) {
8376748d055SPeter Ujfalusi 		dev_err(&pdev->dev, "No compatible match found\n");
8386748d055SPeter Ujfalusi 		return -ENODEV;
8396748d055SPeter Ujfalusi 	}
8406748d055SPeter Ujfalusi 
8416748d055SPeter Ujfalusi 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
8426748d055SPeter Ujfalusi 	if (!priv)
8436748d055SPeter Ujfalusi 		return -ENOMEM;
8446748d055SPeter Ujfalusi 
8456748d055SPeter Ujfalusi 	priv->match_data = match->data;
8466748d055SPeter Ujfalusi 
8476748d055SPeter Ujfalusi 	priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links,
8486748d055SPeter Ujfalusi 				       sizeof(*priv->dai_links), GFP_KERNEL);
8496748d055SPeter Ujfalusi 	if (!priv->dai_links)
8506748d055SPeter Ujfalusi 		return -ENOMEM;
8516748d055SPeter Ujfalusi 
8526748d055SPeter Ujfalusi 	priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1;
8536748d055SPeter Ujfalusi 	priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1;
8546748d055SPeter Ujfalusi 	priv->dev = &pdev->dev;
8556748d055SPeter Ujfalusi 	card = &priv->card;
8566748d055SPeter Ujfalusi 	card->dev = &pdev->dev;
8576748d055SPeter Ujfalusi 	card->owner = THIS_MODULE;
8586748d055SPeter Ujfalusi 	card->dapm_widgets = j721e_cpb_dapm_widgets;
8596748d055SPeter Ujfalusi 	card->num_dapm_widgets = ARRAY_SIZE(j721e_cpb_dapm_widgets);
8606748d055SPeter Ujfalusi 	card->dapm_routes = j721e_cpb_dapm_routes;
8616748d055SPeter Ujfalusi 	card->num_dapm_routes = ARRAY_SIZE(j721e_cpb_dapm_routes);
8626748d055SPeter Ujfalusi 	card->fully_routed = 1;
8636748d055SPeter Ujfalusi 
8646748d055SPeter Ujfalusi 	if (snd_soc_of_parse_card_name(card, "model")) {
8656748d055SPeter Ujfalusi 		dev_err(&pdev->dev, "Card name is not provided\n");
8666748d055SPeter Ujfalusi 		return -ENODEV;
8676748d055SPeter Ujfalusi 	}
8686748d055SPeter Ujfalusi 
8696748d055SPeter Ujfalusi 	link_cnt = 0;
8706748d055SPeter Ujfalusi 	conf_cnt = 0;
8716748d055SPeter Ujfalusi 	ret = j721e_soc_probe_cpb(priv, &link_cnt, &conf_cnt);
8726748d055SPeter Ujfalusi 	if (ret)
8736748d055SPeter Ujfalusi 		return ret;
8746748d055SPeter Ujfalusi 
8756748d055SPeter Ujfalusi 	ret = j721e_soc_probe_ivi(priv, &link_cnt, &conf_cnt);
8766748d055SPeter Ujfalusi 	if (ret)
8776748d055SPeter Ujfalusi 		return ret;
8786748d055SPeter Ujfalusi 
8796748d055SPeter Ujfalusi 	card->dai_link = priv->dai_links;
8806748d055SPeter Ujfalusi 	card->num_links = link_cnt;
8816748d055SPeter Ujfalusi 
8826748d055SPeter Ujfalusi 	card->codec_conf = priv->codec_conf;
8836748d055SPeter Ujfalusi 	card->num_configs = conf_cnt;
8846748d055SPeter Ujfalusi 
8856748d055SPeter Ujfalusi 	ret = j721e_calculate_rate_range(priv);
8866748d055SPeter Ujfalusi 	if (ret)
8876748d055SPeter Ujfalusi 		return ret;
8886748d055SPeter Ujfalusi 
8896748d055SPeter Ujfalusi 	snd_soc_card_set_drvdata(card, priv);
8906748d055SPeter Ujfalusi 
8916748d055SPeter Ujfalusi 	mutex_init(&priv->mutex);
8926748d055SPeter Ujfalusi 	ret = devm_snd_soc_register_card(&pdev->dev, card);
8936748d055SPeter Ujfalusi 	if (ret)
8946748d055SPeter Ujfalusi 		dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n",
8956748d055SPeter Ujfalusi 			ret);
8966748d055SPeter Ujfalusi 
8976748d055SPeter Ujfalusi 	return ret;
8986748d055SPeter Ujfalusi }
8996748d055SPeter Ujfalusi 
9006748d055SPeter Ujfalusi static struct platform_driver j721e_soc_driver = {
9016748d055SPeter Ujfalusi 	.driver = {
9026748d055SPeter Ujfalusi 		.name = "j721e-audio",
9036748d055SPeter Ujfalusi 		.pm = &snd_soc_pm_ops,
9045ec3c854SPeter Ujfalusi 		.of_match_table = j721e_audio_of_match,
9056748d055SPeter Ujfalusi 	},
9066748d055SPeter Ujfalusi 	.probe = j721e_soc_probe,
9076748d055SPeter Ujfalusi };
9086748d055SPeter Ujfalusi 
9096748d055SPeter Ujfalusi module_platform_driver(j721e_soc_driver);
9106748d055SPeter Ujfalusi 
9116748d055SPeter Ujfalusi MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
9126748d055SPeter Ujfalusi MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board");
9136748d055SPeter Ujfalusi MODULE_LICENSE("GPL v2");
914