summaryrefslogtreecommitdiff
path: root/sound/soc/samsung/arndale.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-11-27 07:04:35 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2019-11-27 07:04:35 +0300
commit3f1b210a7f97f7e75c56174ada476fba2d36f340 (patch)
tree222eb9e62a16270877864787b734ab8e8349666f /sound/soc/samsung/arndale.c
parent361b0d286afea0d867537536977a695b5557d133 (diff)
parentbf2aa5cadd1c7bb91af4b5b1218e643cfffb5c9a (diff)
downloadlinux-3f1b210a7f97f7e75c56174ada476fba2d36f340.tar.xz
Merge tag 'sound-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "There have been some significant changes in the core side, both for ALSA and ASoC, while lots of development have been seen in SOF, as well as many small fixes/improvements for ASoC codecs and platforms. Below is a highlight in this cycle: Core: - The unification of PCM vmalloc buffer allocation helpers into the standard API - Clean up of the default PCM mmap handling for vmalloc & SG-buffer - Fix potential races at ALSA timer open - A few new PCM API extensions; just preliminary core changes, the actual changes in drivers will be merged in 5.6 - Continued ASoC componentization works; now almost everything is a common ASoC component object. A lot of refactoring and simplification have been done along with it. ASoC: - Many fixes to the Sound Open Firmware (SOF) code - Wake on voice support for Chromebooks - SPI support and trigger word detection for RT5677 - New drivers for Analog Devices ADAU7118, Intel Cannonlake systems with RT1011 and RT5682, Texas Instruments TAS2562 and TAS2770 HD-audio: - Improved Intel DSP configuration / probe code for SOF - Plumbing the legacy HD-audio driver with Intel SOF HDMI - DP-MST support for Nvidia HDMI codecs - Realtek quirks cleanups and new additions as usual Others: - Lots of refactoring and cleanups for FireWire; period-size sharing, h/w IRQ interval configuration, clock recovery improvements, etc - USB-audio: Scarlett mixer quirks - Cleanups of PCM calls in various drivers (including media and USB) to adapt the core API changes" * tag 'sound-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (497 commits) ALSA: usb-audio: Fix Focusrite Scarlett 6i6 gen1 - input handling ALSA: hda/realtek - Enable internal speaker of ASUS UX431FLC ALSA: aloop: Fix dependency on timer API ASoC: DMI long name - avoid to add board name if matches with product name ASoC: improve the DMI long card code in asoc-core ASoC: rsnd: fix DALIGN register for SSIU ALSA: aloop: Avoid unexpected timer event callback tasklets ALSA: aloop: Remove redundant locking in timer open function ASoC: component: Add sync_stop PCM ops ASoC: pcm: Make ioctl ops optional ALSA: hda/hdmi - Clear codec->relaxed_resume flag at unbinding ALSA: hda - Disable audio component for legacy Nvidia HDMI codecs ALSA: cs4236: fix error return comparison of an unsigned integer ALSA: usb-audio: Fix NULL dereference at parsing BADD ALSA: usb-audio: Fix Scarlett 6i6 Gen 2 port data ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop ALSA: hda/realtek - Move some alc236 pintbls to fallback table ALSA: hda/realtek - Move some alc256 pintbls to fallback table ALSA: docs: Update about the new PCM sync_stop ops ALSA: pcm: Add card sync_irq field ...
Diffstat (limited to 'sound/soc/samsung/arndale.c')
-rw-r--r--sound/soc/samsung/arndale.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c
new file mode 100644
index 000000000000..d64602950cbd
--- /dev/null
+++ b/sound/soc/samsung/arndale.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2014, Insignal Co., Ltd.
+//
+// Author: Claude <claude@insginal.co.kr>
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "../codecs/wm8994.h"
+#include "i2s.h"
+
+static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int rfs, ret;
+ unsigned long rclk;
+
+ rfs = 256;
+
+ rclk = params_rate(params) * rfs;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
+ 0, SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
+ 0, SND_SOC_CLOCK_OUT);
+
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops arndale_rt5631_ops = {
+ .hw_params = arndale_rt5631_hw_params,
+};
+
+static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ unsigned int rfs, rclk;
+
+ /* Ensure AIF1CLK is >= 3 MHz for optimal performance */
+ if (params_width(params) == 24)
+ rfs = 384;
+ else if (params_rate(params) == 8000 || params_rate(params) == 11025)
+ rfs = 512;
+ else
+ rfs = 256;
+
+ rclk = params_rate(params) * rfs;
+
+ /*
+ * We add 1 to the frequency value to ensure proper EPLL setting
+ * for each audio sampling rate (see epll_24mhz_tbl in drivers/clk/
+ * samsung/clk-exynos5250.c for list of available EPLL rates).
+ * The CODEC uses clk API and the value will be rounded hence the MCLK1
+ * clock's frequency will still be exact multiple of the sample rate.
+ */
+ return snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1,
+ rclk + 1, SND_SOC_CLOCK_IN);
+}
+
+static struct snd_soc_ops arndale_wm1811_ops = {
+ .hw_params = arndale_wm1811_hw_params,
+};
+
+SND_SOC_DAILINK_DEFS(rt5631_hifi,
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-aif1")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link arndale_rt5631_dai[] = {
+ {
+ .name = "RT5631 HiFi",
+ .stream_name = "Primary",
+ .dai_fmt = SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS,
+ .ops = &arndale_rt5631_ops,
+ SND_SOC_DAILINK_REG(rt5631_hifi),
+ },
+};
+
+SND_SOC_DAILINK_DEFS(wm1811_hifi,
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link arndale_wm1811_dai[] = {
+ {
+ .name = "WM1811 HiFi",
+ .stream_name = "Primary",
+ .dai_fmt = SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ops = &arndale_wm1811_ops,
+ SND_SOC_DAILINK_REG(wm1811_hifi),
+ },
+};
+
+static struct snd_soc_card arndale_rt5631 = {
+ .name = "Arndale RT5631",
+ .owner = THIS_MODULE,
+ .dai_link = arndale_rt5631_dai,
+ .num_links = ARRAY_SIZE(arndale_rt5631_dai),
+};
+
+static struct snd_soc_card arndale_wm1811 = {
+ .name = "Arndale WM1811",
+ .owner = THIS_MODULE,
+ .dai_link = arndale_wm1811_dai,
+ .num_links = ARRAY_SIZE(arndale_wm1811_dai),
+};
+
+static void arndale_put_of_nodes(struct snd_soc_card *card)
+{
+ struct snd_soc_dai_link *dai_link;
+ int i;
+
+ for_each_card_prelinks(card, i, dai_link) {
+ of_node_put(dai_link->cpus->of_node);
+ of_node_put(dai_link->codecs->of_node);
+ }
+}
+
+static int arndale_audio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_card *card;
+ struct snd_soc_dai_link *dai_link;
+ int ret;
+
+ card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
+ card->dev = &pdev->dev;
+ dai_link = card->dai_link;
+
+ dai_link->cpus->of_node = of_parse_phandle(np, "samsung,audio-cpu", 0);
+ if (!dai_link->cpus->of_node) {
+ dev_err(&pdev->dev,
+ "Property 'samsung,audio-cpu' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ if (!dai_link->platforms->name)
+ dai_link->platforms->of_node = dai_link->cpus->of_node;
+
+ dai_link->codecs->of_node = of_parse_phandle(np, "samsung,audio-codec", 0);
+ if (!dai_link->codecs->of_node) {
+ dev_err(&pdev->dev,
+ "Property 'samsung,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err_put_of_nodes;
+ }
+
+ ret = devm_snd_soc_register_card(card->dev, card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
+ goto err_put_of_nodes;
+ }
+ return 0;
+
+err_put_of_nodes:
+ arndale_put_of_nodes(card);
+ return ret;
+}
+
+static int arndale_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ arndale_put_of_nodes(card);
+ return 0;
+}
+
+static const struct of_device_id arndale_audio_of_match[] = {
+ { .compatible = "samsung,arndale-rt5631", .data = &arndale_rt5631 },
+ { .compatible = "samsung,arndale-alc5631", .data = &arndale_rt5631 },
+ { .compatible = "samsung,arndale-wm1811", .data = &arndale_wm1811 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, arndale_audio_of_match);
+
+static struct platform_driver arndale_audio_driver = {
+ .driver = {
+ .name = "arndale-audio",
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = arndale_audio_of_match,
+ },
+ .probe = arndale_audio_probe,
+ .remove = arndale_audio_remove,
+};
+
+module_platform_driver(arndale_audio_driver);
+
+MODULE_AUTHOR("Claude <claude@insignal.co.kr>");
+MODULE_DESCRIPTION("ALSA SoC Driver for Arndale Board");
+MODULE_LICENSE("GPL");