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

mxs-sgtl5000.c (5324B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2011 Freescale Semiconductor, Inc.
      4 */
      5
      6#include <linux/module.h>
      7#include <linux/device.h>
      8#include <linux/of.h>
      9#include <linux/of_device.h>
     10#include <sound/core.h>
     11#include <sound/pcm.h>
     12#include <sound/soc.h>
     13#include <sound/jack.h>
     14#include <sound/soc-dapm.h>
     15
     16#include "../codecs/sgtl5000.h"
     17#include "mxs-saif.h"
     18
     19static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
     20	struct snd_pcm_hw_params *params)
     21{
     22	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     23	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
     24	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
     25	unsigned int rate = params_rate(params);
     26	u32 mclk;
     27	int ret;
     28
     29	/* sgtl5000 does not support 512*rate when in 96000 fs */
     30	switch (rate) {
     31	case 96000:
     32		mclk = 256 * rate;
     33		break;
     34	default:
     35		mclk = 512 * rate;
     36		break;
     37	}
     38
     39	/* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */
     40	ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0);
     41	if (ret) {
     42		dev_err(codec_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
     43			mclk / 1000000, mclk / 1000 % 1000);
     44		return ret;
     45	}
     46
     47	/* The SAIF MCLK should be the same as SGTL5000_SYSCLK */
     48	ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0);
     49	if (ret) {
     50		dev_err(cpu_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
     51			mclk / 1000000, mclk / 1000 % 1000);
     52		return ret;
     53	}
     54
     55	return 0;
     56}
     57
     58static const struct snd_soc_ops mxs_sgtl5000_hifi_ops = {
     59	.hw_params = mxs_sgtl5000_hw_params,
     60};
     61
     62#define MXS_SGTL5000_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
     63	SND_SOC_DAIFMT_CBS_CFS)
     64
     65
     66SND_SOC_DAILINK_DEFS(hifi_tx,
     67	DAILINK_COMP_ARRAY(COMP_EMPTY()),
     68	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")),
     69	DAILINK_COMP_ARRAY(COMP_EMPTY()));
     70
     71SND_SOC_DAILINK_DEFS(hifi_rx,
     72	DAILINK_COMP_ARRAY(COMP_EMPTY()),
     73	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")),
     74	DAILINK_COMP_ARRAY(COMP_EMPTY()));
     75
     76static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
     77	{
     78		.name		= "HiFi Tx",
     79		.stream_name	= "HiFi Playback",
     80		.dai_fmt	= MXS_SGTL5000_DAI_FMT,
     81		.ops		= &mxs_sgtl5000_hifi_ops,
     82		.playback_only	= true,
     83		SND_SOC_DAILINK_REG(hifi_tx),
     84	}, {
     85		.name		= "HiFi Rx",
     86		.stream_name	= "HiFi Capture",
     87		.dai_fmt	= MXS_SGTL5000_DAI_FMT,
     88		.ops		= &mxs_sgtl5000_hifi_ops,
     89		.capture_only	= true,
     90		SND_SOC_DAILINK_REG(hifi_rx),
     91	},
     92};
     93
     94static const struct snd_soc_dapm_widget mxs_sgtl5000_dapm_widgets[] = {
     95	SND_SOC_DAPM_MIC("Mic Jack", NULL),
     96	SND_SOC_DAPM_LINE("Line In Jack", NULL),
     97	SND_SOC_DAPM_HP("Headphone Jack", NULL),
     98	SND_SOC_DAPM_SPK("Line Out Jack", NULL),
     99	SND_SOC_DAPM_SPK("Ext Spk", NULL),
    100};
    101
    102static struct snd_soc_card mxs_sgtl5000 = {
    103	.name		= "mxs_sgtl5000",
    104	.owner		= THIS_MODULE,
    105	.dai_link	= mxs_sgtl5000_dai,
    106	.num_links	= ARRAY_SIZE(mxs_sgtl5000_dai),
    107};
    108
    109static int mxs_sgtl5000_probe(struct platform_device *pdev)
    110{
    111	struct snd_soc_card *card = &mxs_sgtl5000;
    112	int ret, i;
    113	struct device_node *np = pdev->dev.of_node;
    114	struct device_node *saif_np[2], *codec_np;
    115
    116	saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
    117	saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
    118	codec_np = of_parse_phandle(np, "audio-codec", 0);
    119	if (!saif_np[0] || !saif_np[1] || !codec_np) {
    120		dev_err(&pdev->dev, "phandle missing or invalid\n");
    121		of_node_put(codec_np);
    122		of_node_put(saif_np[0]);
    123		of_node_put(saif_np[1]);
    124		return -EINVAL;
    125	}
    126
    127	for (i = 0; i < 2; i++) {
    128		mxs_sgtl5000_dai[i].codecs->name = NULL;
    129		mxs_sgtl5000_dai[i].codecs->of_node = codec_np;
    130		mxs_sgtl5000_dai[i].cpus->dai_name = NULL;
    131		mxs_sgtl5000_dai[i].cpus->of_node = saif_np[i];
    132		mxs_sgtl5000_dai[i].platforms->name = NULL;
    133		mxs_sgtl5000_dai[i].platforms->of_node = saif_np[i];
    134	}
    135
    136	of_node_put(codec_np);
    137	of_node_put(saif_np[0]);
    138	of_node_put(saif_np[1]);
    139
    140	/*
    141	 * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
    142	 * The Sgtl5000 sysclk is derived from saif0 mclk and it's range
    143	 * should be >= 8MHz and <= 27M.
    144	 */
    145	ret = mxs_saif_get_mclk(0, 44100 * 256, 44100);
    146	if (ret) {
    147		dev_err(&pdev->dev, "failed to get mclk\n");
    148		return ret;
    149	}
    150
    151	card->dev = &pdev->dev;
    152
    153	if (of_find_property(np, "audio-routing", NULL)) {
    154		card->dapm_widgets = mxs_sgtl5000_dapm_widgets;
    155		card->num_dapm_widgets = ARRAY_SIZE(mxs_sgtl5000_dapm_widgets);
    156
    157		ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
    158		if (ret) {
    159			dev_err(&pdev->dev, "failed to parse audio-routing (%d)\n",
    160				ret);
    161			return ret;
    162		}
    163	}
    164
    165	ret = devm_snd_soc_register_card(&pdev->dev, card);
    166	if (ret)
    167		return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
    168
    169	return 0;
    170}
    171
    172static int mxs_sgtl5000_remove(struct platform_device *pdev)
    173{
    174	mxs_saif_put_mclk(0);
    175
    176	return 0;
    177}
    178
    179static const struct of_device_id mxs_sgtl5000_dt_ids[] = {
    180	{ .compatible = "fsl,mxs-audio-sgtl5000", },
    181	{ /* sentinel */ }
    182};
    183MODULE_DEVICE_TABLE(of, mxs_sgtl5000_dt_ids);
    184
    185static struct platform_driver mxs_sgtl5000_audio_driver = {
    186	.driver = {
    187		.name = "mxs-sgtl5000",
    188		.of_match_table = mxs_sgtl5000_dt_ids,
    189	},
    190	.probe = mxs_sgtl5000_probe,
    191	.remove = mxs_sgtl5000_remove,
    192};
    193
    194module_platform_driver(mxs_sgtl5000_audio_driver);
    195
    196MODULE_AUTHOR("Freescale Semiconductor, Inc.");
    197MODULE_DESCRIPTION("MXS ALSA SoC Machine driver");
    198MODULE_LICENSE("GPL");
    199MODULE_ALIAS("platform:mxs-sgtl5000");