X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0288-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch;fp=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0288-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch;h=0000000000000000000000000000000000000000;hb=67dcc43f3a22dc3a7ac07a7065971b426feeb043;hp=c54b5af7a116ebd2e17449e398898a1a2e6b7a41;hpb=47a93a810f78adce5a130d287f82b28e9b54313c;p=openwrt%2Fopenwrt.git diff --git a/target/linux/brcm2708/patches-4.19/950-0288-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch b/target/linux/brcm2708/patches-4.19/950-0288-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch deleted file mode 100644 index c54b5af7a1..0000000000 --- a/target/linux/brcm2708/patches-4.19/950-0288-ASoC-add-driver-for-3Dlab-Nano-soundcard-2758.patch +++ /dev/null @@ -1,483 +0,0 @@ -From e740bd2cc3fcd632fcd6c8881b1fc671bcde5914 Mon Sep 17 00:00:00 2001 -From: dev-3Dlab <45081440+dev-3Dlab@users.noreply.github.com> -Date: Wed, 5 Dec 2018 10:59:11 +0100 -Subject: [PATCH 288/806] ASoC: add driver for 3Dlab Nano soundcard (#2758) - -Signed-off-by: GT ---- - .../overlays/3dlab-nano-player-overlay.dts | 32 ++ - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - sound/soc/bcm/3dlab-nano-player.c | 370 ++++++++++++++++++ - sound/soc/bcm/Kconfig | 6 + - sound/soc/bcm/Makefile | 2 + - 8 files changed, 419 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts - create mode 100644 sound/soc/bcm/3dlab-nano-player.c - ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/3dlab-nano-player-overlay.dts -@@ -0,0 +1,32 @@ -+// Definitions for 3Dlab Nano Player -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2c>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ nano-player@41 { -+ compatible = "3dlab,nano-player"; -+ reg = <0x41>; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -+ -+// EOF ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -1,6 +1,7 @@ - # Overlays for the Raspberry Pi platform - - dtbo-$(CONFIG_ARCH_BCM2835) += \ -+ 3dlab-nano-player.dtbo \ - adau1977-adc.dtbo \ - adau7002-simple.dtbo \ - ads1015.dtbo \ ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -199,6 +199,12 @@ Params: - and the other i2c baudrate parameters. - - -+Name: 3dlab-nano-player -+Info: Configures the 3Dlab Nano Player -+Load: dtoverlay=3dlab-nano-player -+Params: -+ -+ - Name: adau1977-adc - Info: Overlay for activation of ADAU1977 ADC codec over I2C for control - and I2S for data. ---- /dev/null -+++ b/sound/soc/bcm/3dlab-nano-player.c -@@ -0,0 +1,370 @@ -+/* -+ * 3Dlab Nano Player ALSA SoC Audio driver. -+ * -+ * Copyright (C) 2018 3Dlab. -+ * -+ * Author: GT -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#define NANO_ID 0x00 -+#define NANO_VER 0x01 -+#define NANO_CFG 0x02 -+#define NANO_STATUS 0x03 -+#define NANO_SPI_ADDR 0x04 -+#define NANO_SPI_DATA 0x05 -+ -+#define NANO_ID_VAL 0x3D -+#define NANO_CFG_OFF 0x00 -+#define NANO_CFG_MULT1 0 -+#define NANO_CFG_MULT2 1 -+#define NANO_CFG_MULT4 2 -+#define NANO_CFG_MULT8 3 -+#define NANO_CFG_MULT16 4 -+#define NANO_CFG_CLK22 0 -+#define NANO_CFG_CLK24 BIT(3) -+#define NANO_CFG_DSD BIT(4) -+#define NANO_CFG_ENA BIT(5) -+#define NANO_CFG_BLINK BIT(6) -+#define NANO_STATUS_P1 BIT(0) -+#define NANO_STATUS_P2 BIT(1) -+#define NANO_STATUS_FLG BIT(2) -+#define NANO_STATUS_CLK BIT(3) -+#define NANO_SPI_READ 0 -+#define NANO_SPI_WRITE BIT(5) -+ -+#define NANO_DAC_CTRL1 0x00 -+#define NANO_DAC_CTRL2 0x01 -+#define NANO_DAC_CTRL3 0x02 -+#define NANO_DAC_LATT 0x03 -+#define NANO_DAC_RATT 0x04 -+ -+#define NANO_CTRL2_VAL 0x22 -+ -+static int nano_player_spi_write(struct regmap *map, -+ unsigned int reg, unsigned int val) -+{ -+ /* indirect register access */ -+ regmap_write(map, NANO_SPI_DATA, val); -+ regmap_write(map, NANO_SPI_ADDR, reg | NANO_SPI_WRITE); -+ return 0; -+} -+ -+static int nano_player_ctrl_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ /* describe control element */ -+ if (strstr(kcontrol->id.name, "Volume")) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 100; -+ } else { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 1; -+ } -+ -+ return 0; -+} -+ -+static int nano_player_ctrl_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ /* program control value to hardware */ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct regmap *regmap = snd_soc_card_get_drvdata(card); -+ -+ if (strstr(kcontrol->id.name, "Volume")) { -+ unsigned int vol = ucontrol->value.integer.value[0]; -+ unsigned int att = 255 - (2 * (100 - vol)); -+ -+ nano_player_spi_write(regmap, NANO_DAC_LATT, att); -+ nano_player_spi_write(regmap, NANO_DAC_RATT, att); -+ kcontrol->private_value = vol; -+ } else { -+ unsigned int mute = ucontrol->value.integer.value[0]; -+ unsigned int reg = NANO_CTRL2_VAL | mute; -+ -+ nano_player_spi_write(regmap, NANO_DAC_CTRL2, reg); -+ kcontrol->private_value = mute; -+ } -+ return 0; -+} -+ -+static int nano_player_ctrl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ /* return last programmed value */ -+ ucontrol->value.integer.value[0] = kcontrol->private_value; -+ return 0; -+} -+ -+#define SOC_NANO_PLAYER_CTRL(xname) \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ -+ .info = nano_player_ctrl_info, \ -+ .put = nano_player_ctrl_put, \ -+ .get = nano_player_ctrl_get } -+ -+static const struct snd_kcontrol_new nano_player_controls[] = { -+ SOC_NANO_PLAYER_CTRL("Master Playback Volume"), -+ SOC_NANO_PLAYER_CTRL("Master Playback Switch"), -+}; -+ -+static const unsigned int nano_player_rates[] = { -+ 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, -+ 705600, 768000 /* only possible with fast clocks */ -+}; -+ -+static struct snd_pcm_hw_constraint_list nano_player_constraint_rates = { -+ .list = nano_player_rates, -+ .count = ARRAY_SIZE(nano_player_rates), -+}; -+ -+static int nano_player_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_card *card = rtd->card; -+ struct regmap *regmap = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_stream *cpu = &rtd->cpu_dai->driver->playback; -+ struct snd_soc_pcm_stream *codec = &rtd->codec_dai->driver->playback; -+ unsigned int sample_bits = 32; -+ unsigned int val; -+ -+ /* configure cpu dai */ -+ cpu->formats |= SNDRV_PCM_FMTBIT_DSD_U32_LE; -+ cpu->rate_max = 768000; -+ -+ /* configure dummy codec dai */ -+ codec->rate_min = 44100; -+ codec->rates = SNDRV_PCM_RATE_KNOT; -+ codec->formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_LE; -+ -+ /* configure max supported rate */ -+ regmap_read(regmap, NANO_STATUS, &val); -+ if (val & NANO_STATUS_CLK) { -+ dev_notice(card->dev, "Board with fast clocks installed\n"); -+ codec->rate_max = 768000; -+ } else { -+ dev_notice(card->dev, "Board with normal clocks installed\n"); -+ codec->rate_max = 384000; -+ } -+ -+ /* frame length enforced by hardware */ -+ return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, sample_bits * 2); -+} -+ -+static int nano_player_startup(struct snd_pcm_substream *substream) -+{ -+ return snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &nano_player_constraint_rates); -+} -+ -+static int nano_player_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_card *card = rtd->card; -+ struct regmap *regmap = snd_soc_card_get_drvdata(card); -+ unsigned int config = NANO_CFG_ENA; -+ struct snd_mask *fmt; -+ -+ /* configure PCM or DSD */ -+ fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); -+ if (snd_mask_test(fmt, SNDRV_PCM_FORMAT_DSD_U32_LE)) { -+ /* embed DSD in PCM data */ -+ snd_mask_none(fmt); -+ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S32_LE); -+ /* enable DSD mode */ -+ config |= NANO_CFG_DSD; -+ } -+ -+ /* configure clocks */ -+ switch (params_rate(params)) { -+ case 44100: -+ config |= NANO_CFG_MULT1 | NANO_CFG_CLK22; -+ break; -+ case 88200: -+ config |= NANO_CFG_MULT2 | NANO_CFG_CLK22; -+ break; -+ case 176400: -+ config |= NANO_CFG_MULT4 | NANO_CFG_CLK22; -+ break; -+ case 352800: -+ config |= NANO_CFG_MULT8 | NANO_CFG_CLK22; -+ break; -+ case 705600: -+ config |= NANO_CFG_MULT16 | NANO_CFG_CLK22; -+ break; -+ case 48000: -+ config |= NANO_CFG_MULT1 | NANO_CFG_CLK24; -+ break; -+ case 96000: -+ config |= NANO_CFG_MULT2 | NANO_CFG_CLK24; -+ break; -+ case 192000: -+ config |= NANO_CFG_MULT4 | NANO_CFG_CLK24; -+ break; -+ case 384000: -+ config |= NANO_CFG_MULT8 | NANO_CFG_CLK24; -+ break; -+ case 768000: -+ config |= NANO_CFG_MULT16 | NANO_CFG_CLK24; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ dev_dbg(card->dev, "Send CFG register 0x%02X\n", config); -+ return regmap_write(regmap, NANO_CFG, config); -+} -+ -+static struct snd_soc_ops nano_player_ops = { -+ .startup = nano_player_startup, -+ .hw_params = nano_player_hw_params, -+}; -+ -+static struct snd_soc_dai_link nano_player_link = { -+ .name = "3Dlab Nano Player", -+ .stream_name = "3Dlab Nano Player HiFi", -+ .platform_name = "bcm2708-i2s.0", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_name = "snd-soc-dummy", -+ .codec_dai_name = "snd-soc-dummy-dai", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_CONT | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .init = nano_player_init, -+ .ops = &nano_player_ops, -+}; -+ -+static const struct regmap_config nano_player_regmap = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .max_register = 128, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ -+static int nano_player_card_probe(struct snd_soc_card *card) -+{ -+ struct regmap *regmap = snd_soc_card_get_drvdata(card); -+ unsigned int val; -+ -+ /* check hardware integrity */ -+ regmap_read(regmap, NANO_ID, &val); -+ if (val != NANO_ID_VAL) { -+ dev_err(card->dev, "Invalid ID register 0x%02X\n", val); -+ return -ENODEV; -+ } -+ -+ /* report version to the user */ -+ regmap_read(regmap, NANO_VER, &val); -+ dev_notice(card->dev, "Started 3Dlab Nano Player driver (v%d)\n", val); -+ -+ /* enable internal audio bus and blink status LED */ -+ return regmap_write(regmap, NANO_CFG, NANO_CFG_ENA | NANO_CFG_BLINK); -+} -+ -+static int nano_player_card_remove(struct snd_soc_card *card) -+{ -+ /* disable internal audio bus */ -+ struct regmap *regmap = snd_soc_card_get_drvdata(card); -+ -+ return regmap_write(regmap, NANO_CFG, NANO_CFG_OFF); -+} -+ -+static struct snd_soc_card nano_player_card = { -+ .name = "3Dlab_Nano_Player", -+ .owner = THIS_MODULE, -+ .dai_link = &nano_player_link, -+ .num_links = 1, -+ .controls = nano_player_controls, -+ .num_controls = ARRAY_SIZE(nano_player_controls), -+ .probe = nano_player_card_probe, -+ .remove = nano_player_card_remove, -+}; -+ -+static int nano_player_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ struct regmap *regmap; -+ int ret; -+ -+ regmap = devm_regmap_init_i2c(i2c, &nano_player_regmap); -+ if (IS_ERR(regmap)) { -+ ret = PTR_ERR(regmap); -+ dev_err(&i2c->dev, "Failed to init regmap %d\n", ret); -+ return ret; -+ } -+ -+ if (i2c->dev.of_node) { -+ struct snd_soc_dai_link *dai = &nano_player_link; -+ struct device_node *node; -+ -+ /* cpu handle configured by device tree */ -+ node = of_parse_phandle(i2c->dev.of_node, "i2s-controller", 0); -+ if (node) { -+ dai->platform_name = NULL; -+ dai->platform_of_node = node; -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = node; -+ } -+ } -+ -+ nano_player_card.dev = &i2c->dev; -+ snd_soc_card_set_drvdata(&nano_player_card, regmap); -+ ret = devm_snd_soc_register_card(&i2c->dev, &nano_player_card); -+ -+ if (ret && ret != -EPROBE_DEFER) -+ dev_err(&i2c->dev, "Failed to register card %d\n", ret); -+ -+ return ret; -+} -+ -+static const struct of_device_id nano_player_of_match[] = { -+ { .compatible = "3dlab,nano-player", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, nano_player_of_match); -+ -+static const struct i2c_device_id nano_player_i2c_id[] = { -+ { "nano-player", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, nano_player_i2c_id); -+ -+static struct i2c_driver nano_player_i2c_driver = { -+ .probe = nano_player_i2c_probe, -+ .id_table = nano_player_i2c_id, -+ .driver = { -+ .name = "nano-player", -+ .owner = THIS_MODULE, -+ .of_match_table = nano_player_of_match, -+ }, -+}; -+ -+module_i2c_driver(nano_player_i2c_driver); -+ -+MODULE_DESCRIPTION("ASoC 3Dlab Nano Player driver"); -+MODULE_AUTHOR("GT "); -+MODULE_LICENSE("GPL v2"); -+ -+/* EOF */ ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -17,6 +17,12 @@ config SND_SOC_CYGNUS - - If you don't know what to do here, say N. - -+config SND_BCM2708_SOC_3DLAB_NANO_PLAYER -+ tristate "Support for 3Dlab Nano Player" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ help -+ Say Y or M if you want to add support for 3Dlab Nano Player. -+ - config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD - tristate "Support for Google voiceHAT soundcard" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc- - snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o - - # BCM2708 Machine Support -+snd-soc-3dlab-nano-player-objs := 3dlab-nano-player.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-justboom-dac-objs := justboom-dac.o - snd-soc-rpi-cirrus-objs := rpi-cirrus.o -@@ -31,6 +32,7 @@ snd-soc-fe-pi-audio-objs := fe-pi-audio. - snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o - snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o - -+obj-$(CONFIG_SND_BCM2708_SOC_3DLAB_NANO_PLAYER) += snd-soc-3dlab-nano-player.o - obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o