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

arndale.c (5762B)


      1// SPDX-License-Identifier: GPL-2.0+
      2//
      3// Copyright (c) 2014, Insignal Co., Ltd.
      4//
      5//  Author: Claude <claude@insginal.co.kr>
      6
      7#include <linux/module.h>
      8#include <linux/of_device.h>
      9#include <linux/platform_device.h>
     10#include <linux/clk.h>
     11
     12#include <sound/soc.h>
     13#include <sound/soc-dapm.h>
     14#include <sound/pcm.h>
     15#include <sound/pcm_params.h>
     16
     17#include "../codecs/wm8994.h"
     18#include "i2s.h"
     19
     20static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream,
     21				    struct snd_pcm_hw_params *params)
     22{
     23	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     24	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
     25	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
     26	int rfs, ret;
     27	unsigned long rclk;
     28
     29	rfs = 256;
     30
     31	rclk = params_rate(params) * rfs;
     32
     33	ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
     34					0, SND_SOC_CLOCK_OUT);
     35	if (ret < 0)
     36		return ret;
     37
     38	ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
     39					0, SND_SOC_CLOCK_OUT);
     40
     41	if (ret < 0)
     42		return ret;
     43
     44	ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_OUT);
     45	if (ret < 0)
     46		return ret;
     47
     48	return 0;
     49}
     50
     51static const struct snd_soc_ops arndale_rt5631_ops = {
     52	.hw_params = arndale_rt5631_hw_params,
     53};
     54
     55static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream,
     56				    struct snd_pcm_hw_params *params)
     57{
     58	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     59	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
     60	unsigned int rfs, rclk;
     61
     62	/* Ensure AIF1CLK is >= 3 MHz for optimal performance */
     63	if (params_width(params) == 24)
     64		rfs = 384;
     65	else if (params_rate(params) == 8000 || params_rate(params) == 11025)
     66		rfs = 512;
     67	else
     68		rfs = 256;
     69
     70	rclk = params_rate(params) * rfs;
     71
     72	/*
     73	 * We add 1 to the frequency value to ensure proper EPLL setting
     74	 * for each audio sampling rate (see epll_24mhz_tbl in drivers/clk/
     75	 * samsung/clk-exynos5250.c for list of available EPLL rates).
     76	 * The CODEC uses clk API and the value will be rounded hence the MCLK1
     77	 * clock's frequency will still be exact multiple of the sample rate.
     78	 */
     79	return snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1,
     80					rclk + 1, SND_SOC_CLOCK_IN);
     81}
     82
     83static const struct snd_soc_ops arndale_wm1811_ops = {
     84	.hw_params = arndale_wm1811_hw_params,
     85};
     86
     87SND_SOC_DAILINK_DEFS(rt5631_hifi,
     88	DAILINK_COMP_ARRAY(COMP_EMPTY()),
     89	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-aif1")),
     90	DAILINK_COMP_ARRAY(COMP_EMPTY()));
     91
     92static struct snd_soc_dai_link arndale_rt5631_dai[] = {
     93	{
     94		.name = "RT5631 HiFi",
     95		.stream_name = "Primary",
     96		.dai_fmt = SND_SOC_DAIFMT_I2S
     97			| SND_SOC_DAIFMT_NB_NF
     98			| SND_SOC_DAIFMT_CBS_CFS,
     99		.ops = &arndale_rt5631_ops,
    100		SND_SOC_DAILINK_REG(rt5631_hifi),
    101	},
    102};
    103
    104SND_SOC_DAILINK_DEFS(wm1811_hifi,
    105	DAILINK_COMP_ARRAY(COMP_EMPTY()),
    106	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
    107	DAILINK_COMP_ARRAY(COMP_EMPTY()));
    108
    109static struct snd_soc_dai_link arndale_wm1811_dai[] = {
    110	{
    111		.name = "WM1811 HiFi",
    112		.stream_name = "Primary",
    113		.dai_fmt = SND_SOC_DAIFMT_I2S
    114			| SND_SOC_DAIFMT_NB_NF
    115			| SND_SOC_DAIFMT_CBM_CFM,
    116		.ops = &arndale_wm1811_ops,
    117		SND_SOC_DAILINK_REG(wm1811_hifi),
    118	},
    119};
    120
    121static struct snd_soc_card arndale_rt5631 = {
    122	.name = "Arndale RT5631",
    123	.owner = THIS_MODULE,
    124	.dai_link = arndale_rt5631_dai,
    125	.num_links = ARRAY_SIZE(arndale_rt5631_dai),
    126};
    127
    128static struct snd_soc_card arndale_wm1811 = {
    129	.name = "Arndale WM1811",
    130	.owner = THIS_MODULE,
    131	.dai_link = arndale_wm1811_dai,
    132	.num_links = ARRAY_SIZE(arndale_wm1811_dai),
    133};
    134
    135static void arndale_put_of_nodes(struct snd_soc_card *card)
    136{
    137	struct snd_soc_dai_link *dai_link;
    138	int i;
    139
    140	for_each_card_prelinks(card, i, dai_link) {
    141		of_node_put(dai_link->cpus->of_node);
    142		of_node_put(dai_link->codecs->of_node);
    143	}
    144}
    145
    146static int arndale_audio_probe(struct platform_device *pdev)
    147{
    148	struct device_node *np = pdev->dev.of_node;
    149	struct snd_soc_card *card;
    150	struct snd_soc_dai_link *dai_link;
    151	int ret;
    152
    153	card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
    154	card->dev = &pdev->dev;
    155	dai_link = card->dai_link;
    156
    157	dai_link->cpus->of_node = of_parse_phandle(np, "samsung,audio-cpu", 0);
    158	if (!dai_link->cpus->of_node) {
    159		dev_err(&pdev->dev,
    160			"Property 'samsung,audio-cpu' missing or invalid\n");
    161		return -EINVAL;
    162	}
    163
    164	if (!dai_link->platforms->name)
    165		dai_link->platforms->of_node = dai_link->cpus->of_node;
    166
    167	dai_link->codecs->of_node = of_parse_phandle(np, "samsung,audio-codec", 0);
    168	if (!dai_link->codecs->of_node) {
    169		dev_err(&pdev->dev,
    170			"Property 'samsung,audio-codec' missing or invalid\n");
    171		ret = -EINVAL;
    172		goto err_put_of_nodes;
    173	}
    174
    175	ret = devm_snd_soc_register_card(card->dev, card);
    176	if (ret) {
    177		dev_err_probe(&pdev->dev, ret,
    178			      "snd_soc_register_card() failed\n");
    179		goto err_put_of_nodes;
    180	}
    181	return 0;
    182
    183err_put_of_nodes:
    184	arndale_put_of_nodes(card);
    185	return ret;
    186}
    187
    188static int arndale_audio_remove(struct platform_device *pdev)
    189{
    190	struct snd_soc_card *card = platform_get_drvdata(pdev);
    191
    192	arndale_put_of_nodes(card);
    193	return 0;
    194}
    195
    196static const struct of_device_id arndale_audio_of_match[] = {
    197	{ .compatible = "samsung,arndale-rt5631",  .data = &arndale_rt5631 },
    198	{ .compatible = "samsung,arndale-alc5631", .data = &arndale_rt5631 },
    199	{ .compatible = "samsung,arndale-wm1811",  .data = &arndale_wm1811 },
    200	{},
    201};
    202MODULE_DEVICE_TABLE(of, arndale_audio_of_match);
    203
    204static struct platform_driver arndale_audio_driver = {
    205	.driver = {
    206		.name = "arndale-audio",
    207		.pm = &snd_soc_pm_ops,
    208		.of_match_table = arndale_audio_of_match,
    209	},
    210	.probe = arndale_audio_probe,
    211	.remove = arndale_audio_remove,
    212};
    213
    214module_platform_driver(arndale_audio_driver);
    215
    216MODULE_AUTHOR("Claude <claude@insignal.co.kr>");
    217MODULE_DESCRIPTION("ALSA SoC Driver for Arndale Board");
    218MODULE_LICENSE("GPL");