brcm2708: rename target to bcm27xx
[openwrt/staging/wigyori.git] / target / linux / brcm2708 / patches-4.19 / 950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch b/target/linux/brcm2708/patches-4.19/950-0792-sound-Add-the-HiFiBerry-DAC-HD-version.patch
deleted file mode 100644 (file)
index c8b8fd5..0000000
+++ /dev/null
@@ -1,776 +0,0 @@
-From bb4781b1dac98688a3cf64cf728a64d811ca6add Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?J=C3=B6rg=20Schambacher?=
- <j-schambacher@users.noreply.github.com>
-Date: Tue, 21 Jan 2020 15:58:39 +0100
-Subject: [PATCH] sound: Add the HiFiBerry DAC+HD version
-
-This adds the driver for the DAC+HD version supporting HiFiBerry's
-PCM179x based DACs. It also adds PLL control for clock generation.
-
-Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
----
- arch/arm/boot/dts/overlays/Makefile           |   1 +
- arch/arm/boot/dts/overlays/README             |   6 +
- .../overlays/hifiberry-dacplushd-overlay.dts  | 106 ++++++
- drivers/clk/Makefile                          |   1 +
- drivers/clk/clk-hifiberry-dachd.c             | 333 ++++++++++++++++++
- sound/soc/bcm/Kconfig                         |   7 +
- sound/soc/bcm/Makefile                        |   2 +
- sound/soc/bcm/hifiberry_dacplushd.c           | 235 ++++++++++++
- 13 files changed, 696 insertions(+)
- create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts
- create mode 100644 drivers/clk/clk-hifiberry-dachd.c
- create mode 100644 sound/soc/bcm/hifiberry_dacplushd.c
-
---- a/arch/arm/boot/dts/overlays/Makefile
-+++ b/arch/arm/boot/dts/overlays/Makefile
-@@ -57,6 +57,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
-       hifiberry-dacplusadc.dtbo \
-       hifiberry-dacplusadcpro.dtbo \
-       hifiberry-dacplusdsp.dtbo \
-+      hifiberry-dacplushd.dtbo \
-       hifiberry-digi.dtbo \
-       hifiberry-digi-pro.dtbo \
-       hy28a.dtbo \
---- a/arch/arm/boot/dts/overlays/README
-+++ b/arch/arm/boot/dts/overlays/README
-@@ -956,6 +956,12 @@ Load:   dtoverlay=hifiberry-dacplusdsp
- Params: <None>
-+Name:   hifiberry-dacplushd
-+Info:   Configures the HifiBerry DAC+ HD audio card
-+Load:   dtoverlay=hifiberry-dacplushd
-+Params: <None>
-+
-+
- Name:   hifiberry-digi
- Info:   Configures the HifiBerry Digi and Digi+ audio card
- Load:   dtoverlay=hifiberry-digi
---- /dev/null
-+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts
-@@ -0,0 +1,106 @@
-+// Definitions for HiFiBerry DAC+ HD
-+/dts-v1/;
-+/plugin/;
-+
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/ {
-+      compatible = "brcm,bcm2835";
-+
-+      fragment@0 {
-+              target-path = "/clocks";
-+              __overlay__ {
-+                      dachd_osc: pll_dachd_osc {
-+                              compatible = "hifiberry,dachd-clk";
-+                              #clock-cells = <0>;
-+                      };
-+              };
-+      };
-+
-+      fragment@1 {
-+              target = <&i2s>;
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      fragment@2 {
-+              target = <&i2c1>;
-+              __overlay__ {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "okay";
-+
-+                      pcm1792a@4c {
-+                              compatible = "ti,pcm1792a";
-+                              #sound-dai-cells = <0>;
-+                              #clock-cells = <0>;
-+                              clocks = <&dachd_osc>;
-+                              reg = <0x4c>;
-+                              status = "okay";
-+                      };
-+                      pll: pll@62 {
-+                              compatible = "hifiberry,dachd-clk";
-+                              #clock-cells = <0>;
-+                              reg = <0x62>;
-+                              clocks = <&dachd_osc>;
-+                              status = "okay";
-+                              common_pll_regs = [
-+                                      02 53 03 00 07 20 0F 00
-+                                      10 0D 11 1D 12 0D 13 8C
-+                                      14 8C 15 8C 16 8C 17 8C
-+                                      18 2A 1C 00 1D 0F 1F 00
-+                                      2A 00 2C 00 2F 00 30 00
-+                                      31 00 32 00 34 00 37 00
-+                                      38 00 39 00 3A 00 3B 01
-+                                      3E 00 3F 00 40 00 41 00
-+                                      5A 00 5B 00 95 00 96 00
-+                                      97 00 98 00 99 00 9A 00
-+                                      9B 00 A2 00 A3 00 A4 00
-+                                      B7 92 ];
-+                              192k_pll_regs = [
-+                                      1A 0C 1B 35 1E F0 20 09
-+                                      21 50 2B 02 2D 10 2E 40
-+                                      33 01 35 22 36 80 3C 22
-+                                      3D 46 ];
-+                              96k_pll_regs = [
-+                                      1A 0C 1B 35 1E F0 20 09
-+                                      21 50 2B 02 2D 10 2E 40
-+                                      33 01 35 47 36 00 3C 32
-+                                      3D 46 ];
-+                              48k_pll_regs = [
-+                                      1A 0C 1B 35 1E F0 20 09
-+                                      21 50 2B 02 2D 10 2E 40
-+                                      33 01 35 90 36 00 3C 42
-+                                      3D 46 ];
-+                              176k4_pll_regs = [
-+                                      1A 3D 1B 09 1E F3 20 13
-+                                      21 75 2B 04 2D 11 2E E0
-+                                      33 02 35 25 36 C0 3C 22
-+                                      3D 7A ];
-+                              88k2_pll_regs = [
-+                                      1A 3D 1B 09 1E F3 20 13
-+                                      21 75 2B 04 2D 11 2E E0
-+                                      33 01 35 4D 36 80 3C 32
-+                                      3D 7A ];
-+                              44k1_pll_regs = [
-+                                      1A 3D 1B 09 1E F3 20 13
-+                                      21 75 2B 04 2D 11 2E E0
-+                                      33 01 35 9D 36 00 3C 42
-+                                      3D 7A ];
-+                      };
-+              };
-+      };
-+
-+      fragment@3 {
-+              target = <&sound>;
-+              __overlay__ {
-+                      compatible = "hifiberry,hifiberry-dacplushd";
-+                      i2s-controller = <&i2s>;
-+                      clocks = <&pll 0>;
-+                      reset-gpio = <&gpio 16 GPIO_ACTIVE_LOW>;
-+                      status = "okay";
-+              };
-+      };
-+
-+};
---- a/drivers/clk/Makefile
-+++ b/drivers/clk/Makefile
-@@ -32,6 +32,7 @@ obj-$(CONFIG_COMMON_CLK_ASPEED)              += clk-
- obj-$(CONFIG_ARCH_HIGHBANK)           += clk-highbank.o
- obj-$(CONFIG_CLK_HSDK)                        += clk-hsdk-pll.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o
-+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += clk-hifiberry-dachd.o
- obj-$(CONFIG_COMMON_CLK_MAX77686)     += clk-max77686.o
- obj-$(CONFIG_COMMON_CLK_MAX9485)      += clk-max9485.o
- obj-$(CONFIG_ARCH_MOXART)             += clk-moxart.o
---- /dev/null
-+++ b/drivers/clk/clk-hifiberry-dachd.c
-@@ -0,0 +1,333 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Clock Driver for HiFiBerry DAC+ HD
-+ *
-+ * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
-+ *         Copyright 2020
-+ *
-+ * 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/clk-provider.h>
-+#include <linux/clk.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+#include <linux/i2c.h>
-+#include <linux/regmap.h>
-+
-+#define NO_PLL_RESET                  0
-+#define PLL_RESET                     1
-+#define HIFIBERRY_PLL_MAX_REGISTER    256
-+#define DEFAULT_RATE                  44100
-+
-+static struct reg_default hifiberry_pll_reg_defaults[] = {
-+      {0x02, 0x53}, {0x03, 0x00}, {0x07, 0x20}, {0x0F, 0x00},
-+      {0x10, 0x0D}, {0x11, 0x1D}, {0x12, 0x0D}, {0x13, 0x8C},
-+      {0x14, 0x8C}, {0x15, 0x8C}, {0x16, 0x8C}, {0x17, 0x8C},
-+      {0x18, 0x2A}, {0x1C, 0x00}, {0x1D, 0x0F}, {0x1F, 0x00},
-+      {0x2A, 0x00}, {0x2C, 0x00}, {0x2F, 0x00}, {0x30, 0x00},
-+      {0x31, 0x00}, {0x32, 0x00}, {0x34, 0x00}, {0x37, 0x00},
-+      {0x38, 0x00}, {0x39, 0x00}, {0x3A, 0x00}, {0x3B, 0x01},
-+      {0x3E, 0x00}, {0x3F, 0x00}, {0x40, 0x00}, {0x41, 0x00},
-+      {0x5A, 0x00}, {0x5B, 0x00}, {0x95, 0x00}, {0x96, 0x00},
-+      {0x97, 0x00}, {0x98, 0x00}, {0x99, 0x00}, {0x9A, 0x00},
-+      {0x9B, 0x00}, {0xA2, 0x00}, {0xA3, 0x00}, {0xA4, 0x00},
-+      {0xB7, 0x92},
-+      {0x1A, 0x3D}, {0x1B, 0x09}, {0x1E, 0xF3}, {0x20, 0x13},
-+      {0x21, 0x75}, {0x2B, 0x04}, {0x2D, 0x11}, {0x2E, 0xE0},
-+      {0x3D, 0x7A},
-+      {0x35, 0x9D}, {0x36, 0x00}, {0x3C, 0x42},
-+      { 177, 0xAC},
-+};
-+static struct reg_default common_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_common_pll_regs;
-+static struct reg_default dedicated_192k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_192k_pll_regs;
-+static struct reg_default dedicated_96k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_96k_pll_regs;
-+static struct reg_default dedicated_48k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_48k_pll_regs;
-+static struct reg_default dedicated_176k4_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_176k4_pll_regs;
-+static struct reg_default dedicated_88k2_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_88k2_pll_regs;
-+static struct reg_default dedicated_44k1_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
-+static int num_dedicated_44k1_pll_regs;
-+
-+/**
-+ * struct clk_hifiberry_drvdata - Common struct to the HiFiBerry DAC HD Clk
-+ * @hw: clk_hw for the common clk framework
-+ */
-+struct clk_hifiberry_drvdata {
-+      struct regmap *regmap;
-+      struct clk *clk;
-+      struct clk_hw hw;
-+      unsigned long rate;
-+};
-+
-+#define to_hifiberry_clk(_hw) \
-+      container_of(_hw, struct clk_hifiberry_drvdata, hw)
-+
-+static int clk_hifiberry_dachd_write_pll_regs(struct regmap *regmap,
-+                              struct reg_default *regs,
-+                              int num, int do_pll_reset)
-+{
-+      int i;
-+      int ret = 0;
-+      char pll_soft_reset[] = { 177, 0xAC, };
-+
-+      for (i = 0; i < num; i++) {
-+              ret |= regmap_write(regmap, regs[i].reg, regs[i].def);
-+              if (ret)
-+                      return ret;
-+      }
-+      if (do_pll_reset) {
-+              ret |= regmap_write(regmap, pll_soft_reset[0],
-+                                              pll_soft_reset[1]);
-+              mdelay(10);
-+      }
-+      return ret;
-+}
-+
-+static unsigned long clk_hifiberry_dachd_recalc_rate(struct clk_hw *hw,
-+      unsigned long parent_rate)
-+{
-+      return to_hifiberry_clk(hw)->rate;
-+}
-+
-+static long clk_hifiberry_dachd_round_rate(struct clk_hw *hw,
-+      unsigned long rate, unsigned long *parent_rate)
-+{
-+      return rate;
-+}
-+
-+static int clk_hifiberry_dachd_set_rate(struct clk_hw *hw,
-+      unsigned long rate, unsigned long parent_rate)
-+{
-+      int ret;
-+      struct clk_hifiberry_drvdata *drvdata = to_hifiberry_clk(hw);
-+
-+      switch (rate) {
-+      case 44100:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_44k1_pll_regs, num_dedicated_44k1_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      case 88200:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_88k2_pll_regs, num_dedicated_88k2_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      case 176400:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_176k4_pll_regs, num_dedicated_176k4_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      case 48000:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_48k_pll_regs, num_dedicated_48k_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      case 96000:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_96k_pll_regs, num_dedicated_96k_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      case 192000:
-+              ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
-+                      dedicated_192k_pll_regs, num_dedicated_192k_pll_regs,
-+                      PLL_RESET);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+      to_hifiberry_clk(hw)->rate = rate;
-+
-+      return ret;
-+}
-+
-+const struct clk_ops clk_hifiberry_dachd_rate_ops = {
-+      .recalc_rate = clk_hifiberry_dachd_recalc_rate,
-+      .round_rate = clk_hifiberry_dachd_round_rate,
-+      .set_rate = clk_hifiberry_dachd_set_rate,
-+};
-+
-+static int clk_hifiberry_get_prop_values(struct device *dev,
-+                                      char *prop_name,
-+                                      struct reg_default *regs)
-+{
-+      int ret;
-+      int i;
-+      u8 tmp[2 * HIFIBERRY_PLL_MAX_REGISTER];
-+
-+      ret = of_property_read_variable_u8_array(dev->of_node, prop_name,
-+                      tmp, 0, 2 * HIFIBERRY_PLL_MAX_REGISTER);
-+      if (ret < 0)
-+              return ret;
-+      if (ret & 1) {
-+              dev_err(dev,
-+                      "%s <%s> -> #%i odd number of bytes for reg/val pairs!",
-+                      __func__,
-+                      prop_name,
-+                      ret);
-+              return -EINVAL;
-+      }
-+      ret /= 2;
-+      for (i = 0; i < ret; i++) {
-+              regs[i].reg = (u32)tmp[2 * i];
-+              regs[i].def = (u32)tmp[2 * i + 1];
-+      }
-+      return ret;
-+}
-+
-+
-+static int clk_hifiberry_dachd_dt_parse(struct device *dev)
-+{
-+      num_common_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "common_pll_regs", common_pll_regs);
-+      num_dedicated_44k1_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "44k1_pll_regs", dedicated_44k1_pll_regs);
-+      num_dedicated_88k2_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "88k2_pll_regs", dedicated_88k2_pll_regs);
-+      num_dedicated_176k4_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "176k4_pll_regs", dedicated_176k4_pll_regs);
-+      num_dedicated_48k_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "48k_pll_regs", dedicated_48k_pll_regs);
-+      num_dedicated_96k_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "96k_pll_regs", dedicated_96k_pll_regs);
-+      num_dedicated_192k_pll_regs = clk_hifiberry_get_prop_values(dev,
-+                              "192k_pll_regs", dedicated_192k_pll_regs);
-+      return 0;
-+}
-+
-+
-+static int clk_hifiberry_dachd_remove(struct device *dev)
-+{
-+      of_clk_del_provider(dev->of_node);
-+      return 0;
-+}
-+
-+const struct regmap_config hifiberry_pll_regmap = {
-+      .reg_bits = 8,
-+      .val_bits = 8,
-+      .max_register = HIFIBERRY_PLL_MAX_REGISTER,
-+      .reg_defaults = hifiberry_pll_reg_defaults,
-+      .num_reg_defaults = ARRAY_SIZE(hifiberry_pll_reg_defaults),
-+      .cache_type = REGCACHE_RBTREE,
-+};
-+EXPORT_SYMBOL_GPL(hifiberry_pll_regmap);
-+
-+
-+static int clk_hifiberry_dachd_i2c_probe(struct i2c_client *i2c,
-+                           const struct i2c_device_id *id)
-+{
-+      struct clk_hifiberry_drvdata *hdclk;
-+      int ret = 0;
-+      struct clk_init_data init;
-+      struct device *dev = &i2c->dev;
-+      struct device_node *dev_node = dev->of_node;
-+      struct regmap_config config = hifiberry_pll_regmap;
-+
-+      hdclk = devm_kzalloc(&i2c->dev,
-+                      sizeof(struct clk_hifiberry_drvdata), GFP_KERNEL);
-+      if (!hdclk)
-+              return -ENOMEM;
-+
-+      i2c_set_clientdata(i2c, hdclk);
-+
-+      hdclk->regmap = devm_regmap_init_i2c(i2c, &config);
-+
-+      if (IS_ERR(hdclk->regmap))
-+              return PTR_ERR(hdclk->regmap);
-+
-+      /* start PLL to allow detection of DAC */
-+      ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap,
-+                              hifiberry_pll_reg_defaults,
-+                              ARRAY_SIZE(hifiberry_pll_reg_defaults),
-+                              PLL_RESET);
-+      if (ret)
-+              return ret;
-+
-+      clk_hifiberry_dachd_dt_parse(dev);
-+
-+      /* restart PLL with configs from DTB */
-+      ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap, common_pll_regs,
-+                                      num_common_pll_regs, PLL_RESET);
-+      if (ret)
-+              return ret;
-+
-+      init.name = "clk-hifiberry-dachd";
-+      init.ops = &clk_hifiberry_dachd_rate_ops;
-+      init.flags = CLK_IS_BASIC;
-+      init.parent_names = NULL;
-+      init.num_parents = 0;
-+
-+      hdclk->hw.init = &init;
-+
-+      hdclk->clk = devm_clk_register(dev, &hdclk->hw);
-+      if (IS_ERR(hdclk->clk)) {
-+              dev_err(dev, "unable to register %s\n", init.name);
-+              return PTR_ERR(hdclk->clk);
-+      }
-+
-+      ret = of_clk_add_provider(dev_node, of_clk_src_simple_get, hdclk->clk);
-+      if (ret != 0) {
-+              dev_err(dev, "Cannot of_clk_add_provider");
-+              return ret;
-+      }
-+
-+      ret = clk_set_rate(hdclk->hw.clk, DEFAULT_RATE);
-+      if (ret != 0) {
-+              dev_err(dev, "Cannot set rate : %d\n",  ret);
-+              return -EINVAL;
-+      }
-+
-+      return ret;
-+}
-+
-+static int clk_hifiberry_dachd_i2c_remove(struct i2c_client *i2c)
-+{
-+      clk_hifiberry_dachd_remove(&i2c->dev);
-+      return 0;
-+}
-+
-+static const struct i2c_device_id clk_hifiberry_dachd_i2c_id[] = {
-+      { "dachd-clk", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(i2c, clk_hifiberry_dachd_i2c_id);
-+
-+static const struct of_device_id clk_hifiberry_dachd_of_match[] = {
-+      { .compatible = "hifiberry,dachd-clk", },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, clk_hifiberry_dachd_of_match);
-+
-+static struct i2c_driver clk_hifiberry_dachd_i2c_driver = {
-+      .probe          = clk_hifiberry_dachd_i2c_probe,
-+      .remove         = clk_hifiberry_dachd_i2c_remove,
-+      .id_table       = clk_hifiberry_dachd_i2c_id,
-+      .driver         = {
-+              .name   = "dachd-clk",
-+              .of_match_table = of_match_ptr(clk_hifiberry_dachd_of_match),
-+      },
-+};
-+
-+module_i2c_driver(clk_hifiberry_dachd_i2c_driver);
-+
-+
-+MODULE_DESCRIPTION("HiFiBerry DAC+ HD clock driver");
-+MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:clk-hifiberry-dachd");
---- a/sound/soc/bcm/Kconfig
-+++ b/sound/soc/bcm/Kconfig
-@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
-         help
-          Say Y or M if you want to add support for HifiBerry DAC+.
-+config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD
-+        tristate "Support for HifiBerry DAC+ HD"
-+        depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+        select SND_SOC_PCM179X_I2C
-+        help
-+         Say Y or M if you want to add support for HifiBerry DAC+ HD.
-+
- config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
-         tristate "Support for HifiBerry DAC+ADC"
-         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
---- a/sound/soc/bcm/Makefile
-+++ b/sound/soc/bcm/Makefile
-@@ -13,6 +13,7 @@ snd-soc-googlevoicehat-codec-objs := goo
- # BCM2708 Machine Support
- snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
-+snd-soc-hifiberry-dacplushd-objs := hifiberry_dacplushd.o
- snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
- snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
- snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
-@@ -40,6 +41,7 @@ snd-soc-rpi-wm8804-soundcard-objs := rpi
- 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_HIFIBERRY_DACPLUSHD) += snd-soc-hifiberry-dacplushd.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
---- /dev/null
-+++ b/sound/soc/bcm/hifiberry_dacplushd.c
-@@ -0,0 +1,235 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * ASoC Driver for HiFiBerry DAC+ HD
-+ *
-+ * Author:    Joerg Schambacher, i2Audio GmbH for HiFiBerry
-+ *            Copyright 2020
-+ *
-+ * 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/delay.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/delay.h>
-+#include <linux/gpio.h>
-+#include <linux/gpio/consumer.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <linux/i2c.h>
-+#include <linux/clk.h>
-+
-+#include "../codecs/pcm179x.h"
-+
-+#define DEFAULT_RATE          44100
-+
-+struct brd_drv_data {
-+      struct regmap *regmap;
-+      struct clk *sclk;
-+};
-+
-+static struct brd_drv_data drvdata;
-+static struct gpio_desc *reset_gpio;
-+static const unsigned int hb_dacplushd_rates[] = {
-+      192000, 96000, 48000, 176400, 88200, 44100,
-+};
-+
-+static struct snd_pcm_hw_constraint_list hb_dacplushd_constraints = {
-+      .list = hb_dacplushd_rates,
-+      .count = ARRAY_SIZE(hb_dacplushd_rates),
-+};
-+
-+static int snd_rpi_hb_dacplushd_startup(struct snd_pcm_substream *substream)
-+{
-+      /* constraints for standard sample rates */
-+      snd_pcm_hw_constraint_list(substream->runtime, 0,
-+                              SNDRV_PCM_HW_PARAM_RATE,
-+                              &hb_dacplushd_constraints);
-+      return 0;
-+}
-+
-+static void snd_rpi_hifiberry_dacplushd_set_sclk(
-+              struct snd_soc_component *component,
-+              int sample_rate)
-+{
-+      if (!IS_ERR(drvdata.sclk))
-+              clk_set_rate(drvdata.sclk, sample_rate);
-+}
-+
-+static int snd_rpi_hifiberry_dacplushd_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+      struct snd_soc_dai_link *dai = rtd->dai_link;
-+      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+
-+      dai->name = "HiFiBerry DAC+ HD";
-+      dai->stream_name = "HiFiBerry DAC+ HD HiFi";
-+      dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+              | SND_SOC_DAIFMT_CBM_CFM;
-+
-+      /* allow only fixed 32 clock counts per channel */
-+      snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
-+
-+      return 0;
-+}
-+
-+static int snd_rpi_hifiberry_dacplushd_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;
-+
-+      struct snd_soc_component *component = rtd->codec_dai->component;
-+
-+      snd_rpi_hifiberry_dacplushd_set_sclk(component, params_rate(params));
-+      return ret;
-+}
-+
-+/* machine stream operations */
-+static struct snd_soc_ops snd_rpi_hifiberry_dacplushd_ops = {
-+      .startup = snd_rpi_hb_dacplushd_startup,
-+      .hw_params = snd_rpi_hifiberry_dacplushd_hw_params,
-+};
-+
-+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplushd_dai[] = {
-+{
-+      .name           = "HiFiBerry DAC+ HD",
-+      .stream_name    = "HiFiBerry DAC+ HD HiFi",
-+      .cpu_dai_name   = "bcm2708-i2s.0",
-+      .codec_dai_name = "pcm179x-hifi",
-+      .platform_name  = "bcm2708-i2s.0",
-+      .codec_name     = "pcm179x.1-004c",
-+      .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+                              SND_SOC_DAIFMT_CBS_CFS,
-+      .ops            = &snd_rpi_hifiberry_dacplushd_ops,
-+      .init           = snd_rpi_hifiberry_dacplushd_init,
-+},
-+};
-+
-+/* audio machine driver */
-+static struct snd_soc_card snd_rpi_hifiberry_dacplushd = {
-+      .name         = "snd_rpi_hifiberry_dacplushd",
-+      .driver_name  = "HifiberryDacplusHD",
-+      .owner        = THIS_MODULE,
-+      .dai_link     = snd_rpi_hifiberry_dacplushd_dai,
-+      .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplushd_dai),
-+};
-+
-+static int snd_rpi_hifiberry_dacplushd_probe(struct platform_device *pdev)
-+{
-+      int ret = 0;
-+      static int dac_reset_done;
-+      struct device *dev = &pdev->dev;
-+      struct device_node *dev_node = dev->of_node;
-+
-+      snd_rpi_hifiberry_dacplushd.dev = &pdev->dev;
-+
-+      /* get GPIO and release DAC from RESET */
-+      if (!dac_reset_done) {
-+              reset_gpio = gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
-+              if (IS_ERR(reset_gpio)) {
-+                      dev_err(&pdev->dev, "gpiod_get() failed\n");
-+                      return -EINVAL;
-+              }
-+              dac_reset_done = 1;
-+      }
-+      if (!IS_ERR(reset_gpio))
-+              gpiod_set_value(reset_gpio, 0);
-+      msleep(1);
-+      if (!IS_ERR(reset_gpio))
-+              gpiod_set_value(reset_gpio, 1);
-+      msleep(1);
-+      if (!IS_ERR(reset_gpio))
-+              gpiod_set_value(reset_gpio, 0);
-+
-+      if (pdev->dev.of_node) {
-+              struct device_node *i2s_node;
-+              struct snd_soc_dai_link *dai;
-+
-+              dai = &snd_rpi_hifiberry_dacplushd_dai[0];
-+              i2s_node = of_parse_phandle(pdev->dev.of_node,
-+                      "i2s-controller", 0);
-+
-+              if (i2s_node) {
-+                      dai->cpu_dai_name = NULL;
-+                      dai->cpu_of_node = i2s_node;
-+                      dai->platform_name = NULL;
-+                      dai->platform_of_node = i2s_node;
-+              } else {
-+                      return -EPROBE_DEFER;
-+              }
-+
-+      }
-+
-+      ret = devm_snd_soc_register_card(&pdev->dev,
-+                      &snd_rpi_hifiberry_dacplushd);
-+      if (ret && ret != -EPROBE_DEFER) {
-+              dev_err(&pdev->dev,
-+                      "snd_soc_register_card() failed: %d\n", ret);
-+              return ret;
-+      }
-+      if (ret == -EPROBE_DEFER)
-+              return ret;
-+
-+      dev_set_drvdata(dev, &drvdata);
-+      if (dev_node == NULL) {
-+              dev_err(&pdev->dev, "Device tree node not found\n");
-+              return -ENODEV;
-+      }
-+
-+      drvdata.sclk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(drvdata.sclk)) {
-+              drvdata.sclk = ERR_PTR(-ENOENT);
-+              return -ENODEV;
-+      }
-+
-+      clk_set_rate(drvdata.sclk, DEFAULT_RATE);
-+
-+      return ret;
-+}
-+
-+static int snd_rpi_hifiberry_dacplushd_remove(struct platform_device *pdev)
-+{
-+      if (IS_ERR(reset_gpio))
-+              return -EINVAL;
-+
-+      /* put DAC into RESET and release GPIO */
-+      gpiod_set_value(reset_gpio, 0);
-+      gpiod_put(reset_gpio);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id snd_rpi_hifiberry_dacplushd_of_match[] = {
-+      { .compatible = "hifiberry,hifiberry-dacplushd", },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplushd_of_match);
-+
-+static struct platform_driver snd_rpi_hifiberry_dacplushd_driver = {
-+      .driver = {
-+              .name   = "snd-rpi-hifiberry-dacplushd",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = snd_rpi_hifiberry_dacplushd_of_match,
-+      },
-+      .probe          = snd_rpi_hifiberry_dacplushd_probe,
-+      .remove         = snd_rpi_hifiberry_dacplushd_remove,
-+};
-+
-+module_platform_driver(snd_rpi_hifiberry_dacplushd_driver);
-+
-+MODULE_AUTHOR("Joerg Schambacher <joerg@i2audio.com>");
-+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ HD");
-+MODULE_LICENSE("GPL v2");