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