cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fsl-asoc-card.c (27800B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Freescale Generic ASoC Sound Card driver with ASRC
      4//
      5// Copyright (C) 2014 Freescale Semiconductor, Inc.
      6//
      7// Author: Nicolin Chen <nicoleotsuka@gmail.com>
      8
      9#include <linux/clk.h>
     10#include <linux/i2c.h>
     11#include <linux/module.h>
     12#include <linux/of_platform.h>
     13#if IS_ENABLED(CONFIG_SND_AC97_CODEC)
     14#include <sound/ac97_codec.h>
     15#endif
     16#include <sound/pcm_params.h>
     17#include <sound/soc.h>
     18#include <sound/jack.h>
     19#include <sound/simple_card_utils.h>
     20
     21#include "fsl_esai.h"
     22#include "fsl_sai.h"
     23#include "imx-audmux.h"
     24
     25#include "../codecs/sgtl5000.h"
     26#include "../codecs/wm8962.h"
     27#include "../codecs/wm8960.h"
     28#include "../codecs/wm8994.h"
     29#include "../codecs/tlv320aic31xx.h"
     30
     31#define CS427x_SYSCLK_MCLK 0
     32
     33#define RX 0
     34#define TX 1
     35
     36/* Default DAI format without Master and Slave flag */
     37#define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
     38
     39/**
     40 * struct codec_priv - CODEC private data
     41 * @mclk_freq: Clock rate of MCLK
     42 * @free_freq: Clock rate of MCLK for hw_free()
     43 * @mclk_id: MCLK (or main clock) id for set_sysclk()
     44 * @fll_id: FLL (or secordary clock) id for set_sysclk()
     45 * @pll_id: PLL id for set_pll()
     46 */
     47struct codec_priv {
     48	unsigned long mclk_freq;
     49	unsigned long free_freq;
     50	u32 mclk_id;
     51	u32 fll_id;
     52	u32 pll_id;
     53};
     54
     55/**
     56 * struct cpu_priv - CPU private data
     57 * @sysclk_freq: SYSCLK rates for set_sysclk()
     58 * @sysclk_dir: SYSCLK directions for set_sysclk()
     59 * @sysclk_id: SYSCLK ids for set_sysclk()
     60 * @slot_width: Slot width of each frame
     61 *
     62 * Note: [1] for tx and [0] for rx
     63 */
     64struct cpu_priv {
     65	unsigned long sysclk_freq[2];
     66	u32 sysclk_dir[2];
     67	u32 sysclk_id[2];
     68	u32 slot_width;
     69};
     70
     71/**
     72 * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data
     73 * @dai_link: DAI link structure including normal one and DPCM link
     74 * @hp_jack: Headphone Jack structure
     75 * @mic_jack: Microphone Jack structure
     76 * @pdev: platform device pointer
     77 * @codec_priv: CODEC private data
     78 * @cpu_priv: CPU private data
     79 * @card: ASoC card structure
     80 * @streams: Mask of current active streams
     81 * @sample_rate: Current sample rate
     82 * @sample_format: Current sample format
     83 * @asrc_rate: ASRC sample rate used by Back-Ends
     84 * @asrc_format: ASRC sample format used by Back-Ends
     85 * @dai_fmt: DAI format between CPU and CODEC
     86 * @name: Card name
     87 */
     88
     89struct fsl_asoc_card_priv {
     90	struct snd_soc_dai_link dai_link[3];
     91	struct asoc_simple_jack hp_jack;
     92	struct asoc_simple_jack mic_jack;
     93	struct platform_device *pdev;
     94	struct codec_priv codec_priv;
     95	struct cpu_priv cpu_priv;
     96	struct snd_soc_card card;
     97	u8 streams;
     98	u32 sample_rate;
     99	snd_pcm_format_t sample_format;
    100	u32 asrc_rate;
    101	snd_pcm_format_t asrc_format;
    102	u32 dai_fmt;
    103	char name[32];
    104};
    105
    106/*
    107 * This dapm route map exists for DPCM link only.
    108 * The other routes shall go through Device Tree.
    109 *
    110 * Note: keep all ASRC routes in the second half
    111 *	 to drop them easily for non-ASRC cases.
    112 */
    113static const struct snd_soc_dapm_route audio_map[] = {
    114	/* 1st half -- Normal DAPM routes */
    115	{"Playback",  NULL, "CPU-Playback"},
    116	{"CPU-Capture",  NULL, "Capture"},
    117	/* 2nd half -- ASRC DAPM routes */
    118	{"CPU-Playback",  NULL, "ASRC-Playback"},
    119	{"ASRC-Capture",  NULL, "CPU-Capture"},
    120};
    121
    122static const struct snd_soc_dapm_route audio_map_ac97[] = {
    123	/* 1st half -- Normal DAPM routes */
    124	{"Playback",  NULL, "AC97 Playback"},
    125	{"AC97 Capture",  NULL, "Capture"},
    126	/* 2nd half -- ASRC DAPM routes */
    127	{"AC97 Playback",  NULL, "ASRC-Playback"},
    128	{"ASRC-Capture",  NULL, "AC97 Capture"},
    129};
    130
    131static const struct snd_soc_dapm_route audio_map_tx[] = {
    132	/* 1st half -- Normal DAPM routes */
    133	{"Playback",  NULL, "CPU-Playback"},
    134	/* 2nd half -- ASRC DAPM routes */
    135	{"CPU-Playback",  NULL, "ASRC-Playback"},
    136};
    137
    138static const struct snd_soc_dapm_route audio_map_rx[] = {
    139	/* 1st half -- Normal DAPM routes */
    140	{"CPU-Capture",  NULL, "Capture"},
    141	/* 2nd half -- ASRC DAPM routes */
    142	{"ASRC-Capture",  NULL, "CPU-Capture"},
    143};
    144
    145/* Add all possible widgets into here without being redundant */
    146static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
    147	SND_SOC_DAPM_LINE("Line Out Jack", NULL),
    148	SND_SOC_DAPM_LINE("Line In Jack", NULL),
    149	SND_SOC_DAPM_HP("Headphone Jack", NULL),
    150	SND_SOC_DAPM_SPK("Ext Spk", NULL),
    151	SND_SOC_DAPM_MIC("Mic Jack", NULL),
    152	SND_SOC_DAPM_MIC("AMIC", NULL),
    153	SND_SOC_DAPM_MIC("DMIC", NULL),
    154};
    155
    156static bool fsl_asoc_card_is_ac97(struct fsl_asoc_card_priv *priv)
    157{
    158	return priv->dai_fmt == SND_SOC_DAIFMT_AC97;
    159}
    160
    161static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
    162				   struct snd_pcm_hw_params *params)
    163{
    164	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    165	struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
    166	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
    167	struct codec_priv *codec_priv = &priv->codec_priv;
    168	struct cpu_priv *cpu_priv = &priv->cpu_priv;
    169	struct device *dev = rtd->card->dev;
    170	unsigned int pll_out;
    171	int ret;
    172
    173	priv->sample_rate = params_rate(params);
    174	priv->sample_format = params_format(params);
    175	priv->streams |= BIT(substream->stream);
    176
    177	if (fsl_asoc_card_is_ac97(priv))
    178		return 0;
    179
    180	/* Specific configurations of DAIs starts from here */
    181	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), cpu_priv->sysclk_id[tx],
    182				     cpu_priv->sysclk_freq[tx],
    183				     cpu_priv->sysclk_dir[tx]);
    184	if (ret && ret != -ENOTSUPP) {
    185		dev_err(dev, "failed to set sysclk for cpu dai\n");
    186		goto fail;
    187	}
    188
    189	if (cpu_priv->slot_width) {
    190		ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2,
    191					       cpu_priv->slot_width);
    192		if (ret && ret != -ENOTSUPP) {
    193			dev_err(dev, "failed to set TDM slot for cpu dai\n");
    194			goto fail;
    195		}
    196	}
    197
    198	/* Specific configuration for PLL */
    199	if (codec_priv->pll_id && codec_priv->fll_id) {
    200		if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
    201			pll_out = priv->sample_rate * 384;
    202		else
    203			pll_out = priv->sample_rate * 256;
    204
    205		ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
    206					  codec_priv->pll_id,
    207					  codec_priv->mclk_id,
    208					  codec_priv->mclk_freq, pll_out);
    209		if (ret) {
    210			dev_err(dev, "failed to start FLL: %d\n", ret);
    211			goto fail;
    212		}
    213
    214		ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
    215					     codec_priv->fll_id,
    216					     pll_out, SND_SOC_CLOCK_IN);
    217
    218		if (ret && ret != -ENOTSUPP) {
    219			dev_err(dev, "failed to set SYSCLK: %d\n", ret);
    220			goto fail;
    221		}
    222	}
    223
    224	return 0;
    225
    226fail:
    227	priv->streams &= ~BIT(substream->stream);
    228	return ret;
    229}
    230
    231static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
    232{
    233	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    234	struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
    235	struct codec_priv *codec_priv = &priv->codec_priv;
    236	struct device *dev = rtd->card->dev;
    237	int ret;
    238
    239	priv->streams &= ~BIT(substream->stream);
    240
    241	if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) {
    242		/* Force freq to be free_freq to avoid error message in codec */
    243		ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
    244					     codec_priv->mclk_id,
    245					     codec_priv->free_freq,
    246					     SND_SOC_CLOCK_IN);
    247		if (ret) {
    248			dev_err(dev, "failed to switch away from FLL: %d\n", ret);
    249			return ret;
    250		}
    251
    252		ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
    253					  codec_priv->pll_id, 0, 0, 0);
    254		if (ret && ret != -ENOTSUPP) {
    255			dev_err(dev, "failed to stop FLL: %d\n", ret);
    256			return ret;
    257		}
    258	}
    259
    260	return 0;
    261}
    262
    263static const struct snd_soc_ops fsl_asoc_card_ops = {
    264	.hw_params = fsl_asoc_card_hw_params,
    265	.hw_free = fsl_asoc_card_hw_free,
    266};
    267
    268static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
    269			      struct snd_pcm_hw_params *params)
    270{
    271	struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
    272	struct snd_interval *rate;
    273	struct snd_mask *mask;
    274
    275	rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
    276	rate->max = rate->min = priv->asrc_rate;
    277
    278	mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    279	snd_mask_none(mask);
    280	snd_mask_set_format(mask, priv->asrc_format);
    281
    282	return 0;
    283}
    284
    285SND_SOC_DAILINK_DEFS(hifi,
    286	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    287	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    288	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    289
    290SND_SOC_DAILINK_DEFS(hifi_fe,
    291	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    292	DAILINK_COMP_ARRAY(COMP_DUMMY()),
    293	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    294
    295SND_SOC_DAILINK_DEFS(hifi_be,
    296	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    297	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    298	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    299
    300static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
    301	/* Default ASoC DAI Link*/
    302	{
    303		.name = "HiFi",
    304		.stream_name = "HiFi",
    305		.ops = &fsl_asoc_card_ops,
    306		SND_SOC_DAILINK_REG(hifi),
    307	},
    308	/* DPCM Link between Front-End and Back-End (Optional) */
    309	{
    310		.name = "HiFi-ASRC-FE",
    311		.stream_name = "HiFi-ASRC-FE",
    312		.dpcm_playback = 1,
    313		.dpcm_capture = 1,
    314		.dynamic = 1,
    315		SND_SOC_DAILINK_REG(hifi_fe),
    316	},
    317	{
    318		.name = "HiFi-ASRC-BE",
    319		.stream_name = "HiFi-ASRC-BE",
    320		.be_hw_params_fixup = be_hw_params_fixup,
    321		.ops = &fsl_asoc_card_ops,
    322		.dpcm_playback = 1,
    323		.dpcm_capture = 1,
    324		.no_pcm = 1,
    325		SND_SOC_DAILINK_REG(hifi_be),
    326	},
    327};
    328
    329static int fsl_asoc_card_audmux_init(struct device_node *np,
    330				     struct fsl_asoc_card_priv *priv)
    331{
    332	struct device *dev = &priv->pdev->dev;
    333	u32 int_ptcr = 0, ext_ptcr = 0;
    334	int int_port, ext_port;
    335	int ret;
    336
    337	ret = of_property_read_u32(np, "mux-int-port", &int_port);
    338	if (ret) {
    339		dev_err(dev, "mux-int-port missing or invalid\n");
    340		return ret;
    341	}
    342	ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
    343	if (ret) {
    344		dev_err(dev, "mux-ext-port missing or invalid\n");
    345		return ret;
    346	}
    347
    348	/*
    349	 * The port numbering in the hardware manual starts at 1, while
    350	 * the AUDMUX API expects it starts at 0.
    351	 */
    352	int_port--;
    353	ext_port--;
    354
    355	/*
    356	 * Use asynchronous mode (6 wires) for all cases except AC97.
    357	 * If only 4 wires are needed, just set SSI into
    358	 * synchronous mode and enable 4 PADs in IOMUX.
    359	 */
    360	switch (priv->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
    361	case SND_SOC_DAIFMT_CBP_CFP:
    362		int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) |
    363			   IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) |
    364			   IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
    365			   IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
    366			   IMX_AUDMUX_V2_PTCR_RFSDIR |
    367			   IMX_AUDMUX_V2_PTCR_RCLKDIR |
    368			   IMX_AUDMUX_V2_PTCR_TFSDIR |
    369			   IMX_AUDMUX_V2_PTCR_TCLKDIR;
    370		break;
    371	case SND_SOC_DAIFMT_CBP_CFC:
    372		int_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) |
    373			   IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
    374			   IMX_AUDMUX_V2_PTCR_RCLKDIR |
    375			   IMX_AUDMUX_V2_PTCR_TCLKDIR;
    376		ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) |
    377			   IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
    378			   IMX_AUDMUX_V2_PTCR_RFSDIR |
    379			   IMX_AUDMUX_V2_PTCR_TFSDIR;
    380		break;
    381	case SND_SOC_DAIFMT_CBC_CFP:
    382		int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) |
    383			   IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
    384			   IMX_AUDMUX_V2_PTCR_RFSDIR |
    385			   IMX_AUDMUX_V2_PTCR_TFSDIR;
    386		ext_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) |
    387			   IMX_AUDMUX_V2_PTCR_TCSEL(int_port) |
    388			   IMX_AUDMUX_V2_PTCR_RCLKDIR |
    389			   IMX_AUDMUX_V2_PTCR_TCLKDIR;
    390		break;
    391	case SND_SOC_DAIFMT_CBC_CFC:
    392		ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) |
    393			   IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) |
    394			   IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
    395			   IMX_AUDMUX_V2_PTCR_TCSEL(int_port) |
    396			   IMX_AUDMUX_V2_PTCR_RFSDIR |
    397			   IMX_AUDMUX_V2_PTCR_RCLKDIR |
    398			   IMX_AUDMUX_V2_PTCR_TFSDIR |
    399			   IMX_AUDMUX_V2_PTCR_TCLKDIR;
    400		break;
    401	default:
    402		if (!fsl_asoc_card_is_ac97(priv))
    403			return -EINVAL;
    404	}
    405
    406	if (fsl_asoc_card_is_ac97(priv)) {
    407		int_ptcr = IMX_AUDMUX_V2_PTCR_SYN |
    408			   IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
    409			   IMX_AUDMUX_V2_PTCR_TCLKDIR;
    410		ext_ptcr = IMX_AUDMUX_V2_PTCR_SYN |
    411			   IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
    412			   IMX_AUDMUX_V2_PTCR_TFSDIR;
    413	}
    414
    415	/* Asynchronous mode can not be set along with RCLKDIR */
    416	if (!fsl_asoc_card_is_ac97(priv)) {
    417		unsigned int pdcr =
    418				IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port);
    419
    420		ret = imx_audmux_v2_configure_port(int_port, 0,
    421						   pdcr);
    422		if (ret) {
    423			dev_err(dev, "audmux internal port setup failed\n");
    424			return ret;
    425		}
    426	}
    427
    428	ret = imx_audmux_v2_configure_port(int_port, int_ptcr,
    429					   IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
    430	if (ret) {
    431		dev_err(dev, "audmux internal port setup failed\n");
    432		return ret;
    433	}
    434
    435	if (!fsl_asoc_card_is_ac97(priv)) {
    436		unsigned int pdcr =
    437				IMX_AUDMUX_V2_PDCR_RXDSEL(int_port);
    438
    439		ret = imx_audmux_v2_configure_port(ext_port, 0,
    440						   pdcr);
    441		if (ret) {
    442			dev_err(dev, "audmux external port setup failed\n");
    443			return ret;
    444		}
    445	}
    446
    447	ret = imx_audmux_v2_configure_port(ext_port, ext_ptcr,
    448					   IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
    449	if (ret) {
    450		dev_err(dev, "audmux external port setup failed\n");
    451		return ret;
    452	}
    453
    454	return 0;
    455}
    456
    457static int hp_jack_event(struct notifier_block *nb, unsigned long event,
    458			 void *data)
    459{
    460	struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
    461	struct snd_soc_dapm_context *dapm = &jack->card->dapm;
    462
    463	if (event & SND_JACK_HEADPHONE)
    464		/* Disable speaker if headphone is plugged in */
    465		return snd_soc_dapm_disable_pin(dapm, "Ext Spk");
    466	else
    467		return snd_soc_dapm_enable_pin(dapm, "Ext Spk");
    468}
    469
    470static struct notifier_block hp_jack_nb = {
    471	.notifier_call = hp_jack_event,
    472};
    473
    474static int mic_jack_event(struct notifier_block *nb, unsigned long event,
    475			  void *data)
    476{
    477	struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
    478	struct snd_soc_dapm_context *dapm = &jack->card->dapm;
    479
    480	if (event & SND_JACK_MICROPHONE)
    481		/* Disable dmic if microphone is plugged in */
    482		return snd_soc_dapm_disable_pin(dapm, "DMIC");
    483	else
    484		return snd_soc_dapm_enable_pin(dapm, "DMIC");
    485}
    486
    487static struct notifier_block mic_jack_nb = {
    488	.notifier_call = mic_jack_event,
    489};
    490
    491static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
    492{
    493	struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
    494	struct snd_soc_pcm_runtime *rtd = list_first_entry(
    495			&card->rtd_list, struct snd_soc_pcm_runtime, list);
    496	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    497	struct codec_priv *codec_priv = &priv->codec_priv;
    498	struct device *dev = card->dev;
    499	int ret;
    500
    501	if (fsl_asoc_card_is_ac97(priv)) {
    502#if IS_ENABLED(CONFIG_SND_AC97_CODEC)
    503		struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
    504		struct snd_ac97 *ac97 = snd_soc_component_get_drvdata(component);
    505
    506		/*
    507		 * Use slots 3/4 for S/PDIF so SSI won't try to enable
    508		 * other slots and send some samples there
    509		 * due to SLOTREQ bits for S/PDIF received from codec
    510		 */
    511		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
    512				     AC97_EA_SPSA_SLOT_MASK, AC97_EA_SPSA_3_4);
    513#endif
    514
    515		return 0;
    516	}
    517
    518	ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
    519				     codec_priv->mclk_freq, SND_SOC_CLOCK_IN);
    520	if (ret && ret != -ENOTSUPP) {
    521		dev_err(dev, "failed to set sysclk in %s\n", __func__);
    522		return ret;
    523	}
    524
    525	return 0;
    526}
    527
    528static int fsl_asoc_card_probe(struct platform_device *pdev)
    529{
    530	struct device_node *cpu_np, *codec_np, *asrc_np;
    531	struct device_node *np = pdev->dev.of_node;
    532	struct platform_device *asrc_pdev = NULL;
    533	struct device_node *bitclkprovider = NULL;
    534	struct device_node *frameprovider = NULL;
    535	struct platform_device *cpu_pdev;
    536	struct fsl_asoc_card_priv *priv;
    537	struct device *codec_dev = NULL;
    538	const char *codec_dai_name;
    539	const char *codec_dev_name;
    540	u32 width;
    541	int ret;
    542
    543	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
    544	if (!priv)
    545		return -ENOMEM;
    546
    547	cpu_np = of_parse_phandle(np, "audio-cpu", 0);
    548	/* Give a chance to old DT binding */
    549	if (!cpu_np)
    550		cpu_np = of_parse_phandle(np, "ssi-controller", 0);
    551	if (!cpu_np) {
    552		dev_err(&pdev->dev, "CPU phandle missing or invalid\n");
    553		ret = -EINVAL;
    554		goto fail;
    555	}
    556
    557	cpu_pdev = of_find_device_by_node(cpu_np);
    558	if (!cpu_pdev) {
    559		dev_err(&pdev->dev, "failed to find CPU DAI device\n");
    560		ret = -EINVAL;
    561		goto fail;
    562	}
    563
    564	codec_np = of_parse_phandle(np, "audio-codec", 0);
    565	if (codec_np) {
    566		struct platform_device *codec_pdev;
    567		struct i2c_client *codec_i2c;
    568
    569		codec_i2c = of_find_i2c_device_by_node(codec_np);
    570		if (codec_i2c) {
    571			codec_dev = &codec_i2c->dev;
    572			codec_dev_name = codec_i2c->name;
    573		}
    574		if (!codec_dev) {
    575			codec_pdev = of_find_device_by_node(codec_np);
    576			if (codec_pdev) {
    577				codec_dev = &codec_pdev->dev;
    578				codec_dev_name = codec_pdev->name;
    579			}
    580		}
    581	}
    582
    583	asrc_np = of_parse_phandle(np, "audio-asrc", 0);
    584	if (asrc_np)
    585		asrc_pdev = of_find_device_by_node(asrc_np);
    586
    587	/* Get the MCLK rate only, and leave it controlled by CODEC drivers */
    588	if (codec_dev) {
    589		struct clk *codec_clk = clk_get(codec_dev, NULL);
    590
    591		if (!IS_ERR(codec_clk)) {
    592			priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
    593			clk_put(codec_clk);
    594		}
    595	}
    596
    597	/* Default sample rate and format, will be updated in hw_params() */
    598	priv->sample_rate = 44100;
    599	priv->sample_format = SNDRV_PCM_FORMAT_S16_LE;
    600
    601	/* Assign a default DAI format, and allow each card to overwrite it */
    602	priv->dai_fmt = DAI_FMT_BASE;
    603
    604	memcpy(priv->dai_link, fsl_asoc_card_dai,
    605	       sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
    606
    607	priv->card.dapm_routes = audio_map;
    608	priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
    609	/* Diversify the card configurations */
    610	if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
    611		codec_dai_name = "cs42888";
    612		priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq;
    613		priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq;
    614		priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
    615		priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
    616		priv->cpu_priv.slot_width = 32;
    617		priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
    618	} else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) {
    619		codec_dai_name = "cs4271-hifi";
    620		priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK;
    621		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    622	} else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) {
    623		codec_dai_name = "sgtl5000";
    624		priv->codec_priv.mclk_id = SGTL5000_SYSCLK;
    625		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    626	} else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) {
    627		codec_dai_name = "tlv320aic32x4-hifi";
    628		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    629	} else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) {
    630		codec_dai_name = "tlv320dac31xx-hifi";
    631		priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
    632		priv->dai_link[1].dpcm_capture = 0;
    633		priv->dai_link[2].dpcm_capture = 0;
    634		priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
    635		priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
    636		priv->card.dapm_routes = audio_map_tx;
    637		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
    638	} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
    639		codec_dai_name = "wm8962";
    640		priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
    641		priv->codec_priv.fll_id = WM8962_SYSCLK_FLL;
    642		priv->codec_priv.pll_id = WM8962_FLL;
    643		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    644	} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
    645		codec_dai_name = "wm8960-hifi";
    646		priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO;
    647		priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO;
    648		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    649	} else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
    650		codec_dai_name = "ac97-hifi";
    651		priv->dai_fmt = SND_SOC_DAIFMT_AC97;
    652		priv->card.dapm_routes = audio_map_ac97;
    653		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
    654	} else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
    655		codec_dai_name = "fsl-mqs-dai";
    656		priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
    657				SND_SOC_DAIFMT_CBC_CFC |
    658				SND_SOC_DAIFMT_NB_NF;
    659		priv->dai_link[1].dpcm_capture = 0;
    660		priv->dai_link[2].dpcm_capture = 0;
    661		priv->card.dapm_routes = audio_map_tx;
    662		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
    663	} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
    664		codec_dai_name = "wm8524-hifi";
    665		priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
    666		priv->dai_link[1].dpcm_capture = 0;
    667		priv->dai_link[2].dpcm_capture = 0;
    668		priv->cpu_priv.slot_width = 32;
    669		priv->card.dapm_routes = audio_map_tx;
    670		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
    671	} else if (of_device_is_compatible(np, "fsl,imx-audio-si476x")) {
    672		codec_dai_name = "si476x-codec";
    673		priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
    674		priv->card.dapm_routes = audio_map_rx;
    675		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx);
    676	} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) {
    677		codec_dai_name = "wm8994-aif1";
    678		priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
    679		priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1;
    680		priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1;
    681		priv->codec_priv.pll_id = WM8994_FLL1;
    682		priv->codec_priv.free_freq = priv->codec_priv.mclk_freq;
    683		priv->card.dapm_routes = NULL;
    684		priv->card.num_dapm_routes = 0;
    685	} else {
    686		dev_err(&pdev->dev, "unknown Device Tree compatible\n");
    687		ret = -EINVAL;
    688		goto asrc_fail;
    689	}
    690
    691	/*
    692	 * Allow setting mclk-id from the device-tree node. Otherwise, the
    693	 * default value for each card configuration is used.
    694	 */
    695	of_property_read_u32(np, "mclk-id", &priv->codec_priv.mclk_id);
    696
    697	/* Format info from DT is optional. */
    698	snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL, &bitclkprovider, &frameprovider);
    699	if (bitclkprovider || frameprovider) {
    700		unsigned int daifmt = snd_soc_daifmt_parse_format(np, NULL);
    701
    702		if (codec_np == bitclkprovider)
    703			daifmt |= (codec_np == frameprovider) ?
    704				SND_SOC_DAIFMT_CBP_CFP : SND_SOC_DAIFMT_CBP_CFC;
    705		else
    706			daifmt |= (codec_np == frameprovider) ?
    707				SND_SOC_DAIFMT_CBC_CFP : SND_SOC_DAIFMT_CBC_CFC;
    708
    709		/* Override dai_fmt with value from DT */
    710		priv->dai_fmt = daifmt;
    711	}
    712
    713	/* Change direction according to format */
    714	if (priv->dai_fmt & SND_SOC_DAIFMT_CBP_CFP) {
    715		priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_IN;
    716		priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_IN;
    717	}
    718
    719	of_node_put(bitclkprovider);
    720	of_node_put(frameprovider);
    721
    722	if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
    723		dev_dbg(&pdev->dev, "failed to find codec device\n");
    724		ret = -EPROBE_DEFER;
    725		goto asrc_fail;
    726	}
    727
    728	/* Common settings for corresponding Freescale CPU DAI driver */
    729	if (of_node_name_eq(cpu_np, "ssi")) {
    730		/* Only SSI needs to configure AUDMUX */
    731		ret = fsl_asoc_card_audmux_init(np, priv);
    732		if (ret) {
    733			dev_err(&pdev->dev, "failed to init audmux\n");
    734			goto asrc_fail;
    735		}
    736	} else if (of_node_name_eq(cpu_np, "esai")) {
    737		struct clk *esai_clk = clk_get(&cpu_pdev->dev, "extal");
    738
    739		if (!IS_ERR(esai_clk)) {
    740			priv->cpu_priv.sysclk_freq[TX] = clk_get_rate(esai_clk);
    741			priv->cpu_priv.sysclk_freq[RX] = clk_get_rate(esai_clk);
    742			clk_put(esai_clk);
    743		} else if (PTR_ERR(esai_clk) == -EPROBE_DEFER) {
    744			ret = -EPROBE_DEFER;
    745			goto asrc_fail;
    746		}
    747
    748		priv->cpu_priv.sysclk_id[1] = ESAI_HCKT_EXTAL;
    749		priv->cpu_priv.sysclk_id[0] = ESAI_HCKR_EXTAL;
    750	} else if (of_node_name_eq(cpu_np, "sai")) {
    751		priv->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1;
    752		priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1;
    753	}
    754
    755	/* Initialize sound card */
    756	priv->pdev = pdev;
    757	priv->card.dev = &pdev->dev;
    758	priv->card.owner = THIS_MODULE;
    759	ret = snd_soc_of_parse_card_name(&priv->card, "model");
    760	if (ret) {
    761		snprintf(priv->name, sizeof(priv->name), "%s-audio",
    762			 fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name);
    763		priv->card.name = priv->name;
    764	}
    765	priv->card.dai_link = priv->dai_link;
    766	priv->card.late_probe = fsl_asoc_card_late_probe;
    767	priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets;
    768	priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets);
    769
    770	/* Drop the second half of DAPM routes -- ASRC */
    771	if (!asrc_pdev)
    772		priv->card.num_dapm_routes /= 2;
    773
    774	if (of_property_read_bool(np, "audio-routing")) {
    775		ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
    776		if (ret) {
    777			dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
    778			goto asrc_fail;
    779		}
    780	}
    781
    782	/* Normal DAI Link */
    783	priv->dai_link[0].cpus->of_node = cpu_np;
    784	priv->dai_link[0].codecs->dai_name = codec_dai_name;
    785
    786	if (!fsl_asoc_card_is_ac97(priv))
    787		priv->dai_link[0].codecs->of_node = codec_np;
    788	else {
    789		u32 idx;
    790
    791		ret = of_property_read_u32(cpu_np, "cell-index", &idx);
    792		if (ret) {
    793			dev_err(&pdev->dev,
    794				"cannot get CPU index property\n");
    795			goto asrc_fail;
    796		}
    797
    798		priv->dai_link[0].codecs->name =
    799				devm_kasprintf(&pdev->dev, GFP_KERNEL,
    800					       "ac97-codec.%u",
    801					       (unsigned int)idx);
    802		if (!priv->dai_link[0].codecs->name) {
    803			ret = -ENOMEM;
    804			goto asrc_fail;
    805		}
    806	}
    807
    808	priv->dai_link[0].platforms->of_node = cpu_np;
    809	priv->dai_link[0].dai_fmt = priv->dai_fmt;
    810	priv->card.num_links = 1;
    811
    812	if (asrc_pdev) {
    813		/* DPCM DAI Links only if ASRC exsits */
    814		priv->dai_link[1].cpus->of_node = asrc_np;
    815		priv->dai_link[1].platforms->of_node = asrc_np;
    816		priv->dai_link[2].codecs->dai_name = codec_dai_name;
    817		priv->dai_link[2].codecs->of_node = codec_np;
    818		priv->dai_link[2].codecs->name =
    819				priv->dai_link[0].codecs->name;
    820		priv->dai_link[2].cpus->of_node = cpu_np;
    821		priv->dai_link[2].dai_fmt = priv->dai_fmt;
    822		priv->card.num_links = 3;
    823
    824		ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
    825					   &priv->asrc_rate);
    826		if (ret) {
    827			dev_err(&pdev->dev, "failed to get output rate\n");
    828			ret = -EINVAL;
    829			goto asrc_fail;
    830		}
    831
    832		ret = of_property_read_u32(asrc_np, "fsl,asrc-format",
    833					   &priv->asrc_format);
    834		if (ret) {
    835			/* Fallback to old binding; translate to asrc_format */
    836			ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
    837						   &width);
    838			if (ret) {
    839				dev_err(&pdev->dev,
    840					"failed to decide output format\n");
    841				goto asrc_fail;
    842			}
    843
    844			if (width == 24)
    845				priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
    846			else
    847				priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
    848		}
    849	}
    850
    851	/* Finish card registering */
    852	platform_set_drvdata(pdev, priv);
    853	snd_soc_card_set_drvdata(&priv->card, priv);
    854
    855	ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
    856	if (ret) {
    857		dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
    858		goto asrc_fail;
    859	}
    860
    861	/*
    862	 * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and
    863	 * asoc_simple_init_jack uses these properties for creating
    864	 * Headphone Jack and Microphone Jack.
    865	 *
    866	 * The notifier is initialized in snd_soc_card_jack_new(), then
    867	 * snd_soc_jack_notifier_register can be called.
    868	 */
    869	if (of_property_read_bool(np, "hp-det-gpio")) {
    870		ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack,
    871					    1, NULL, "Headphone Jack");
    872		if (ret)
    873			goto asrc_fail;
    874
    875		snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
    876	}
    877
    878	if (of_property_read_bool(np, "mic-det-gpio")) {
    879		ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack,
    880					    0, NULL, "Mic Jack");
    881		if (ret)
    882			goto asrc_fail;
    883
    884		snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb);
    885	}
    886
    887asrc_fail:
    888	of_node_put(asrc_np);
    889	of_node_put(codec_np);
    890	put_device(&cpu_pdev->dev);
    891fail:
    892	of_node_put(cpu_np);
    893
    894	return ret;
    895}
    896
    897static const struct of_device_id fsl_asoc_card_dt_ids[] = {
    898	{ .compatible = "fsl,imx-audio-ac97", },
    899	{ .compatible = "fsl,imx-audio-cs42888", },
    900	{ .compatible = "fsl,imx-audio-cs427x", },
    901	{ .compatible = "fsl,imx-audio-tlv320aic32x4", },
    902	{ .compatible = "fsl,imx-audio-tlv320aic31xx", },
    903	{ .compatible = "fsl,imx-audio-sgtl5000", },
    904	{ .compatible = "fsl,imx-audio-wm8962", },
    905	{ .compatible = "fsl,imx-audio-wm8960", },
    906	{ .compatible = "fsl,imx-audio-mqs", },
    907	{ .compatible = "fsl,imx-audio-wm8524", },
    908	{ .compatible = "fsl,imx-audio-si476x", },
    909	{ .compatible = "fsl,imx-audio-wm8958", },
    910	{}
    911};
    912MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
    913
    914static struct platform_driver fsl_asoc_card_driver = {
    915	.probe = fsl_asoc_card_probe,
    916	.driver = {
    917		.name = "fsl-asoc-card",
    918		.pm = &snd_soc_pm_ops,
    919		.of_match_table = fsl_asoc_card_dt_ids,
    920	},
    921};
    922module_platform_driver(fsl_asoc_card_driver);
    923
    924MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC");
    925MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>");
    926MODULE_ALIAS("platform:fsl-asoc-card");
    927MODULE_LICENSE("GPL");