openwrt/target/linux/bcm27xx/patches-6.6/950-1228-ASoC-add-driver-for-new-HiFiBerry-ADC-only-board-s.patch
Álvaro Fernández Rojas 538a1d740c bcm27xx: update to latest RPi patches
The patches were generated from the RPi repo with the following command:
git format-patch v6.6.58..rpi-6.6.y

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-10-31 13:44:23 +01:00

229 lines
7.3 KiB
Diff

From 784ef64631be19ef45a597e618c04a0f8b041307 Mon Sep 17 00:00:00 2001
From: j-schambacher <joerg@hifiberry.com>
Date: Tue, 20 Aug 2024 10:08:27 +0200
Subject: [PATCH 1228/1350] ASoC: add driver for new HiFiBerry ADC only
board(s)
Adds the driver for the soon to be released first ADC only board.
It includes the same ADC controls as used by the DAC+ADC Pro driver.
Signed-off-by: j-schambacher <joerg@hifiberry.com>
---
sound/soc/bcm/Kconfig | 7 ++
sound/soc/bcm/Makefile | 2 +
sound/soc/bcm/hifiberry_adc.c | 174 ++++++++++++++++++++++++++++++++++
3 files changed, 183 insertions(+)
create mode 100644 sound/soc/bcm/hifiberry_adc.c
--- a/sound/soc/bcm/Kconfig
+++ b/sound/soc/bcm/Kconfig
@@ -39,6 +39,13 @@ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SO
help
Say Y or M if you want to add support for voiceHAT soundcard.
+config SND_BCM2708_SOC_HIFIBERRY_ADC
+ tristate "Support for HifiBerry ADC"
+ select SND_SOC_PCM186X_I2C
+ select SND_RPI_HIFIBERRY_ADC
+ help
+ Say Y or M if you want to add support for HifiBerry ADC.
+
config SND_BCM2708_SOC_HIFIBERRY_DAC
tristate "Support for HifiBerry DAC and DAC8X"
select SND_SOC_PCM5102A
--- a/sound/soc/bcm/Makefile
+++ b/sound/soc/bcm/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) +
snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
# BCM2708 Machine Support
+snd-soc-hifiberry-adc-objs := hifiberry_adc.o
snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
snd-soc-hifiberry-dacplushd-objs := hifiberry_dacplushd.o
snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
@@ -51,6 +52,7 @@ snd-soc-chipdip-dac-objs := chipdip-dac.
snd-soc-dacberry400-objs := dacberry400.o
obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_ADC) += snd-soc-hifiberry-adc.o
obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += snd-soc-hifiberry-dacplushd.o
obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
--- /dev/null
+++ b/sound/soc/bcm/hifiberry_adc.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ASoC Driver for HiFiBerry ADC
+ *
+ * Author: Joerg Schambacher <joerg@hifiberry.com>
+ * Copyright 2024
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/tlv.h>
+
+#include "../codecs/pcm186x.h"
+#include "hifiberry_adc_controls.h"
+
+static bool leds_off;
+
+static int pcm1863_add_controls(struct snd_soc_component *component)
+{
+ snd_soc_add_component_controls(component,
+ pcm1863_snd_controls_card,
+ ARRAY_SIZE(pcm1863_snd_controls_card));
+ return 0;
+}
+
+static int snd_rpi_hifiberry_adc_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *adc = codec_dai->component;
+ int ret;
+
+ ret = pcm1863_add_controls(adc);
+ if (ret < 0)
+ dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
+ ret);
+
+ codec_dai->driver->capture.rates =
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000;
+
+ /* set GPIO2 to output, GPIO3 input */
+ snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
+ snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
+ if (leds_off)
+ snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
+ else
+ snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
+
+ return 0;
+}
+
+static int snd_rpi_hifiberry_adc_hw_params(
+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int channels = params_channels(params);
+ int width = snd_pcm_format_width(params_format(params));
+
+ /* Using powers of 2 allows for an integer clock divisor */
+ width = width <= 16 ? 16 : 32;
+
+ ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
+ return ret;
+}
+
+/* machine stream operations */
+static const struct snd_soc_ops snd_rpi_hifiberry_adc_ops = {
+ .hw_params = snd_rpi_hifiberry_adc_hw_params,
+};
+
+SND_SOC_DAILINK_DEFS(hifi,
+ DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("pcm186x.1-004a", "pcm1863-aif")),
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
+
+static struct snd_soc_dai_link snd_rpi_hifiberry_adc_dai[] = {
+{
+ .name = "HiFiBerry ADC",
+ .stream_name = "HiFiBerry ADC HiFi",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ops = &snd_rpi_hifiberry_adc_ops,
+ .init = snd_rpi_hifiberry_adc_init,
+ SND_SOC_DAILINK_REG(hifi),
+},
+};
+
+/* audio machine driver */
+static struct snd_soc_card snd_rpi_hifiberry_adc = {
+ .name = "snd_rpi_hifiberry_adc",
+ .driver_name = "HifiberryAdc",
+ .owner = THIS_MODULE,
+ .dai_link = snd_rpi_hifiberry_adc_dai,
+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_adc_dai),
+};
+
+static int snd_rpi_hifiberry_adc_probe(struct platform_device *pdev)
+{
+ int ret = 0, i = 0;
+ struct snd_soc_card *card = &snd_rpi_hifiberry_adc;
+
+ snd_rpi_hifiberry_adc.dev = &pdev->dev;
+ if (pdev->dev.of_node) {
+ struct device_node *i2s_node;
+ struct snd_soc_dai_link *dai;
+
+ dai = &snd_rpi_hifiberry_adc_dai[0];
+ i2s_node = of_parse_phandle(pdev->dev.of_node,
+ "i2s-controller", 0);
+ if (i2s_node) {
+ for (i = 0; i < card->num_links; i++) {
+ dai->cpus->dai_name = NULL;
+ dai->cpus->of_node = i2s_node;
+ dai->platforms->name = NULL;
+ dai->platforms->of_node = i2s_node;
+ }
+ }
+ }
+ leds_off = of_property_read_bool(pdev->dev.of_node,
+ "hifiberry-adc,leds_off");
+ ret = snd_soc_register_card(&snd_rpi_hifiberry_adc);
+ if (ret && ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "snd_soc_register_card() failed: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id snd_rpi_hifiberry_adc_of_match[] = {
+ { .compatible = "hifiberry,hifiberry-adc", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_adc_of_match);
+
+static struct platform_driver snd_rpi_hifiberry_adc_driver = {
+ .driver = {
+ .name = "snd-rpi-hifiberry-adc",
+ .owner = THIS_MODULE,
+ .of_match_table = snd_rpi_hifiberry_adc_of_match,
+ },
+ .probe = snd_rpi_hifiberry_adc_probe,
+};
+
+module_platform_driver(snd_rpi_hifiberry_adc_driver);
+
+MODULE_AUTHOR("Joerg Schambacher <joerg@hifiberry.com>");
+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry ADC");
+MODULE_LICENSE("GPL");