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

h1940_uda1380.c (5437B)


      1// SPDX-License-Identifier: GPL-2.0+
      2//
      3// h1940_uda1380.c - ALSA SoC Audio Layer
      4//
      5// Copyright (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
      6// Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
      7//
      8// Based on version from Arnaud Patard <arnaud.patard@rtp-net.org>
      9
     10#include <linux/types.h>
     11#include <linux/gpio.h>
     12#include <linux/module.h>
     13
     14#include <sound/soc.h>
     15#include <sound/jack.h>
     16
     17#include "regs-iis.h"
     18#include "s3c24xx-i2s.h"
     19
     20static const unsigned int rates[] = {
     21	11025,
     22	22050,
     23	44100,
     24};
     25
     26static const struct snd_pcm_hw_constraint_list hw_rates = {
     27	.count = ARRAY_SIZE(rates),
     28	.list = rates,
     29};
     30
     31static struct gpio_desc *gpiod_speaker_power;
     32
     33static struct snd_soc_jack hp_jack;
     34
     35static struct snd_soc_jack_pin hp_jack_pins[] = {
     36	{
     37		.pin	= "Headphone Jack",
     38		.mask	= SND_JACK_HEADPHONE,
     39	},
     40	{
     41		.pin	= "Speaker",
     42		.mask	= SND_JACK_HEADPHONE,
     43		.invert	= 1,
     44	},
     45};
     46
     47static struct snd_soc_jack_gpio hp_jack_gpios[] = {
     48	{
     49		.name			= "hp-gpio",
     50		.report			= SND_JACK_HEADPHONE,
     51		.invert			= 1,
     52		.debounce_time		= 200,
     53	},
     54};
     55
     56static int h1940_startup(struct snd_pcm_substream *substream)
     57{
     58	struct snd_pcm_runtime *runtime = substream->runtime;
     59
     60	return snd_pcm_hw_constraint_list(runtime, 0,
     61					SNDRV_PCM_HW_PARAM_RATE,
     62					&hw_rates);
     63}
     64
     65static int h1940_hw_params(struct snd_pcm_substream *substream,
     66				struct snd_pcm_hw_params *params)
     67{
     68	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
     69	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
     70	int div;
     71	int ret;
     72	unsigned int rate = params_rate(params);
     73
     74	switch (rate) {
     75	case 11025:
     76	case 22050:
     77	case 44100:
     78		div = s3c24xx_i2s_get_clockrate() / (384 * rate);
     79		if (s3c24xx_i2s_get_clockrate() % (384 * rate) > (192 * rate))
     80			div++;
     81		break;
     82	default:
     83		dev_err(rtd->dev, "%s: rate %d is not supported\n",
     84			__func__, rate);
     85		return -EINVAL;
     86	}
     87
     88	/* select clock source */
     89	ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, rate,
     90			SND_SOC_CLOCK_OUT);
     91	if (ret < 0)
     92		return ret;
     93
     94	/* set MCLK division for sample rate */
     95	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
     96		S3C2410_IISMOD_384FS);
     97	if (ret < 0)
     98		return ret;
     99
    100	/* set BCLK division for sample rate */
    101	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
    102		S3C2410_IISMOD_32FS);
    103	if (ret < 0)
    104		return ret;
    105
    106	/* set prescaler division for sample rate */
    107	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
    108		S3C24XX_PRESCALE(div, div));
    109	if (ret < 0)
    110		return ret;
    111
    112	return 0;
    113}
    114
    115static const struct snd_soc_ops h1940_ops = {
    116	.startup	= h1940_startup,
    117	.hw_params	= h1940_hw_params,
    118};
    119
    120static int h1940_spk_power(struct snd_soc_dapm_widget *w,
    121				struct snd_kcontrol *kcontrol, int event)
    122{
    123	if (SND_SOC_DAPM_EVENT_ON(event))
    124		gpiod_set_value(gpiod_speaker_power, 1);
    125	else
    126		gpiod_set_value(gpiod_speaker_power, 0);
    127
    128	return 0;
    129}
    130
    131/* h1940 machine dapm widgets */
    132static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
    133	SND_SOC_DAPM_HP("Headphone Jack", NULL),
    134	SND_SOC_DAPM_MIC("Mic Jack", NULL),
    135	SND_SOC_DAPM_SPK("Speaker", h1940_spk_power),
    136};
    137
    138/* h1940 machine audio_map */
    139static const struct snd_soc_dapm_route audio_map[] = {
    140	/* headphone connected to VOUTLHP, VOUTRHP */
    141	{"Headphone Jack", NULL, "VOUTLHP"},
    142	{"Headphone Jack", NULL, "VOUTRHP"},
    143
    144	/* ext speaker connected to VOUTL, VOUTR  */
    145	{"Speaker", NULL, "VOUTL"},
    146	{"Speaker", NULL, "VOUTR"},
    147
    148	/* mic is connected to VINM */
    149	{"VINM", NULL, "Mic Jack"},
    150};
    151
    152static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
    153{
    154	snd_soc_card_jack_new_pins(rtd->card, "Headphone Jack",
    155		SND_JACK_HEADPHONE,
    156		&hp_jack, hp_jack_pins, ARRAY_SIZE(hp_jack_pins));
    157
    158	snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
    159		hp_jack_gpios);
    160
    161	return 0;
    162}
    163
    164/* s3c24xx digital audio interface glue - connects codec <--> CPU */
    165SND_SOC_DAILINK_DEFS(uda1380,
    166	DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")),
    167	DAILINK_COMP_ARRAY(COMP_CODEC("uda1380-codec.0-001a", "uda1380-hifi")),
    168	DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis")));
    169
    170static struct snd_soc_dai_link h1940_uda1380_dai[] = {
    171	{
    172		.name		= "uda1380",
    173		.stream_name	= "UDA1380 Duplex",
    174		.init		= h1940_uda1380_init,
    175		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
    176				  SND_SOC_DAIFMT_CBS_CFS,
    177		.ops		= &h1940_ops,
    178		SND_SOC_DAILINK_REG(uda1380),
    179	},
    180};
    181
    182static struct snd_soc_card h1940_asoc = {
    183	.name = "h1940",
    184	.owner = THIS_MODULE,
    185	.dai_link = h1940_uda1380_dai,
    186	.num_links = ARRAY_SIZE(h1940_uda1380_dai),
    187
    188	.dapm_widgets = uda1380_dapm_widgets,
    189	.num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
    190	.dapm_routes = audio_map,
    191	.num_dapm_routes = ARRAY_SIZE(audio_map),
    192};
    193
    194static int h1940_probe(struct platform_device *pdev)
    195{
    196	struct device *dev = &pdev->dev;
    197
    198	h1940_asoc.dev = dev;
    199	hp_jack_gpios[0].gpiod_dev = dev;
    200	gpiod_speaker_power = devm_gpiod_get(&pdev->dev, "speaker-power",
    201					     GPIOD_OUT_LOW);
    202
    203	if (IS_ERR(gpiod_speaker_power)) {
    204		dev_err(dev, "Could not get gpio\n");
    205		return PTR_ERR(gpiod_speaker_power);
    206	}
    207
    208	return devm_snd_soc_register_card(dev, &h1940_asoc);
    209}
    210
    211static struct platform_driver h1940_audio_driver = {
    212	.driver = {
    213		.name = "h1940-audio",
    214		.pm = &snd_soc_pm_ops,
    215	},
    216	.probe = h1940_probe,
    217};
    218module_platform_driver(h1940_audio_driver);
    219
    220/* Module information */
    221MODULE_AUTHOR("Arnaud Patard, Vasily Khoruzhick");
    222MODULE_DESCRIPTION("ALSA SoC H1940");
    223MODULE_LICENSE("GPL");
    224MODULE_ALIAS("platform:h1940-audio");