Devicetree
 help / color / mirror / Atom feed
* [PATCH] of: Provide dummy of_device_compatible_match() for compile-testing
From: Geert Uytterhoeven @ 2017-04-25 17:38 UTC (permalink / raw)
  To: Rob Herring, Frank Rowand
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven

Most of_device_*() functions have dummy versions for CONFIG_OF=n,
but of_device_compatible_match() hasn't.  Fix that to improve the
ability to do compile-testing.

Fixes: b9c13fe32faaa71c ("dt: Add of_device_compatible_match()")
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
 include/linux/of.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/of.h b/include/linux/of.h
index 21e6323de0f3b786..bfd1a23221735161 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -620,6 +620,12 @@ static inline int of_device_is_compatible(const struct device_node *device,
 	return 0;
 }
 
+static inline  int of_device_compatible_match(struct device_node *device,
+					      const char *const *compat)
+{
+	return 0;
+}
+
 static inline bool of_device_is_available(const struct device_node *device)
 {
 	return false;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH] clk: Provide dummy of_clk_get_from_provider() for compile-testing
From: Geert Uytterhoeven @ 2017-04-25 17:28 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Russell King, Rob Herring,
	Mark Rutland
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven

When CONFIG_ON=n, dummies are provided for of_clk_get() and
of_clk_get_by_name(), but not for of_clk_get_from_provider().

Provide a dummy for the latter, to improve the ability to do
compile-testing.

Fixes: 766e6a4ec602d0c1 ("clk: add DT clock binding support")
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
 include/linux/clk.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/clk.h b/include/linux/clk.h
index e9d36b3e49de5b1b..3ed97abb5cbb7f94 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -539,6 +539,10 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
 {
 	return ERR_PTR(-ENOENT);
 }
+static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
+{
+	return ERR_PTR(-ENOENT);
+}
 #endif
 
 #endif
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 08/13] reset: Add a reset controller driver for the Lantiq XWAY based SoCs
From: Rob Herring @ 2017-04-25 17:01 UTC (permalink / raw)
  To: Hauke Mehrtens
  Cc: Ralf Baechle, Linux-MIPS,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	LINUX-WATCHDOG,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Martin Blumenstingl, John Crispin,
	linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	hauke.mehrtens-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <a9519140-a804-9888-3223-9a1446e25c52-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>

On Tue, Apr 25, 2017 at 2:00 AM, Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org> wrote:
>
>
> On 04/20/2017 04:54 PM, Rob Herring wrote:
>> On Mon, Apr 17, 2017 at 09:29:37PM +0200, Hauke Mehrtens wrote:
>>> From: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>>
>>> The reset controllers (on xRX200 and newer SoCs have two of them) are
>>> provided by the RCU module. This was initially implemented as a simple
>>> reset controller. However, the RCU module provides more functionality
>>> (ethernet GPHYs, USB PHY, etc.), which makes it a MFD device.
>>> The old reset controller driver implementation from
>>> arch/mips/lantiq/xway/reset.c did not honor this fact.
>>>
>>> For some devices the request and the status bits are different.
>>>
>>> Signed-off-by: Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>>> ---
>>>  .../devicetree/bindings/reset/lantiq,rcu-reset.txt |  43 ++++
>>>  arch/mips/lantiq/xway/reset.c                      |  68 ------
>>>  drivers/reset/Kconfig                              |   6 +
>>>  drivers/reset/Makefile                             |   1 +
>>>  drivers/reset/reset-lantiq-rcu.c                   | 231 +++++++++++++++++++++
>>>  5 files changed, 281 insertions(+), 68 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>>  create mode 100644 drivers/reset/reset-lantiq-rcu.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt b/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>> new file mode 100644
>>> index 000000000000..7f097d16bbb7
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/reset/lantiq,rcu-reset.txt
>>> @@ -0,0 +1,43 @@
>>> +Lantiq XWAY SoC RCU reset controller binding
>>> +============================================
>>> +
>>> +This binding describes a reset-controller found on the RCU module on Lantiq
>>> +XWAY SoCs.
>>> +
>>> +
>>> +-------------------------------------------------------------------------------
>>> +Required properties (controller (parent) node):
>>> +- compatible                : Should be "lantiq,rcu-reset"
>>> +- lantiq,rcu-syscon : A phandle to the RCU syscon, the reset register
>>> +                      offset and the status register offset.
>>> +- #reset-cells              : Specifies the number of cells needed to encode the
>>> +                      reset line, should be 1.
>>> +
>>> +Optional properties:
>>> +- reset-status              : The request status bit. For some bits the request bit
>>> +                      and the status bit are different. This is depending
>>> +                      on the SoC. If the reset-status bit does not match
>>> +                      the reset-request bit, put the reset number into the
>>> +                      reset-request property and the status bit at the same
>>> +                      index into the reset-status property. If no
>>> +                      reset-request bit is given here, the driver assume
>>> +                      status and request bit are the same.
>>> +- reset-request             : The reset request bit, to map it to the reset-status
>>> +                      bit.
>>
>> These should either be implied by SoC specific compatible or be made
>> part of the reset cells. In the latter case, you still need the SoC
>> specific compatible.
>
> Currently the reset framework only supports a single reset cell to my
> knowledge, but I haven't looked into the details, I could extend it to
> make it support two.

I thought we had cases already, but maybe I'm thinking of something
else. In any case, driver limitations shouldn't define binding design.

> The SoC which needs this has two reset control register sets and the
> bits are specific for each register set. Would a specific compatible
> string for each register set ok?

Yes. You should have that.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 06/13] MIPS: lantiq: Convert the xbar driver to a platform_driver
From: Rob Herring @ 2017-04-25 16:57 UTC (permalink / raw)
  To: Hauke Mehrtens
  Cc: Ralf Baechle, Linux-MIPS,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	LINUX-WATCHDOG,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Martin Blumenstingl, John Crispin,
	linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	hauke.mehrtens-ral2JQCrhuEAvxtiuMwx3w
In-Reply-To: <8742e3b3-4dc2-bc74-f607-00d96f74512c-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>

On Tue, Apr 25, 2017 at 1:56 AM, Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org> wrote:
>
>
> On 04/20/2017 04:48 PM, Rob Herring wrote:
>> On Mon, Apr 17, 2017 at 09:29:35PM +0200, Hauke Mehrtens wrote:
>>> From: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>>
>>> This allows using the xbar driver on ARX300 based SoCs which require the
>>> same xbar setup as the xRX200 chipsets because the xbar driver
>>> initialization is not guarded by an xRX200 specific
>>> of_machine_is_compatible condition anymore. Additionally the new driver
>>> takes a syscon phandle to configure the XBAR endianness bits in RCU
>>> (before this was done in arch/mips/lantiq/xway/reset.c and also
>>> guarded by an xRX200 specific if-statement).
>>>
>>> Signed-off-by: Hauke Mehrtens <hauke-5/S+JYg5SzeELgA04lAiVw@public.gmane.org>
>>> ---
>>>  .../devicetree/bindings/mips/lantiq/xbar.txt       |  22 +++++
>>>  MAINTAINERS                                        |   1 +
>>>  arch/mips/lantiq/xway/reset.c                      |   4 -
>>>  arch/mips/lantiq/xway/sysctrl.c                    |  41 ---------
>>>  drivers/soc/Makefile                               |   1 +
>>>  drivers/soc/lantiq/Makefile                        |   1 +
>>>  drivers/soc/lantiq/xbar.c                          | 100 +++++++++++++++++++++
>>>  7 files changed, 125 insertions(+), 45 deletions(-)
>>>  create mode 100644 Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>>  create mode 100644 drivers/soc/lantiq/Makefile
>>>  create mode 100644 drivers/soc/lantiq/xbar.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/mips/lantiq/xbar.txt b/Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>> new file mode 100644
>>> index 000000000000..86e53ff3b0d5
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/mips/lantiq/xbar.txt
>>> @@ -0,0 +1,22 @@
>>> +Lantiq XWAY SoC XBAR binding
>>> +============================
>>> +
>>> +
>>> +-------------------------------------------------------------------------------
>>> +Required properties:
>>> +- compatible        : Should be "lantiq,xbar-xway"
>>
>> This compatible is already in use so it is fine, but you should also
>> have per SoC compatible strings.
>
> I will add a new SoC specific one.
> What does per SoC device tree mean? Does it mean for the same silicon,
> for the same silicon revision, for the same fusing of a silicon or for
> the same marketing name?

Depends how specific you need to some extent. For fusing, packaging,
metal fixes, speed grading, etc. probably use the same compatible.
Different design and dies from the start, then they should have
different compatibles.

> I would like to make it per silicon or per silicon revision for the IP
> cores which I know are different.

Being "the same IP" doesn't really matter. The errata can be different
and often there is no visibility into what h/w designers may have
changed. On some IP you can rely on revision/feature registers though
forgetting to rev revision registers is not uncommon. You need to have
sufficient information that you can work-around a problem in the
future without requiring a new dtb.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 01/10] clk: renesas: cpg-mssr: Document R-Car Gen2 support
From: Geert Uytterhoeven @ 2017-04-25 16:53 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
	Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1493139200-27396-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>

Document use of the Renesas Clock Pulse Generator / Module Standby and
Software Reset DT Bindings for various member of the R-Car Gen2 family
(H2, M2-W, V2H, M2-N, and E2).

Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
 Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
index f4f944d813081857..0cd894f987a38e81 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
@@ -15,6 +15,11 @@ Required Properties:
   - compatible: Must be one of:
       - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
       - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
+      - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
+      - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
+      - "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H)
+      - "renesas,r8a7793-cpg-mssr" for the r8a7793 SoC (R-Car M2-N)
+      - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
@@ -24,9 +29,10 @@ Required Properties:
   - clocks: References to external parent clocks, one entry for each entry in
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
-      - "extal" (r8a7743, r8a7745, r8a7795, r8a7796)
+      - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
+		 r8a7795, r8a7796)
       - "extalr" (r8a7795, r8a7796)
-      - "usb_extal" (r8a7743, r8a7745)
+      - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Ryan Lee @ 2017-04-25 16:51 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, alsa-devel, Kuninori Morimoto, Liam Girdwood, tiwai,
	Srinivas Kandagatla, romain.perier, bardliao, lars, Axel Lin,
	Paul.Handrigan, devicetree, Arnd Bergmann, nh6z, robh+dt, ckeepax,
	Dylan Reid, oder_chiou, Ryan Lee, KCHSU0, linux-kernel
In-Reply-To: <E1cwCZ1-0001o4-Q5@debutante>

'

On Thu, Apr 6, 2017 at 11:55 AM, Mark Brown <broonie@kernel.org> wrote:
> The patch
>
>    ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> has been applied to the asoc tree at
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
>
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.
>
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
>
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
>
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.
>
> Thanks,
> Mark

I have tried to check MAX98927 driver on linux-next tree and
'git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git' but
have failed.
So I wanted to check the current status of MAX98927 driver.
I'm sorry for top-posting.

>
> From 7c0c2000716e64151b3c0c62026c18f31537ebe9 Mon Sep 17 00:00:00 2001
> From: Ryan Lee <ryans.lee@maximintegrated.com>
> Date: Tue, 4 Apr 2017 02:23:08 +0900
> Subject: [PATCH] ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> Signed-off-by: Ryan Lee <ryans.lee@maximintegrated.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  .../devicetree/bindings/sound/max98925.txt         |  22 -
>  .../devicetree/bindings/sound/max98926.txt         |  32 -
>  .../devicetree/bindings/sound/max9892x.txt         |  41 +
>  sound/soc/codecs/Kconfig                           |   5 +
>  sound/soc/codecs/Makefile                          |   2 +
>  sound/soc/codecs/max98927.c                        | 841 +++++++++++++++++++++
>  sound/soc/codecs/max98927.h                        | 272 +++++++
>  7 files changed, 1161 insertions(+), 54 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98925.txt
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98926.txt
>  create mode 100644 Documentation/devicetree/bindings/sound/max9892x.txt
>  create mode 100644 sound/soc/codecs/max98927.c
>  create mode 100644 sound/soc/codecs/max98927.h
>
> diff --git a/Documentation/devicetree/bindings/sound/max98925.txt b/Documentation/devicetree/bindings/sound/max98925.txt
> deleted file mode 100644
> index 27be63e2aa0d..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98925.txt
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -max98925 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98925"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98925@1a {
> -       compatible = "maxim,max98925";
> -       vmon-slot-no = <0>;
> -       imon-slot-no = <2>;
> -       reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt
> deleted file mode 100644
> index 0b7f4e4d5f9a..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98926.txt
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -max98926 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98926"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -                   or in inteleave mode this will be used as
> -                   interleave slot.
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - interleave-mode : When using two MAX98926 in a system it is
> -                      possible to create ADC data that that will
> -                      overflow the frame size. Digital Audio Interleave
> -                      mode provides a means to output VMON and IMON data
> -                      from two devices on a single DOUT line when running
> -                      smaller frames sizes such as 32 BCLKS per LRCLK or
> -                      48 BCLKS per LRCLK.
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98926@1a {
> -   compatible = "maxim,max98926";
> -   vmon-slot-no = <0>;
> -   imon-slot-no = <2>;
> -   reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max9892x.txt b/Documentation/devicetree/bindings/sound/max9892x.txt
> new file mode 100644
> index 000000000000..f6171591ddc6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/max9892x.txt
> @@ -0,0 +1,41 @@
> +Maxim Integrated MAX98925/MAX98926/MAX98927 Speaker Amplifier
> +
> +This device supports I2C.
> +
> +Required properties:
> +
> +  - compatible : should be one of the following
> +    - "maxim,max98925"
> +    - "maxim,max98926"
> +    - "maxim,max98927"
> +
> +  - vmon-slot-no : slot number used to send voltage information
> +                   or in inteleave mode this will be used as
> +                   interleave slot.
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - imon-slot-no : slot number used to send current information
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - interleave-mode : When using two MAX9892X in a system it is
> +                   possible to create ADC data that that will
> +                   overflow the frame size. Digital Audio Interleave
> +                   mode provides a means to output VMON and IMON data
> +                   from two devices on a single DOUT line when running
> +                   smaller frames sizes such as 32 BCLKS per LRCLK or
> +                   48 BCLKS per LRCLK.
> +                   Range : 0 (off), 1 (on),  Default : 0
> +
> +  - reg : the I2C address of the device for I2C
> +
> +Example:
> +
> +codec: max98927@3a {
> +   compatible = "maxim,max98927";
> +   vmon-slot-no = <0>;
> +   imon-slot-no = <1>;
> +   interleave-mode = <0>;
> +   reg = <0x3a>;
> +};
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 9e1718a8cb1c..65e31ab88280 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -89,6 +89,7 @@ config SND_SOC_ALL_CODECS
>         select SND_SOC_MAX9867 if I2C
>         select SND_SOC_MAX98925 if I2C
>         select SND_SOC_MAX98926 if I2C
> +       select SND_SOC_MAX98927 if I2C
>         select SND_SOC_MAX9850 if I2C
>         select SND_SOC_MAX9860 if I2C
>         select SND_SOC_MAX9768 if I2C
> @@ -585,6 +586,10 @@ config SND_SOC_MAX98925
>  config SND_SOC_MAX98926
>         tristate
>
> +config SND_SOC_MAX98927
> +       tristate "Maxim Integrated MAX98927 Speaker Amplifier"
> +       depends on I2C
> +
>  config SND_SOC_MAX9850
>         tristate
>
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 7e1dad79610b..64656c43200c 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -84,6 +84,7 @@ snd-soc-max98371-objs := max98371.o
>  snd-soc-max9867-objs := max9867.o
>  snd-soc-max98925-objs := max98925.o
>  snd-soc-max98926-objs := max98926.o
> +snd-soc-max98927-objs := max98927.o
>  snd-soc-max9850-objs := max9850.o
>  snd-soc-max9860-objs := max9860.o
>  snd-soc-mc13783-objs := mc13783.o
> @@ -312,6 +313,7 @@ obj-$(CONFIG_SND_SOC_MAX98357A)     += snd-soc-max98357a.o
>  obj-$(CONFIG_SND_SOC_MAX9867)  += snd-soc-max9867.o
>  obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
>  obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
> +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
>  obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
>  obj-$(CONFIG_SND_SOC_MAX9860)  += snd-soc-max9860.o
>  obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
> diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c
> new file mode 100644
> index 000000000000..b5ee29499e16
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.c
> @@ -0,0 +1,841 @@
> +/*
> + * max98927.c  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright (C) 2016 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee@maximintegrated.com>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <sound/tlv.h>
> +#include "max98927.h"
> +
> +static struct reg_default max98927_reg[] = {
> +       {MAX98927_R0001_INT_RAW1,  0x00},
> +       {MAX98927_R0002_INT_RAW2,  0x00},
> +       {MAX98927_R0003_INT_RAW3,  0x00},
> +       {MAX98927_R0004_INT_STATE1,  0x00},
> +       {MAX98927_R0005_INT_STATE2,  0x00},
> +       {MAX98927_R0006_INT_STATE3,  0x00},
> +       {MAX98927_R0007_INT_FLAG1,  0x00},
> +       {MAX98927_R0008_INT_FLAG2,  0x00},
> +       {MAX98927_R0009_INT_FLAG3,  0x00},
> +       {MAX98927_R000A_INT_EN1,  0x00},
> +       {MAX98927_R000B_INT_EN2,  0x00},
> +       {MAX98927_R000C_INT_EN3,  0x00},
> +       {MAX98927_R000D_INT_FLAG_CLR1,  0x00},
> +       {MAX98927_R000E_INT_FLAG_CLR2,  0x00},
> +       {MAX98927_R000F_INT_FLAG_CLR3,  0x00},
> +       {MAX98927_R0010_IRQ_CTRL,  0x00},
> +       {MAX98927_R0011_CLK_MON,  0x00},
> +       {MAX98927_R0012_WDOG_CTRL,  0x00},
> +       {MAX98927_R0013_WDOG_RST,  0x00},
> +       {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH,  0x00},
> +       {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH,  0x00},
> +       {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS,  0x00},
> +       {MAX98927_R0017_PIN_CFG,  0x55},
> +       {MAX98927_R0018_PCM_RX_EN_A,  0x00},
> +       {MAX98927_R0019_PCM_RX_EN_B,  0x00},
> +       {MAX98927_R001A_PCM_TX_EN_A,  0x00},
> +       {MAX98927_R001B_PCM_TX_EN_B,  0x00},
> +       {MAX98927_R001C_PCM_TX_HIZ_CTRL_A,  0x00},
> +       {MAX98927_R001D_PCM_TX_HIZ_CTRL_B,  0x00},
> +       {MAX98927_R001E_PCM_TX_CH_SRC_A,  0x00},
> +       {MAX98927_R001F_PCM_TX_CH_SRC_B,  0x00},
> +       {MAX98927_R0020_PCM_MODE_CFG,  0x40},
> +       {MAX98927_R0021_PCM_MASTER_MODE,  0x00},
> +       {MAX98927_R0022_PCM_CLK_SETUP,  0x22},
> +       {MAX98927_R0023_PCM_SR_SETUP1,  0x00},
> +       {MAX98927_R0024_PCM_SR_SETUP2,  0x00},
> +       {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,  0x00},
> +       {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,  0x00},
> +       {MAX98927_R0027_ICC_RX_EN_A,  0x00},
> +       {MAX98927_R0028_ICC_RX_EN_B,  0x00},
> +       {MAX98927_R002B_ICC_TX_EN_A,  0x00},
> +       {MAX98927_R002C_ICC_TX_EN_B,  0x00},
> +       {MAX98927_R002E_ICC_HIZ_MANUAL_MODE,  0x00},
> +       {MAX98927_R002F_ICC_TX_HIZ_EN_A,  0x00},
> +       {MAX98927_R0030_ICC_TX_HIZ_EN_B,  0x00},
> +       {MAX98927_R0031_ICC_LNK_EN,  0x00},
> +       {MAX98927_R0032_PDM_TX_EN,  0x00},
> +       {MAX98927_R0033_PDM_TX_HIZ_CTRL,  0x00},
> +       {MAX98927_R0034_PDM_TX_CTRL,  0x00},
> +       {MAX98927_R0035_PDM_RX_CTRL,  0x00},
> +       {MAX98927_R0036_AMP_VOL_CTRL,  0x00},
> +       {MAX98927_R0037_AMP_DSP_CFG,  0x02},
> +       {MAX98927_R0038_TONE_GEN_DC_CFG,  0x00},
> +       {MAX98927_R0039_DRE_CTRL,  0x01},
> +       {MAX98927_R003A_AMP_EN,  0x00},
> +       {MAX98927_R003B_SPK_SRC_SEL,  0x00},
> +       {MAX98927_R003C_SPK_GAIN,  0x00},
> +       {MAX98927_R003D_SSM_CFG,  0x01},
> +       {MAX98927_R003E_MEAS_EN,  0x00},
> +       {MAX98927_R003F_MEAS_DSP_CFG,  0x04},
> +       {MAX98927_R0040_BOOST_CTRL0,  0x00},
> +       {MAX98927_R0041_BOOST_CTRL3,  0x00},
> +       {MAX98927_R0042_BOOST_CTRL1,  0x00},
> +       {MAX98927_R0043_MEAS_ADC_CFG,  0x00},
> +       {MAX98927_R0044_MEAS_ADC_BASE_MSB,  0x00},
> +       {MAX98927_R0045_MEAS_ADC_BASE_LSB,  0x00},
> +       {MAX98927_R0046_ADC_CH0_DIVIDE,  0x00},
> +       {MAX98927_R0047_ADC_CH1_DIVIDE,  0x00},
> +       {MAX98927_R0048_ADC_CH2_DIVIDE,  0x00},
> +       {MAX98927_R0049_ADC_CH0_FILT_CFG,  0x00},
> +       {MAX98927_R004A_ADC_CH1_FILT_CFG,  0x00},
> +       {MAX98927_R004B_ADC_CH2_FILT_CFG,  0x00},
> +       {MAX98927_R004C_MEAS_ADC_CH0_READ,  0x00},
> +       {MAX98927_R004D_MEAS_ADC_CH1_READ,  0x00},
> +       {MAX98927_R004E_MEAS_ADC_CH2_READ,  0x00},
> +       {MAX98927_R0051_BROWNOUT_STATUS,  0x00},
> +       {MAX98927_R0052_BROWNOUT_EN,  0x00},
> +       {MAX98927_R0053_BROWNOUT_INFINITE_HOLD,  0x00},
> +       {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR,  0x00},
> +       {MAX98927_R0055_BROWNOUT_LVL_HOLD,  0x00},
> +       {MAX98927_R005A_BROWNOUT_LVL1_THRESH,  0x00},
> +       {MAX98927_R005B_BROWNOUT_LVL2_THRESH,  0x00},
> +       {MAX98927_R005C_BROWNOUT_LVL3_THRESH,  0x00},
> +       {MAX98927_R005D_BROWNOUT_LVL4_THRESH,  0x00},
> +       {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS,  0x00},
> +       {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL,  0x00},
> +       {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL,  0x00},
> +       {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE,  0x00},
> +       {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT,  0x00},
> +       {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT,  0x00},
> +       {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT,  0x00},
> +       {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1,  0x00},
> +       {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2,  0x00},
> +       {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT,  0x00},
> +       {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,  0x00},
> +       {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY,  0x00},
> +       {MAX98927_R0084_ENV_TRACK_REL_RATE,  0x00},
> +       {MAX98927_R0085_ENV_TRACK_HOLD_RATE,  0x00},
> +       {MAX98927_R0086_ENV_TRACK_CTRL,  0x00},
> +       {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,  0x00},
> +       {MAX98927_R00FF_GLOBAL_SHDN,  0x00},
> +       {MAX98927_R0100_SOFT_RESET,  0x00},
> +       {MAX98927_R01FF_REV_ID,  0x40},
> +};
> +
> +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
> +{
> +       struct snd_soc_codec *codec = codec_dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int mode = 0;
> +       unsigned int format = 0;
> +       unsigned int invert = 0;
> +
> +       dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
> +
> +       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +       case SND_SOC_DAIFMT_CBS_CFS:
> +               mode = MAX98927_PCM_MASTER_MODE_SLAVE;
> +               break;
> +       case SND_SOC_DAIFMT_CBM_CFM:
> +               max98927->master = true;
> +               mode = MAX98927_PCM_MASTER_MODE_MASTER;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI clock mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0021_PCM_MASTER_MODE,
> +               MAX98927_PCM_MASTER_MODE_MASK,
> +               mode);
> +
> +       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +       case SND_SOC_DAIFMT_NB_NF:
> +               break;
> +       case SND_SOC_DAIFMT_IB_NF:
> +               invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI invert mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE,
> +               invert);
> +
> +       /* interface format */
> +       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +       case SND_SOC_DAIFMT_I2S:
> +               max98927->iface |= SND_SOC_DAIFMT_I2S;
> +               format = MAX98927_PCM_FORMAT_I2S;
> +               break;
> +       case SND_SOC_DAIFMT_LEFT_J:
> +               max98927->iface |= SND_SOC_DAIFMT_LEFT_J;
> +               format = MAX98927_PCM_FORMAT_LJ;
> +               break;
> +       case SND_SOC_DAIFMT_PDM:
> +               max98927->iface |= SND_SOC_DAIFMT_PDM;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       /* pcm channel configuration */
> +       if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0020_PCM_MODE_CFG,
> +                       MAX98927_PCM_MODE_CFG_FORMAT_MASK,
> +                       format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 0);
> +
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);
> +
> +       /* pdm channel configuration */
> +       if (max98927->iface & SND_SOC_DAIFMT_PDM) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 1);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 3);
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 0);
> +       return 0;
> +}
> +
> +/* codec MCLK rate in master mode */
> +static const int rate_table[] = {
> +       5644800, 6000000, 6144000, 6500000,
> +       9600000, 11289600, 12000000, 12288000,
> +       13000000, 19200000,
> +};
> +
> +static int max98927_set_clock(struct max98927_priv *max98927,
> +       struct snd_pcm_hw_params *params)
> +{
> +       struct snd_soc_codec *codec = max98927->codec;
> +       /* BCLK/LRCLK ratio calculation */
> +       int blr_clk_ratio = params_channels(params) * max98927->ch_size;
> +       int value;
> +
> +       if (max98927->master) {
> +               int i;
> +               /* match rate to closest value */
> +               for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
> +                       if (rate_table[i] >= max98927->sysclk)
> +                               break;
> +               }
> +               if (i == ARRAY_SIZE(rate_table)) {
> +                       dev_err(codec->dev, "failed to find proper clock rate.\n");
> +                       return -EINVAL;
> +               }
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0021_PCM_MASTER_MODE,
> +                       MAX98927_PCM_MASTER_MODE_MCLK_MASK,
> +                       i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
> +       }
> +
> +       switch (blr_clk_ratio) {
> +       case 32:
> +               value = 2;
> +               break;
> +       case 48:
> +               value = 3;
> +               break;
> +       case 64:
> +               value = 4;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0022_PCM_CLK_SETUP,
> +               MAX98927_PCM_CLK_SETUP_BSEL_MASK,
> +               value);
> +       return 0;
> +}
> +
> +static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
> +       struct snd_pcm_hw_params *params,
> +       struct snd_soc_dai *dai)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int sampling_rate = 0;
> +       unsigned int chan_sz = 0;
> +
> +       /* pcm mode configuration */
> +       switch (snd_pcm_format_width(params_format(params))) {
> +       case 16:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
> +               break;
> +       case 24:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
> +               break;
> +       case 32:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
> +               break;
> +       default:
> +               dev_err(codec->dev, "format unsupported %d",
> +                       params_format(params));
> +               goto err;
> +       }
> +
> +       max98927->ch_size = snd_pcm_format_width(params_format(params));
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
> +
> +       dev_dbg(codec->dev, "format supported %d",
> +               params_format(params));
> +
> +       /* sampling rate configuration */
> +       switch (params_rate(params)) {
> +       case 8000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_8000;
> +               break;
> +       case 11025:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_11025;
> +               break;
> +       case 12000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_12000;
> +               break;
> +       case 16000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_16000;
> +               break;
> +       case 22050:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_22050;
> +               break;
> +       case 24000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_24000;
> +               break;
> +       case 32000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_32000;
> +               break;
> +       case 44100:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_44100;
> +               break;
> +       case 48000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_48000;
> +               break;
> +       default:
> +               dev_err(codec->dev, "rate %d not supported\n",
> +                       params_rate(params));
> +               goto err;
> +       }
> +       /* set DAI_SR to correct LRCLK frequency */
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0023_PCM_SR_SETUP1,
> +               MAX98927_PCM_SR_SET1_SR_MASK,
> +               sampling_rate);
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0024_PCM_SR_SETUP2,
> +               MAX98927_PCM_SR_SET2_SR_MASK,
> +               sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT);
> +
> +       /* set sampling rate of IV */
> +       if (max98927->interleave_mode &&
> +           sampling_rate > MAX98927_PCM_SR_SET1_SR_16000)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate - 3);
> +       else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate);
> +       return max98927_set_clock(max98927, params);
> +err:
> +       return -EINVAL;
> +}
> +
> +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000
> +
> +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
> +       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
> +
> +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai,
> +       int clk_id, unsigned int freq, int dir)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->sysclk = freq;
> +       return 0;
> +}
> +
> +static const struct snd_soc_dai_ops max98927_dai_ops = {
> +       .set_sysclk = max98927_dai_set_sysclk,
> +       .set_fmt = max98927_dai_set_fmt,
> +       .hw_params = max98927_dai_hw_params,
> +};
> +
> +static int max98927_dac_event(struct snd_soc_dapm_widget *w,
> +       struct snd_kcontrol *kcontrol, int event)
> +{
> +       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       switch (event) {
> +       case SND_SOC_DAPM_POST_PMU:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 1);
> +               /* enable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 1);
> +               break;
> +       case SND_SOC_DAPM_POST_PMD:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 0);
> +               /* disable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, 0);
> +               break;
> +       default:
> +               return 0;
> +       }
> +       return 0;
> +}
> +
> +static const char * const max98927_switch_text[] = {
> +       "Left", "Right", "LeftRight"};
> +
> +static const struct soc_enum dai_sel_enum =
> +       SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
> +               3, max98927_switch_text);
> +
> +static const struct snd_kcontrol_new max98927_dai_controls =
> +       SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
> +
> +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = {
> +       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
> +       SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN,
> +               0, 0, max98927_dac_event,
> +               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
> +       SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
> +               &max98927_dai_controls),
> +       SND_SOC_DAPM_OUTPUT("BE_OUT"),
> +};
> +
> +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0);
> +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0);
> +
> +static bool max98927_readable_register(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B:
> +       case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B:
> +       case MAX98927_R002E_ICC_HIZ_MANUAL_MODE
> +               ... MAX98927_R004E_MEAS_ADC_CH2_READ:
> +       case MAX98927_R0051_BROWNOUT_STATUS
> +               ... MAX98927_R0055_BROWNOUT_LVL_HOLD:
> +       case MAX98927_R005A_BROWNOUT_LVL1_THRESH
> +               ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE:
> +       case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT
> +               ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ:
> +       case MAX98927_R00FF_GLOBAL_SHDN:
> +       case MAX98927_R0100_SOFT_RESET:
> +       case MAX98927_R01FF_REV_ID:
> +               return true;
> +       default:
> +               return false;
> +       }
> +};
> +
> +static bool max98927_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static const char * const max98927_boost_voltage_text[] = {
> +       "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
> +       "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
> +       "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
> +       "9.5V", "9.625V", "9.75V", "9.875V", "10V"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_boost_voltage,
> +               MAX98927_R0040_BOOST_CTRL0, 0,
> +               max98927_boost_voltage_text);
> +
> +static const char * const max98927_current_limit_text[] = {
> +       "1.00A", "1.10A", "1.20A", "1.30A", "1.40A", "1.50A", "1.60A", "1.70A",
> +       "1.80A", "1.90A", "2.00A", "2.10A", "2.20A", "2.30A", "2.40A", "2.50A",
> +       "2.60A", "2.70A", "2.80A", "2.90A", "3.00A", "3.10A", "3.20A", "3.30A",
> +       "3.40A", "3.50A", "3.60A", "3.70A", "3.80A", "3.90A", "4.00A", "4.10A"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_current_limit,
> +               MAX98927_R0042_BOOST_CTRL1, 1,
> +               max98927_current_limit_text);
> +
> +static const struct snd_kcontrol_new max98927_snd_controls[] = {
> +       SOC_SINGLE_TLV("Speaker Volume", MAX98927_R003C_SPK_GAIN,
> +               0, 6, 0,
> +               max98927_spk_tlv),
> +       SOC_SINGLE_TLV("Digital Volume", MAX98927_R0036_AMP_VOL_CTRL,
> +               0, (1<<MAX98927_AMP_VOL_WIDTH)-1, 0,
> +               max98927_digital_tlv),
> +       SOC_SINGLE("Amp DSP Switch", MAX98927_R0052_BROWNOUT_EN,
> +               MAX98927_BROWNOUT_DSP_SHIFT, 1, 0),
> +       SOC_SINGLE("Ramp Switch", MAX98927_R0037_AMP_DSP_CFG,
> +               MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0),
> +       SOC_SINGLE("DRE Switch", MAX98927_R0039_DRE_CTRL,
> +               MAX98927_DRE_EN_SHIFT, 1, 0),
> +       SOC_SINGLE("Volume Location Switch", MAX98927_R0036_AMP_VOL_CTRL,
> +               MAX98927_AMP_VOL_SEL_SHIFT, 1, 0),
> +       SOC_ENUM("Boost Output Voltage", max98927_boost_voltage),
> +       SOC_ENUM("Current Limit", max98927_current_limit),
> +};
> +
> +static const struct snd_soc_dapm_route max98927_audio_map[] = {
> +       {"Amp Enable", NULL, "DAI_OUT"},
> +       {"DAI Sel Mux", "Left", "Amp Enable"},
> +       {"DAI Sel Mux", "Right", "Amp Enable"},
> +       {"DAI Sel Mux", "LeftRight", "Amp Enable"},
> +       {"BE_OUT", NULL, "DAI Sel Mux"},
> +};
> +
> +static struct snd_soc_dai_driver max98927_dai[] = {
> +       {
> +               .name = "max98927-aif1",
> +               .playback = {
> +                       .stream_name = "HiFi Playback",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .capture = {
> +                       .stream_name = "HiFi Capture",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .ops = &max98927_dai_ops,
> +       }
> +};
> +
> +static int max98927_probe(struct snd_soc_codec *codec)
> +{
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->codec = codec;
> +       codec->control_data = max98927->regmap;
> +       codec->cache_bypass = 1;
> +
> +       /* Software Reset */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0100_SOFT_RESET, MAX98927_SOFT_RESET);
> +
> +       /* IV default slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               0x80);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,
> +               0x1);
> +       /* Set inital volume (+13dB) */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0036_AMP_VOL_CTRL,
> +               0x38);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003C_SPK_GAIN,
> +               0x05);
> +       /* Enable DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0037_AMP_DSP_CFG,
> +               0x03);
> +       /* Enable IMON VMON DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003F_MEAS_DSP_CFG,
> +               0xF7);
> +       /* Boost Output Voltage & Current limit */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0040_BOOST_CTRL0,
> +               0x1C);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0042_BOOST_CTRL1,
> +               0x3E);
> +       /* Measurement ADC config */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0043_MEAS_ADC_CFG,
> +               0x04);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0044_MEAS_ADC_BASE_MSB,
> +               0x00);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0045_MEAS_ADC_BASE_LSB,
> +               0x24);
> +       /* Brownout Level */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,
> +               0x06);
> +       /* Envelope Tracking configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,
> +               0x08);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0086_ENV_TRACK_CTRL,
> +               0x01);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,
> +               0x10);
> +
> +       /* voltage, current slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001E_PCM_TX_CH_SRC_A,
> +               (max98927->i_l_slot<<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT|
> +               max98927->v_l_slot)&0xFF);
> +
> +       if (max98927->v_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->v_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->v_l_slot,
> +                       1 << max98927->v_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->v_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->v_l_slot - 8),
> +                       1 << (max98927->v_l_slot - 8));
> +       }
> +
> +       if (max98927->i_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->i_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->i_l_slot,
> +                       1 << max98927->i_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->i_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->i_l_slot - 8),
> +                       1 << (max98927->i_l_slot - 8));
> +       }
> +
> +       /* Set interleave mode */
> +       if (max98927->interleave_mode)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001F_PCM_TX_CH_SRC_B,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK);
> +       return 0;
> +}
> +
> +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = {
> +       .probe = max98927_probe,
> +       .component_driver = {
> +               .controls = max98927_snd_controls,
> +               .num_controls = ARRAY_SIZE(max98927_snd_controls),
> +               .dapm_widgets = max98927_dapm_widgets,
> +               .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets),
> +               .dapm_routes = max98927_audio_map,
> +               .num_dapm_routes = ARRAY_SIZE(max98927_audio_map),
> +       },
> +};
> +
> +static const struct regmap_config max98927_regmap = {
> +       .reg_bits         = 16,
> +       .val_bits         = 8,
> +       .max_register     = MAX98927_R01FF_REV_ID,
> +       .reg_defaults     = max98927_reg,
> +       .num_reg_defaults = ARRAY_SIZE(max98927_reg),
> +       .readable_reg     = max98927_readable_register,
> +       .volatile_reg     = max98927_volatile_reg,
> +       .cache_type       = REGCACHE_RBTREE,
> +};
> +
> +static void max98927_slot_config(struct i2c_client *i2c,
> +       struct max98927_priv *max98927)
> +{
> +       int value;
> +
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "vmon-slot-no", &value))
> +               max98927->v_l_slot = value & 0xF;
> +       else
> +               max98927->v_l_slot = 0;
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "imon-slot-no", &value))
> +               max98927->i_l_slot = value & 0xF;
> +       else
> +               max98927->i_l_slot = 1;
> +}
> +
> +static int max98927_i2c_probe(struct i2c_client *i2c,
> +       const struct i2c_device_id *id)
> +{
> +
> +       int ret = 0, value;
> +       int reg = 0;
> +       struct max98927_priv *max98927 = NULL;
> +
> +       max98927 = devm_kzalloc(&i2c->dev,
> +               sizeof(*max98927), GFP_KERNEL);
> +
> +       if (!max98927) {
> +               ret = -ENOMEM;
> +               return ret;
> +       }
> +       i2c_set_clientdata(i2c, max98927);
> +
> +       /* update interleave mode info */
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "interleave_mode", &value)) {
> +               if (value > 0)
> +                       max98927->interleave_mode = 1;
> +               else
> +                       max98927->interleave_mode = 0;
> +       } else
> +               max98927->interleave_mode = 0;
> +
> +       /* regmap initialization */
> +       max98927->regmap
> +               = devm_regmap_init_i2c(i2c, &max98927_regmap);
> +       if (IS_ERR(max98927->regmap)) {
> +               ret = PTR_ERR(max98927->regmap);
> +               dev_err(&i2c->dev,
> +                       "Failed to allocate regmap: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* Check Revision ID */
> +       ret = regmap_read(max98927->regmap,
> +               MAX98927_R01FF_REV_ID, &reg);
> +       if (ret < 0) {
> +               dev_err(&i2c->dev,
> +                       "Failed to read: 0x%02X\n", MAX98927_R01FF_REV_ID);
> +               return ret;
> +       }
> +       dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n", reg);
> +
> +       /* voltage/current slot configuration */
> +       max98927_slot_config(i2c, max98927);
> +
> +       /* codec registeration */
> +       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927,
> +               max98927_dai, ARRAY_SIZE(max98927_dai));
> +       if (ret < 0)
> +               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static int max98927_i2c_remove(struct i2c_client *client)
> +{
> +       snd_soc_unregister_codec(&client->dev);
> +       return 0;
> +}
> +
> +static const struct i2c_device_id max98927_i2c_id[] = {
> +       { "max98927", 0},
> +       { },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id max98927_of_match[] = {
> +       { .compatible = "maxim,max98927", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, max98927_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id max98927_acpi_match[] = {
> +       { "MX98927", 0 },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(acpi, max98927_acpi_match);
> +#endif
> +
> +static struct i2c_driver max98927_i2c_driver = {
> +       .driver = {
> +               .name = "max98927",
> +               .of_match_table = of_match_ptr(max98927_of_match),
> +               .acpi_match_table = ACPI_PTR(max98927_acpi_match),
> +               .pm = NULL,
> +       },
> +       .probe  = max98927_i2c_probe,
> +       .remove = max98927_i2c_remove,
> +       .id_table = max98927_i2c_id,
> +};
> +
> +module_i2c_driver(max98927_i2c_driver)
> +
> +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver");
> +MODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h
> new file mode 100644
> index 000000000000..ece6a608cbe1
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.h
> @@ -0,0 +1,272 @@
> +/*
> + * max98927.h  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright 2013-15 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee@maximintegrated.com>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + */
> +#ifndef _MAX98927_H
> +#define _MAX98927_H
> +
> +/* Register Values */
> +#define MAX98927_R0001_INT_RAW1 0x0001
> +#define MAX98927_R0002_INT_RAW2 0x0002
> +#define MAX98927_R0003_INT_RAW3 0x0003
> +#define MAX98927_R0004_INT_STATE1 0x0004
> +#define MAX98927_R0005_INT_STATE2 0x0005
> +#define MAX98927_R0006_INT_STATE3 0x0006
> +#define MAX98927_R0007_INT_FLAG1 0x0007
> +#define MAX98927_R0008_INT_FLAG2 0x0008
> +#define MAX98927_R0009_INT_FLAG3 0x0009
> +#define MAX98927_R000A_INT_EN1 0x000A
> +#define MAX98927_R000B_INT_EN2 0x000B
> +#define MAX98927_R000C_INT_EN3 0x000C
> +#define MAX98927_R000D_INT_FLAG_CLR1   0x000D
> +#define MAX98927_R000E_INT_FLAG_CLR2   0x000E
> +#define MAX98927_R000F_INT_FLAG_CLR3   0x000F
> +#define MAX98927_R0010_IRQ_CTRL 0x0010
> +#define MAX98927_R0011_CLK_MON 0x0011
> +#define MAX98927_R0012_WDOG_CTRL 0x0012
> +#define MAX98927_R0013_WDOG_RST 0x0013
> +#define MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH 0x0014
> +#define MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH 0x0015
> +#define MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS 0x0016
> +#define MAX98927_R0017_PIN_CFG 0x0017
> +#define MAX98927_R0018_PCM_RX_EN_A 0x0018
> +#define MAX98927_R0019_PCM_RX_EN_B 0x0019
> +#define MAX98927_R001A_PCM_TX_EN_A 0x001A
> +#define MAX98927_R001B_PCM_TX_EN_B 0x001B
> +#define MAX98927_R001C_PCM_TX_HIZ_CTRL_A 0x001C
> +#define MAX98927_R001D_PCM_TX_HIZ_CTRL_B 0x001D
> +#define MAX98927_R001E_PCM_TX_CH_SRC_A 0x001E
> +#define MAX98927_R001F_PCM_TX_CH_SRC_B 0x001F
> +#define MAX98927_R0020_PCM_MODE_CFG 0x0020
> +#define MAX98927_R0021_PCM_MASTER_MODE 0x0021
> +#define MAX98927_R0022_PCM_CLK_SETUP 0x0022
> +#define MAX98927_R0023_PCM_SR_SETUP1 0x0023
> +#define MAX98927_R0024_PCM_SR_SETUP2   0x0024
> +#define MAX98927_R0025_PCM_TO_SPK_MONOMIX_A 0x0025
> +#define MAX98927_R0026_PCM_TO_SPK_MONOMIX_B 0x0026
> +#define MAX98927_R0027_ICC_RX_EN_A 0x0027
> +#define MAX98927_R0028_ICC_RX_EN_B 0x0028
> +#define MAX98927_R002B_ICC_TX_EN_A 0x002B
> +#define MAX98927_R002C_ICC_TX_EN_B 0x002C
> +#define MAX98927_R002E_ICC_HIZ_MANUAL_MODE 0x002E
> +#define MAX98927_R002F_ICC_TX_HIZ_EN_A 0x002F
> +#define MAX98927_R0030_ICC_TX_HIZ_EN_B 0x0030
> +#define MAX98927_R0031_ICC_LNK_EN 0x0031
> +#define MAX98927_R0032_PDM_TX_EN 0x0032
> +#define MAX98927_R0033_PDM_TX_HIZ_CTRL 0x0033
> +#define MAX98927_R0034_PDM_TX_CTRL 0x0034
> +#define MAX98927_R0035_PDM_RX_CTRL 0x0035
> +#define MAX98927_R0036_AMP_VOL_CTRL 0x0036
> +#define MAX98927_R0037_AMP_DSP_CFG 0x0037
> +#define MAX98927_R0038_TONE_GEN_DC_CFG 0x0038
> +#define MAX98927_R0039_DRE_CTRL 0x0039
> +#define MAX98927_R003A_AMP_EN 0x003A
> +#define MAX98927_R003B_SPK_SRC_SEL 0x003B
> +#define MAX98927_R003C_SPK_GAIN 0x003C
> +#define MAX98927_R003D_SSM_CFG 0x003D
> +#define MAX98927_R003E_MEAS_EN 0x003E
> +#define MAX98927_R003F_MEAS_DSP_CFG 0x003F
> +#define MAX98927_R0040_BOOST_CTRL0 0x0040
> +#define MAX98927_R0041_BOOST_CTRL3 0x0041
> +#define MAX98927_R0042_BOOST_CTRL1 0x0042
> +#define MAX98927_R0043_MEAS_ADC_CFG 0x0043
> +#define MAX98927_R0044_MEAS_ADC_BASE_MSB 0x0044
> +#define MAX98927_R0045_MEAS_ADC_BASE_LSB 0x0045
> +#define MAX98927_R0046_ADC_CH0_DIVIDE 0x0046
> +#define MAX98927_R0047_ADC_CH1_DIVIDE 0x0047
> +#define MAX98927_R0048_ADC_CH2_DIVIDE 0x0048
> +#define MAX98927_R0049_ADC_CH0_FILT_CFG 0x0049
> +#define MAX98927_R004A_ADC_CH1_FILT_CFG 0x004A
> +#define MAX98927_R004B_ADC_CH2_FILT_CFG 0x004B
> +#define MAX98927_R004C_MEAS_ADC_CH0_READ 0x004C
> +#define MAX98927_R004D_MEAS_ADC_CH1_READ 0x004D
> +#define MAX98927_R004E_MEAS_ADC_CH2_READ 0x004E
> +#define MAX98927_R0051_BROWNOUT_STATUS 0x0051
> +#define MAX98927_R0052_BROWNOUT_EN 0x0052
> +#define MAX98927_R0053_BROWNOUT_INFINITE_HOLD 0x0053
> +#define MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR 0x0054
> +#define MAX98927_R0055_BROWNOUT_LVL_HOLD 0x0055
> +#define MAX98927_R005A_BROWNOUT_LVL1_THRESH 0x005A
> +#define MAX98927_R005B_BROWNOUT_LVL2_THRESH 0x005B
> +#define MAX98927_R005C_BROWNOUT_LVL3_THRESH 0x005C
> +#define MAX98927_R005D_BROWNOUT_LVL4_THRESH 0x005D
> +#define MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS 0x005E
> +#define MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL 0x005F
> +#define MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL 0x0060
> +#define MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE 0x0061
> +#define MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 0x0072
> +#define MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1 0x0073
> +#define MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2 0x0074
> +#define MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3 0x0075
> +#define MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT 0x0076
> +#define MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1 0x0077
> +#define MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2 0x0078
> +#define MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3 0x0079
> +#define MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT 0x007A
> +#define MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1 0x007B
> +#define MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2 0x007C
> +#define MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3 0x007D
> +#define MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT 0x007E
> +#define MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1 0x007F
> +#define MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2 0x0080
> +#define MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3 0x0081
> +#define MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM 0x0082
> +#define MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY 0x0083
> +#define MAX98927_R0084_ENV_TRACK_REL_RATE 0x0084
> +#define MAX98927_R0085_ENV_TRACK_HOLD_RATE 0x0085
> +#define MAX98927_R0086_ENV_TRACK_CTRL 0x0086
> +#define MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ 0x0087
> +#define MAX98927_R00FF_GLOBAL_SHDN 0x00FF
> +#define MAX98927_R0100_SOFT_RESET 0x0100
> +#define MAX98927_R01FF_REV_ID 0x01FF
> +
> +/* MAX98927_R0018_PCM_RX_EN_A */
> +#define MAX98927_PCM_RX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_RX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_RX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_RX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_RX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_RX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_RX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_RX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001A_PCM_TX_EN_A */
> +#define MAX98927_PCM_TX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_TX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_TX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_TX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_TX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_TX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_TX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_TX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001E_PCM_TX_CH_SRC_A */
> +#define MAX98927_PCM_TX_CH_SRC_A_V_SHIFT (0)
> +#define MAX98927_PCM_TX_CH_SRC_A_I_SHIFT (4)
> +
> +/* MAX98927_R001F_PCM_TX_CH_SRC_B */
> +#define MAX98927_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 5)
> +
> +/* MAX98927_R0020_PCM_MODE_CFG */
> +#define MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3)
> +#define MAX98927_PCM_FORMAT_I2S (0x0 << 0)
> +#define MAX98927_PCM_FORMAT_LJ (0x1 << 0)
> +
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
> +
> +/* MAX98927_R0021_PCM_MASTER_MODE */
> +#define MAX98927_PCM_MASTER_MODE_MASK (0x3 << 0)
> +#define MAX98927_PCM_MASTER_MODE_SLAVE (0x0 << 0)
> +#define MAX98927_PCM_MASTER_MODE_MASTER (0x3 << 0)
> +
> +#define MAX98927_PCM_MASTER_MODE_MCLK_MASK (0xF << 2)
> +#define MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2)
> +
> +/* MAX98927_R0022_PCM_CLK_SETUP */
> +#define MAX98927_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
> +
> +/* MAX98927_R0023_PCM_SR_SETUP1 */
> +#define MAX98927_PCM_SR_SET1_SR_MASK (0xF << 0)
> +
> +#define MAX98927_PCM_SR_SET1_SR_8000 (0x0 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_11025 (0x1 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_12000 (0x2 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_16000 (0x3 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_22050 (0x4 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_24000 (0x5 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_32000 (0x6 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_44100 (0x7 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_48000 (0x8 << 0)
> +
> +/* MAX98927_R0024_PCM_SR_SETUP2 */
> +#define MAX98927_PCM_SR_SET2_SR_MASK (0xF << 4)
> +#define MAX98927_PCM_SR_SET2_SR_SHIFT (4)
> +#define MAX98927_PCM_SR_SET2_IVADC_SR_MASK (0xf << 0)
> +
> +/* MAX98927_R0025_PCM_TO_SPK_MONOMIX_A */
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
> +
> +/* MAX98927_R0035_PDM_RX_CTRL */
> +#define MAX98927_PDM_RX_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R0036_AMP_VOL_CTRL */
> +#define MAX98927_AMP_VOL_SEL (0x1 << 7)
> +#define MAX98927_AMP_VOL_SEL_WIDTH (1)
> +#define MAX98927_AMP_VOL_SEL_SHIFT (7)
> +#define MAX98927_AMP_VOL_MASK (0x7f << 0)
> +#define MAX98927_AMP_VOL_WIDTH (7)
> +#define MAX98927_AMP_VOL_SHIFT (0)
> +
> +/* MAX98927_R0037_AMP_DSP_CFG */
> +#define MAX98927_AMP_DSP_CFG_DCBLK_EN (0x1 << 0)
> +#define MAX98927_AMP_DSP_CFG_DITH_EN (0x1 << 1)
> +#define MAX98927_AMP_DSP_CFG_RMP_BYPASS (0x1 << 4)
> +#define MAX98927_AMP_DSP_CFG_DAC_INV (0x1 << 5)
> +#define MAX98927_AMP_DSP_CFG_RMP_SHIFT (4)
> +
> +/* MAX98927_R0039_DRE_CTRL */
> +#define MAX98927_DRE_CTRL_DRE_EN       (0x1 << 0)
> +#define MAX98927_DRE_EN_SHIFT 0x1
> +
> +/* MAX98927_R003A_AMP_EN */
> +#define MAX98927_AMP_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R003B_SPK_SRC_SEL */
> +#define MAX98927_SPK_SRC_MASK (0x3 << 0)
> +
> +/* MAX98927_R003C_SPK_GAIN */
> +#define MAX98927_SPK_PCM_GAIN_MASK (0x7 << 0)
> +#define MAX98927_SPK_PDM_GAIN_MASK (0x7 << 4)
> +#define MAX98927_SPK_GAIN_WIDTH (3)
> +
> +/* MAX98927_R003E_MEAS_EN */
> +#define MAX98927_MEAS_V_EN (0x1 << 0)
> +#define MAX98927_MEAS_I_EN (0x1 << 1)
> +
> +/* MAX98927_R0040_BOOST_CTRL0 */
> +#define MAX98927_BOOST_CTRL0_VOUT_MASK (0x1f << 0)
> +#define MAX98927_BOOST_CTRL0_PVDD_MASK (0x1 << 7)
> +#define MAX98927_BOOST_CTRL0_PVDD_EN_SHIFT (7)
> +
> +/* MAX98927_R0052_BROWNOUT_EN */
> +#define MAX98927_BROWNOUT_BDE_EN (0x1 << 0)
> +#define MAX98927_BROWNOUT_AMP_EN (0x1 << 1)
> +#define MAX98927_BROWNOUT_DSP_EN (0x1 << 2)
> +#define MAX98927_BROWNOUT_DSP_SHIFT (2)
> +
> +/* MAX98927_R0100_SOFT_RESET */
> +#define MAX98927_SOFT_RESET (0x1 << 0)
> +
> +/* MAX98927_R00FF_GLOBAL_SHDN */
> +#define MAX98927_GLOBAL_EN_MASK (0x1 << 0)
> +
> +struct max98927_priv {
> +       struct regmap *regmap;
> +       struct snd_soc_codec *codec;
> +       struct max98927_pdata *pdata;
> +       unsigned int spk_gain;
> +       unsigned int sysclk;
> +       unsigned int v_l_slot;
> +       unsigned int i_l_slot;
> +       bool interleave_mode;
> +       unsigned int ch_size;
> +       unsigned int rate;
> +       unsigned int iface;
> +       unsigned int master;
> +       unsigned int digital_gain;
> +};
> +#endif
> --
> 2.11.0
>

^ permalink raw reply

* [PATCH] ARM: dts: Add devicetree for the Raspberry Pi 3, for arm32 (v6)
From: Eric Anholt @ 2017-04-25 16:45 UTC (permalink / raw)
  To: Lee Jones, Florian Fainelli, Olof Johansson, Rob Herring,
	Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Stefan Wahren,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Gerd Hoffmann,
	Eric Anholt

Raspbian and Fedora have decided to support the Pi3 in 32-bit mode for
now, so it's useful to be able to test that mode on an upstream
kernel.  It's also been useful for me to use the same board for 32-bit
and 64-bit development.

Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
---
 arch/arm/boot/dts/Makefile            | 1 +
 arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3-b.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 011808490fed..eded842d9978 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
 	bcm2835-rpi-b-plus.dtb \
 	bcm2835-rpi-a-plus.dtb \
 	bcm2836-rpi-2-b.dtb \
+	bcm2837-rpi-3-b.dtb \
 	bcm2835-rpi-zero.dtb
 dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4708-asus-rt-ac56u.dtb \
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
new file mode 100644
index 000000000000..c72a27d908b6
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
@@ -0,0 +1 @@
+#include "arm64/broadcom/bcm2837-rpi-3-b.dts"
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH] ARM: dts: Add devicetree for the Raspberry Pi 3, for arm32 (v5)
From: Eric Anholt @ 2017-04-25 16:45 UTC (permalink / raw)
  To: Stefan Wahren, Lee Jones, Florian Fainelli, Olof Johansson,
	Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Gerd Hoffmann,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <68d88bf7-1f47-4056-3b70-7b97d9a02953-eS4NqCHxEME@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]

Stefan Wahren <stefan.wahren-eS4NqCHxEME@public.gmane.org> writes:

> Am 24.04.2017 um 22:00 schrieb Eric Anholt:
>> Raspbian and Fedora have decided to support the Pi3 in 32-bit mode for
>> now, so it's useful to be able to test that mode on an upstream
>> kernel.  It's also been useful for me to use the same board for 32-bit
>> and 64-bit development.
>>
>> Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> ---
>>  arch/arm/boot/dts/Makefile            | 1 +
>>  arch/arm/boot/dts/bcm2837-rpi-3.b.dts | 1 +
>>  2 files changed, 2 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 011808490fed..eded842d9978 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
>>  	bcm2835-rpi-b-plus.dtb \
>>  	bcm2835-rpi-a-plus.dtb \
>>  	bcm2836-rpi-2-b.dtb \
>> +	bcm2837-rpi-3-b.dtb \
>>  	bcm2835-rpi-zero.dtb
>>  dtb-$(CONFIG_ARCH_BCM_5301X) += \
>>  	bcm4708-asus-rt-ac56u.dtb \
>> diff --git a/arch/arm/boot/dts/bcm2837-rpi-3.b.dts b/arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>> new file mode 100644
>> index 000000000000..8c8aa4d1e9b3
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/bcm2837-rpi-3.b.dts
>> @@ -0,0 +1 @@
>> +#include "arm64/broadcom/bcm2837-rpi-3.b.dts"
>
> Looks like a typo in the dts filename and in the include ( dot instead
> of dash ).

Sorry about that, everyone.  I remember doing builds of the patch, but
maybe things succeeded because there was already a .dtb present in my
tree or something.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/2] of: Add unit tests for applying overlays
From: Rob Herring @ 2017-04-25 16:44 UTC (permalink / raw)
  To: Frank Rowand
  Cc: Stephen Boyd, Michal Marek, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Linux Kbuild mailing list
In-Reply-To: <1493075119-32026-3-git-send-email-frowand.list@gmail.com>

On Mon, Apr 24, 2017 at 6:05 PM,  <frowand.list@gmail.com> wrote:
> From: Frank Rowand <frank.rowand@sony.com>
>
> Existing overlay unit tests examine individual pieces of the overlay
> code.  The new tests target the entire process of applying an overlay.

Just a few nits.

> Signed-off-by: Frank Rowand <frank.rowand@sony.com>

[...]

> diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
> index 18bbb4517e25..cc76b3b81eab 100644
> --- a/drivers/of/of_private.h
> +++ b/drivers/of/of_private.h
> @@ -55,6 +55,17 @@ static inline int of_property_notify(int action, struct device_node *np,
>  }
>  #endif /* CONFIG_OF_DYNAMIC */
>
> +#ifdef CONFIG_OF_UNITTEST
> +extern void __init unittest_unflatten_overlay_base(void);
> +extern void *__unflatten_device_tree(const void *blob,

This can and should be outside the ifdef.

> +                             struct device_node *dad,
> +                             struct device_node **mynodes,
> +                             void *(*dt_alloc)(u64 size, u64 align),
> +                             bool detached);
> +#else
> +static inline void unittest_unflatten_overlay_base(void) {};
> +#endif
> +
>  /**
>   * General utilities for working with live trees.
>   *

[...]

> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
> index 62db55b97c10..884f6c1f8ae9 100644
> --- a/drivers/of/unittest.c
> +++ b/drivers/of/unittest.c
> @@ -8,6 +8,7 @@
>  #include <linux/err.h>
>  #include <linux/errno.h>
>  #include <linux/hashtable.h>
> +#include <linux/libfdt.h>
>  #include <linux/of.h>
>  #include <linux/of_fdt.h>
>  #include <linux/of_irq.h>
> @@ -1925,6 +1926,320 @@ static void __init of_unittest_overlay(void)
>  static inline void __init of_unittest_overlay(void) { }
>  #endif
>
> +#ifdef CONFIG_OF_OVERLAY

This can move down to...

> +
> +/*
> + * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
> + * in scripts/Makefile.lib
> + */
> +
> +#define OVERLAY_INFO_EXTERN(name) \
> +       extern uint8_t __dtb_##name##_begin[]; \
> +       extern uint8_t __dtb_##name##_end[]
> +
> +#define OVERLAY_INFO(name, expected) \
> +{      .dtb_begin       = __dtb_##name##_begin, \
> +       .dtb_end         = __dtb_##name##_end, \
> +       .expected_result = expected, \
> +}
> +
> +struct overlay_info {
> +       uint8_t            *dtb_begin;
> +       uint8_t            *dtb_end;
> +       void               *data;
> +       struct device_node *np_overlay;
> +       int                expected_result;
> +       int                overlay_id;
> +};
> +
> +OVERLAY_INFO_EXTERN(overlay_base);
> +OVERLAY_INFO_EXTERN(overlay);
> +OVERLAY_INFO_EXTERN(overlay_bad_phandle);

...here. Maybe we want to move all this to a separate file instead.

> +
> +/* order of entries is hard-coded into users of overlays[] */
> +struct overlay_info overlays[] = {

static?

> +       OVERLAY_INFO(overlay_base, -9999),
> +       OVERLAY_INFO(overlay, 0),
> +       OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
> +       {}
> +};

[...]

> @@ -1962,6 +2277,9 @@ static int __init of_unittest(void)
>         /* Double check linkage after removing testcase data */
>         of_unittest_check_tree_linkage();
>
> +

Extra blank line.

> +       of_unittest_overlay_high_level();
> +
>         pr_info("end of unittest - %i passed, %i failed\n",
>                 unittest_results.passed, unittest_results.failed);
>
> --
> Frank Rowand <frank.rowand@sony.com>
>

^ permalink raw reply

* Re: [PATCH v8 1/3] backlight arcxcnn add arc to vendor prefix
From: Jingoo Han @ 2017-04-25 16:36 UTC (permalink / raw)
  To: 'Olimpiu Dejeu', 'Rob Herring'
  Cc: 'Lee Jones', linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, 'Brian Dodge',
	'Joe Perches', 'Matthew D'Asaro',
	'Daniel Thompson'
In-Reply-To: <2aac01d2bd24$17449a90$45cdcfb0$@arcticsand.com>

On Monday, April 24, 2017 1:56 PM, Olimpiu Dejeu wrote:
> 
> On Mon, April 24, 2017 11:10 AM, Rob Herring < robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> 
> > On Wed, Mar 15, 2017 at 2:45 PM, Olimpiu Dejeu <olimpiu-eV7fy4qpoLhpLGFMi4vTTA@public.gmane.org>
> wrote:
> >> backlight: Add arc to vendor prefixes
> >> Signed-off-by: Olimpiu Dejeu <olimpiu-eV7fy4qpoLhpLGFMi4vTTA@public.gmane.org>
> >> ---
> >> v8:
> >> - Version to match other patches in set
> >>
> >>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> b/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> index 16d3b5e..6f33a4b 100644
> >> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> >> @@ -28,6 +28,7 @@ andestech     Andes Technology Corporation
> >>  apm    Applied Micro Circuits Corporation (APM)
> >>  aptina Aptina Imaging
> >>  arasan Arasan Chip Systems
> >> +arc    Arctic Sand
> 
> >arc is also a cpu arch. While not a vendor, it could be confusing. How
> about "arctic" >instead?
> 
> Rob, will do, i.e. I will change it to "arctic"

Hi Olimpiu,

Oh, "arc" and "arctic" is totally different.
In my opinion, one of the purposes of DT is to describe hardware stuffs.
So, please use more detailed words.

> 
> >BTW, some reason your patches are not going to the DT list.
> 
> 
> I'm emailing to devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, I think this is the correct
> list. Please advise.

DT is some kind of ABI. It means that changing DT names such as property names
is not easy, after DT patches were merged. So, if someone want to add new DT stuff
into the vanilla kernel, that patch should be reviewed more thoroughly
than normal patches about driver stuffs.

Thanks,
Jingoo Han

> 
> 
> >Rob
> Olimpiu
> 


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v14 00/11] mux controller abstraction and iio/i2c muxes
From: Philipp Zabel @ 2017-04-25 16:32 UTC (permalink / raw)
  To: Peter Rosin
  Cc: Jonathan Cameron, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Greg Kroah-Hartman, Wolfram Sang, Rob Herring, Mark Rutland,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Jonathan Corbet, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Andrew Morton, Colin Ian King,
	Paul Gortmaker, kernel-bIcnvbaLZ9MEGnE8C9+IrQ
In-Reply-To: <e53bbf82-793f-b22f-2e9b-4bd377446351-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>

On Tue, 2017-04-25 at 16:55 +0200, Peter Rosin wrote:
> On 2017-04-25 16:16, Peter Rosin wrote:
> > On 2017-04-24 16:59, Philipp Zabel wrote:
> >> On Mon, 2017-04-24 at 16:36 +0200, Peter Rosin wrote:
> >> [...]
> >>>> How about an atomic use_count on the mux_control, a bool shared that is
> >>>> only set by the first consumer, and controls whether selecting locks?
> >>>
> >>> That has the drawback that it is hard to restore the mux-control in a safe
> >>> way so that exclusive consumers are allowed after the last shared consumer
> >>> puts the mux away.
> >>
> >> True.
> >>
> >>> Agreed, it's a corner case, but I had this very similar
> >>> patch going through the compiler when I got this mail. Does it work as well
> >>> as what you suggested?
> >>
> >> Yes, this patch works just as well.
> > 
> > Right, as expected :-) However, I don't like it much. It divides the mux
> > consumers into two camps in a way that makes it difficult to select which
> > camp a consumer should be in.
> > 
> > E.g. consider the iio-mux. The current implementation only supports quick
> > accesses that fit the mux_control_get_shared case. But if that mux in the
> > future needs to grow continuous buffered accesses, I think there will be
> > pressure to switch it over to the exclusive mode. Because that is a lot
> > closer to what you are doing with the video-mux. And then what? It will be
> > impossible to predict if the end user is going to use buffered accesses or
> > not...
> > 
> > So, I think the best approach is to skip the distinction between shared
> > and exclusive consumers and instead implement the locking with an ordinary
> > semaphore (instead of the old rwsem or the current mutex). Semaphores don't
> > have the property that the same task should down/up them (mutexes require
> > that for lock/unlock, and is also the reason for the lockdep complaint) and
> > thus fits better for long-time use such as yours or the above iio-mux with
> > buffered accesses. It should also hopefully be cheaper that an rwsem, and
> > not have any downgrade_write calls thus possibly keeping Greg sufficiently
> > happy...

No idea whether this will placate Greg, but it does work for the
video-mux case.
The documentation for mux_control_(try_)select should mention that these
calls will hold the mux lock until deselect is called, and the
documentation for mux_control_select should probably mention that it
will block until the lock is released.

> > Sure, consumers can still dig themselves into a hole by not calling deselect
> > as they should, but at least I think it can be made to work w/o dividing the
> > consumers...
> 
> Like this (only compile-tested). Philipp, it should work the same as with
> the rwsem in v13 and earlier. At least for your case...

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Mark Brown @ 2017-04-25 16:28 UTC (permalink / raw)
  To: Ryan Lee
  Cc: Liam Girdwood, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
	Kuninori Morimoto, Arnd Bergmann,
	ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	lars-Qo5EllUWu/uELgA04lAiVw, bardliao-Rasf1IRRPZFBDgjK7y7TUQ,
	nh6z-fFIq/eER6g8, KCHSU0-KrzQf0k3Iz9BDgjK7y7TUQ, Axel Lin,
	romain.perier-ZGY8ohtN/8qB+jHODAdFcQ, Srinivas Kandagatla,
	oder_chiou-Rasf1IRRPZFBDgjK7y7TUQ,
	Paul.Handrigan-jGc1dHjMKG3QT0dZR+AlfA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dylan Reid
In-Reply-To: <CAN4-oj=suA8Bx_QLGOvGkjr=CgUwhPibNRk31Y_JaBydZX6USg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 544 bytes --]

On Tue, Apr 25, 2017 at 09:24:34AM -0700, Ryan Lee wrote:
> I was not able to see any activities about MAX98927 driver after previous mail.
> Is there anything wrong with this driver?

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.

I'm not sure what communication you're expecting...  if nobody is
complaining about your driver that's probably good?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v2 15/18] dt-bindings: sound: Add bindings for Cirrus Logic Madera codecs
From: Richard Fitzgerald @ 2017-04-25 16:27 UTC (permalink / raw)
  To: Mark Brown
  Cc: gnurou, alsa-devel, jason, devicetree, linus.walleij, patches,
	linux-kernel, linux-gpio, robh+dt, tglx, lee.jones
In-Reply-To: <20170425155257.s6m4wgrzxxsxcggo@sirena.org.uk>

On Tue, 2017-04-25 at 16:52 +0100, Mark Brown wrote:
> On Mon, Apr 24, 2017 at 05:08:41PM +0100, Richard Fitzgerald wrote:
> > The Cirrus Logic Madera codecs are a family of related codecs with
> > extensive digital and analogue I/O, digital mixing and routing,
> > signal processing and programmable DSPs.
> 
> Please submit patches using subject lines reflecting the style for the
> subsystem.  This makes it easier for people to identify relevant
> patches.  Look at what existing commits in the area you're changing are
> doing and make sure your subject lines visually resemble what they're
> doing.
> 
> > +Required properties:
> > +  - compatible : One of the following chip-specific strings:
> > +        "cirrus,cs47l35-codec"
> > +        "cirrus,cs47l85-codec"
> > +        "cirrus,cs47l90-codec"
> 
> You shouldn't have compatible strings for subfunctions of a MFD unless
> these represent meaningful reusable IPs that can exist separately from
> the parent chip, that's clearly not the case here.  All you're doing
> here is encoding Linux internal abstractions which aren't OS neutral and
> might change in future (for example clocking might move more into the
> clock API).

While that's nice, the of_node doesn't get populated if there isn't a
compatible string. And people don't like workarounds for the missing
of_node.

^ permalink raw reply

* Re: Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Ryan Lee @ 2017-04-25 16:24 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
	Kuninori Morimoto, Arnd Bergmann,
	ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	lars-Qo5EllUWu/uELgA04lAiVw, bardliao-Rasf1IRRPZFBDgjK7y7TUQ,
	nh6z-fFIq/eER6g8, KCHSU0-KrzQf0k3Iz9BDgjK7y7TUQ, Axel Lin,
	romain.perier-ZGY8ohtN/8qB+jHODAdFcQ, Srinivas Kandagatla,
	oder_chiou-Rasf1IRRPZFBDgjK7y7TUQ,
	Paul.Handrigan-jGc1dHjMKG3QT0dZR+AlfA,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dylan Reid
In-Reply-To: <E1cwCZ1-0001o4-Q5@debutante>

I was not able to see any activities about MAX98927 driver after previous mail.
Is there anything wrong with this driver?


On Thu, Apr 6, 2017 at 11:55 AM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> The patch
>
>    ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> has been applied to the asoc tree at
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
>
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.
>
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
>
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
>
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.
>
> Thanks,
> Mark
>
> From 7c0c2000716e64151b3c0c62026c18f31537ebe9 Mon Sep 17 00:00:00 2001
> From: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> Date: Tue, 4 Apr 2017 02:23:08 +0900
> Subject: [PATCH] ASoC: Add support for Maxim Integrated MAX98927 Amplifier
>
> Signed-off-by: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  .../devicetree/bindings/sound/max98925.txt         |  22 -
>  .../devicetree/bindings/sound/max98926.txt         |  32 -
>  .../devicetree/bindings/sound/max9892x.txt         |  41 +
>  sound/soc/codecs/Kconfig                           |   5 +
>  sound/soc/codecs/Makefile                          |   2 +
>  sound/soc/codecs/max98927.c                        | 841 +++++++++++++++++++++
>  sound/soc/codecs/max98927.h                        | 272 +++++++
>  7 files changed, 1161 insertions(+), 54 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98925.txt
>  delete mode 100644 Documentation/devicetree/bindings/sound/max98926.txt
>  create mode 100644 Documentation/devicetree/bindings/sound/max9892x.txt
>  create mode 100644 sound/soc/codecs/max98927.c
>  create mode 100644 sound/soc/codecs/max98927.h
>
> diff --git a/Documentation/devicetree/bindings/sound/max98925.txt b/Documentation/devicetree/bindings/sound/max98925.txt
> deleted file mode 100644
> index 27be63e2aa0d..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98925.txt
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -max98925 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98925"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98925@1a {
> -       compatible = "maxim,max98925";
> -       vmon-slot-no = <0>;
> -       imon-slot-no = <2>;
> -       reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt
> deleted file mode 100644
> index 0b7f4e4d5f9a..000000000000
> --- a/Documentation/devicetree/bindings/sound/max98926.txt
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -max98926 audio CODEC
> -
> -This device supports I2C.
> -
> -Required properties:
> -
> -  - compatible : "maxim,max98926"
> -
> -  - vmon-slot-no : slot number used to send voltage information
> -                   or in inteleave mode this will be used as
> -                   interleave slot.
> -
> -  - imon-slot-no : slot number used to send current information
> -
> -  - interleave-mode : When using two MAX98926 in a system it is
> -                      possible to create ADC data that that will
> -                      overflow the frame size. Digital Audio Interleave
> -                      mode provides a means to output VMON and IMON data
> -                      from two devices on a single DOUT line when running
> -                      smaller frames sizes such as 32 BCLKS per LRCLK or
> -                      48 BCLKS per LRCLK.
> -
> -  - reg : the I2C address of the device for I2C
> -
> -Example:
> -
> -codec: max98926@1a {
> -   compatible = "maxim,max98926";
> -   vmon-slot-no = <0>;
> -   imon-slot-no = <2>;
> -   reg = <0x1a>;
> -};
> diff --git a/Documentation/devicetree/bindings/sound/max9892x.txt b/Documentation/devicetree/bindings/sound/max9892x.txt
> new file mode 100644
> index 000000000000..f6171591ddc6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/max9892x.txt
> @@ -0,0 +1,41 @@
> +Maxim Integrated MAX98925/MAX98926/MAX98927 Speaker Amplifier
> +
> +This device supports I2C.
> +
> +Required properties:
> +
> +  - compatible : should be one of the following
> +    - "maxim,max98925"
> +    - "maxim,max98926"
> +    - "maxim,max98927"
> +
> +  - vmon-slot-no : slot number used to send voltage information
> +                   or in inteleave mode this will be used as
> +                   interleave slot.
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - imon-slot-no : slot number used to send current information
> +                   MAX98925/MAX98926 slot range : 0 ~ 30,  Default : 0
> +                   MAX98927 slot range : 0 ~ 15,  Default : 0
> +
> +  - interleave-mode : When using two MAX9892X in a system it is
> +                   possible to create ADC data that that will
> +                   overflow the frame size. Digital Audio Interleave
> +                   mode provides a means to output VMON and IMON data
> +                   from two devices on a single DOUT line when running
> +                   smaller frames sizes such as 32 BCLKS per LRCLK or
> +                   48 BCLKS per LRCLK.
> +                   Range : 0 (off), 1 (on),  Default : 0
> +
> +  - reg : the I2C address of the device for I2C
> +
> +Example:
> +
> +codec: max98927@3a {
> +   compatible = "maxim,max98927";
> +   vmon-slot-no = <0>;
> +   imon-slot-no = <1>;
> +   interleave-mode = <0>;
> +   reg = <0x3a>;
> +};
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 9e1718a8cb1c..65e31ab88280 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -89,6 +89,7 @@ config SND_SOC_ALL_CODECS
>         select SND_SOC_MAX9867 if I2C
>         select SND_SOC_MAX98925 if I2C
>         select SND_SOC_MAX98926 if I2C
> +       select SND_SOC_MAX98927 if I2C
>         select SND_SOC_MAX9850 if I2C
>         select SND_SOC_MAX9860 if I2C
>         select SND_SOC_MAX9768 if I2C
> @@ -585,6 +586,10 @@ config SND_SOC_MAX98925
>  config SND_SOC_MAX98926
>         tristate
>
> +config SND_SOC_MAX98927
> +       tristate "Maxim Integrated MAX98927 Speaker Amplifier"
> +       depends on I2C
> +
>  config SND_SOC_MAX9850
>         tristate
>
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 7e1dad79610b..64656c43200c 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -84,6 +84,7 @@ snd-soc-max98371-objs := max98371.o
>  snd-soc-max9867-objs := max9867.o
>  snd-soc-max98925-objs := max98925.o
>  snd-soc-max98926-objs := max98926.o
> +snd-soc-max98927-objs := max98927.o
>  snd-soc-max9850-objs := max9850.o
>  snd-soc-max9860-objs := max9860.o
>  snd-soc-mc13783-objs := mc13783.o
> @@ -312,6 +313,7 @@ obj-$(CONFIG_SND_SOC_MAX98357A)     += snd-soc-max98357a.o
>  obj-$(CONFIG_SND_SOC_MAX9867)  += snd-soc-max9867.o
>  obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
>  obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
> +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
>  obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
>  obj-$(CONFIG_SND_SOC_MAX9860)  += snd-soc-max9860.o
>  obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
> diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c
> new file mode 100644
> index 000000000000..b5ee29499e16
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.c
> @@ -0,0 +1,841 @@
> +/*
> + * max98927.c  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright (C) 2016 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <sound/tlv.h>
> +#include "max98927.h"
> +
> +static struct reg_default max98927_reg[] = {
> +       {MAX98927_R0001_INT_RAW1,  0x00},
> +       {MAX98927_R0002_INT_RAW2,  0x00},
> +       {MAX98927_R0003_INT_RAW3,  0x00},
> +       {MAX98927_R0004_INT_STATE1,  0x00},
> +       {MAX98927_R0005_INT_STATE2,  0x00},
> +       {MAX98927_R0006_INT_STATE3,  0x00},
> +       {MAX98927_R0007_INT_FLAG1,  0x00},
> +       {MAX98927_R0008_INT_FLAG2,  0x00},
> +       {MAX98927_R0009_INT_FLAG3,  0x00},
> +       {MAX98927_R000A_INT_EN1,  0x00},
> +       {MAX98927_R000B_INT_EN2,  0x00},
> +       {MAX98927_R000C_INT_EN3,  0x00},
> +       {MAX98927_R000D_INT_FLAG_CLR1,  0x00},
> +       {MAX98927_R000E_INT_FLAG_CLR2,  0x00},
> +       {MAX98927_R000F_INT_FLAG_CLR3,  0x00},
> +       {MAX98927_R0010_IRQ_CTRL,  0x00},
> +       {MAX98927_R0011_CLK_MON,  0x00},
> +       {MAX98927_R0012_WDOG_CTRL,  0x00},
> +       {MAX98927_R0013_WDOG_RST,  0x00},
> +       {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH,  0x00},
> +       {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH,  0x00},
> +       {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS,  0x00},
> +       {MAX98927_R0017_PIN_CFG,  0x55},
> +       {MAX98927_R0018_PCM_RX_EN_A,  0x00},
> +       {MAX98927_R0019_PCM_RX_EN_B,  0x00},
> +       {MAX98927_R001A_PCM_TX_EN_A,  0x00},
> +       {MAX98927_R001B_PCM_TX_EN_B,  0x00},
> +       {MAX98927_R001C_PCM_TX_HIZ_CTRL_A,  0x00},
> +       {MAX98927_R001D_PCM_TX_HIZ_CTRL_B,  0x00},
> +       {MAX98927_R001E_PCM_TX_CH_SRC_A,  0x00},
> +       {MAX98927_R001F_PCM_TX_CH_SRC_B,  0x00},
> +       {MAX98927_R0020_PCM_MODE_CFG,  0x40},
> +       {MAX98927_R0021_PCM_MASTER_MODE,  0x00},
> +       {MAX98927_R0022_PCM_CLK_SETUP,  0x22},
> +       {MAX98927_R0023_PCM_SR_SETUP1,  0x00},
> +       {MAX98927_R0024_PCM_SR_SETUP2,  0x00},
> +       {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,  0x00},
> +       {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,  0x00},
> +       {MAX98927_R0027_ICC_RX_EN_A,  0x00},
> +       {MAX98927_R0028_ICC_RX_EN_B,  0x00},
> +       {MAX98927_R002B_ICC_TX_EN_A,  0x00},
> +       {MAX98927_R002C_ICC_TX_EN_B,  0x00},
> +       {MAX98927_R002E_ICC_HIZ_MANUAL_MODE,  0x00},
> +       {MAX98927_R002F_ICC_TX_HIZ_EN_A,  0x00},
> +       {MAX98927_R0030_ICC_TX_HIZ_EN_B,  0x00},
> +       {MAX98927_R0031_ICC_LNK_EN,  0x00},
> +       {MAX98927_R0032_PDM_TX_EN,  0x00},
> +       {MAX98927_R0033_PDM_TX_HIZ_CTRL,  0x00},
> +       {MAX98927_R0034_PDM_TX_CTRL,  0x00},
> +       {MAX98927_R0035_PDM_RX_CTRL,  0x00},
> +       {MAX98927_R0036_AMP_VOL_CTRL,  0x00},
> +       {MAX98927_R0037_AMP_DSP_CFG,  0x02},
> +       {MAX98927_R0038_TONE_GEN_DC_CFG,  0x00},
> +       {MAX98927_R0039_DRE_CTRL,  0x01},
> +       {MAX98927_R003A_AMP_EN,  0x00},
> +       {MAX98927_R003B_SPK_SRC_SEL,  0x00},
> +       {MAX98927_R003C_SPK_GAIN,  0x00},
> +       {MAX98927_R003D_SSM_CFG,  0x01},
> +       {MAX98927_R003E_MEAS_EN,  0x00},
> +       {MAX98927_R003F_MEAS_DSP_CFG,  0x04},
> +       {MAX98927_R0040_BOOST_CTRL0,  0x00},
> +       {MAX98927_R0041_BOOST_CTRL3,  0x00},
> +       {MAX98927_R0042_BOOST_CTRL1,  0x00},
> +       {MAX98927_R0043_MEAS_ADC_CFG,  0x00},
> +       {MAX98927_R0044_MEAS_ADC_BASE_MSB,  0x00},
> +       {MAX98927_R0045_MEAS_ADC_BASE_LSB,  0x00},
> +       {MAX98927_R0046_ADC_CH0_DIVIDE,  0x00},
> +       {MAX98927_R0047_ADC_CH1_DIVIDE,  0x00},
> +       {MAX98927_R0048_ADC_CH2_DIVIDE,  0x00},
> +       {MAX98927_R0049_ADC_CH0_FILT_CFG,  0x00},
> +       {MAX98927_R004A_ADC_CH1_FILT_CFG,  0x00},
> +       {MAX98927_R004B_ADC_CH2_FILT_CFG,  0x00},
> +       {MAX98927_R004C_MEAS_ADC_CH0_READ,  0x00},
> +       {MAX98927_R004D_MEAS_ADC_CH1_READ,  0x00},
> +       {MAX98927_R004E_MEAS_ADC_CH2_READ,  0x00},
> +       {MAX98927_R0051_BROWNOUT_STATUS,  0x00},
> +       {MAX98927_R0052_BROWNOUT_EN,  0x00},
> +       {MAX98927_R0053_BROWNOUT_INFINITE_HOLD,  0x00},
> +       {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR,  0x00},
> +       {MAX98927_R0055_BROWNOUT_LVL_HOLD,  0x00},
> +       {MAX98927_R005A_BROWNOUT_LVL1_THRESH,  0x00},
> +       {MAX98927_R005B_BROWNOUT_LVL2_THRESH,  0x00},
> +       {MAX98927_R005C_BROWNOUT_LVL3_THRESH,  0x00},
> +       {MAX98927_R005D_BROWNOUT_LVL4_THRESH,  0x00},
> +       {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS,  0x00},
> +       {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL,  0x00},
> +       {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL,  0x00},
> +       {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE,  0x00},
> +       {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT,  0x00},
> +       {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT,  0x00},
> +       {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT,  0x00},
> +       {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1,  0x00},
> +       {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2,  0x00},
> +       {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3,  0x00},
> +       {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT,  0x00},
> +       {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,  0x00},
> +       {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2,  0x00},
> +       {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3,  0x00},
> +       {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,  0x00},
> +       {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY,  0x00},
> +       {MAX98927_R0084_ENV_TRACK_REL_RATE,  0x00},
> +       {MAX98927_R0085_ENV_TRACK_HOLD_RATE,  0x00},
> +       {MAX98927_R0086_ENV_TRACK_CTRL,  0x00},
> +       {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,  0x00},
> +       {MAX98927_R00FF_GLOBAL_SHDN,  0x00},
> +       {MAX98927_R0100_SOFT_RESET,  0x00},
> +       {MAX98927_R01FF_REV_ID,  0x40},
> +};
> +
> +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
> +{
> +       struct snd_soc_codec *codec = codec_dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int mode = 0;
> +       unsigned int format = 0;
> +       unsigned int invert = 0;
> +
> +       dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
> +
> +       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +       case SND_SOC_DAIFMT_CBS_CFS:
> +               mode = MAX98927_PCM_MASTER_MODE_SLAVE;
> +               break;
> +       case SND_SOC_DAIFMT_CBM_CFM:
> +               max98927->master = true;
> +               mode = MAX98927_PCM_MASTER_MODE_MASTER;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI clock mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0021_PCM_MASTER_MODE,
> +               MAX98927_PCM_MASTER_MODE_MASK,
> +               mode);
> +
> +       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +       case SND_SOC_DAIFMT_NB_NF:
> +               break;
> +       case SND_SOC_DAIFMT_IB_NF:
> +               invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE;
> +               break;
> +       default:
> +               dev_err(codec->dev, "DAI invert mode unsupported");
> +               return -EINVAL;
> +       }
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE,
> +               invert);
> +
> +       /* interface format */
> +       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +       case SND_SOC_DAIFMT_I2S:
> +               max98927->iface |= SND_SOC_DAIFMT_I2S;
> +               format = MAX98927_PCM_FORMAT_I2S;
> +               break;
> +       case SND_SOC_DAIFMT_LEFT_J:
> +               max98927->iface |= SND_SOC_DAIFMT_LEFT_J;
> +               format = MAX98927_PCM_FORMAT_LJ;
> +               break;
> +       case SND_SOC_DAIFMT_PDM:
> +               max98927->iface |= SND_SOC_DAIFMT_PDM;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       /* pcm channel configuration */
> +       if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0020_PCM_MODE_CFG,
> +                       MAX98927_PCM_MODE_CFG_FORMAT_MASK,
> +                       format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 0);
> +
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0018_PCM_RX_EN_A,
> +                       MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);
> +
> +       /* pdm channel configuration */
> +       if (max98927->iface & SND_SOC_DAIFMT_PDM) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 1);
> +
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003B_SPK_SRC_SEL,
> +                       MAX98927_SPK_SRC_MASK, 3);
> +       } else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0035_PDM_RX_CTRL,
> +                       MAX98927_PDM_RX_EN_MASK, 0);
> +       return 0;
> +}
> +
> +/* codec MCLK rate in master mode */
> +static const int rate_table[] = {
> +       5644800, 6000000, 6144000, 6500000,
> +       9600000, 11289600, 12000000, 12288000,
> +       13000000, 19200000,
> +};
> +
> +static int max98927_set_clock(struct max98927_priv *max98927,
> +       struct snd_pcm_hw_params *params)
> +{
> +       struct snd_soc_codec *codec = max98927->codec;
> +       /* BCLK/LRCLK ratio calculation */
> +       int blr_clk_ratio = params_channels(params) * max98927->ch_size;
> +       int value;
> +
> +       if (max98927->master) {
> +               int i;
> +               /* match rate to closest value */
> +               for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
> +                       if (rate_table[i] >= max98927->sysclk)
> +                               break;
> +               }
> +               if (i == ARRAY_SIZE(rate_table)) {
> +                       dev_err(codec->dev, "failed to find proper clock rate.\n");
> +                       return -EINVAL;
> +               }
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0021_PCM_MASTER_MODE,
> +                       MAX98927_PCM_MASTER_MODE_MCLK_MASK,
> +                       i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
> +       }
> +
> +       switch (blr_clk_ratio) {
> +       case 32:
> +               value = 2;
> +               break;
> +       case 48:
> +               value = 3;
> +               break;
> +       case 64:
> +               value = 4;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0022_PCM_CLK_SETUP,
> +               MAX98927_PCM_CLK_SETUP_BSEL_MASK,
> +               value);
> +       return 0;
> +}
> +
> +static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
> +       struct snd_pcm_hw_params *params,
> +       struct snd_soc_dai *dai)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +       unsigned int sampling_rate = 0;
> +       unsigned int chan_sz = 0;
> +
> +       /* pcm mode configuration */
> +       switch (snd_pcm_format_width(params_format(params))) {
> +       case 16:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
> +               break;
> +       case 24:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
> +               break;
> +       case 32:
> +               chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
> +               break;
> +       default:
> +               dev_err(codec->dev, "format unsupported %d",
> +                       params_format(params));
> +               goto err;
> +       }
> +
> +       max98927->ch_size = snd_pcm_format_width(params_format(params));
> +
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0020_PCM_MODE_CFG,
> +               MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
> +
> +       dev_dbg(codec->dev, "format supported %d",
> +               params_format(params));
> +
> +       /* sampling rate configuration */
> +       switch (params_rate(params)) {
> +       case 8000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_8000;
> +               break;
> +       case 11025:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_11025;
> +               break;
> +       case 12000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_12000;
> +               break;
> +       case 16000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_16000;
> +               break;
> +       case 22050:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_22050;
> +               break;
> +       case 24000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_24000;
> +               break;
> +       case 32000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_32000;
> +               break;
> +       case 44100:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_44100;
> +               break;
> +       case 48000:
> +               sampling_rate = MAX98927_PCM_SR_SET1_SR_48000;
> +               break;
> +       default:
> +               dev_err(codec->dev, "rate %d not supported\n",
> +                       params_rate(params));
> +               goto err;
> +       }
> +       /* set DAI_SR to correct LRCLK frequency */
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0023_PCM_SR_SETUP1,
> +               MAX98927_PCM_SR_SET1_SR_MASK,
> +               sampling_rate);
> +       regmap_update_bits(max98927->regmap,
> +               MAX98927_R0024_PCM_SR_SETUP2,
> +               MAX98927_PCM_SR_SET2_SR_MASK,
> +               sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT);
> +
> +       /* set sampling rate of IV */
> +       if (max98927->interleave_mode &&
> +           sampling_rate > MAX98927_PCM_SR_SET1_SR_16000)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate - 3);
> +       else
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R0024_PCM_SR_SETUP2,
> +                       MAX98927_PCM_SR_SET2_IVADC_SR_MASK,
> +                       sampling_rate);
> +       return max98927_set_clock(max98927, params);
> +err:
> +       return -EINVAL;
> +}
> +
> +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000
> +
> +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
> +       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
> +
> +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai,
> +       int clk_id, unsigned int freq, int dir)
> +{
> +       struct snd_soc_codec *codec = dai->codec;
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->sysclk = freq;
> +       return 0;
> +}
> +
> +static const struct snd_soc_dai_ops max98927_dai_ops = {
> +       .set_sysclk = max98927_dai_set_sysclk,
> +       .set_fmt = max98927_dai_set_fmt,
> +       .hw_params = max98927_dai_hw_params,
> +};
> +
> +static int max98927_dac_event(struct snd_soc_dapm_widget *w,
> +       struct snd_kcontrol *kcontrol, int event)
> +{
> +       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       switch (event) {
> +       case SND_SOC_DAPM_POST_PMU:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 1);
> +               /* enable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 1);
> +               break;
> +       case SND_SOC_DAPM_POST_PMD:
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R00FF_GLOBAL_SHDN,
> +                       MAX98927_GLOBAL_EN_MASK, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003A_AMP_EN,
> +                       MAX98927_AMP_EN_MASK, 0);
> +               /* disable VMON and IMON */
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R003E_MEAS_EN,
> +                       MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, 0);
> +               break;
> +       default:
> +               return 0;
> +       }
> +       return 0;
> +}
> +
> +static const char * const max98927_switch_text[] = {
> +       "Left", "Right", "LeftRight"};
> +
> +static const struct soc_enum dai_sel_enum =
> +       SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
> +               3, max98927_switch_text);
> +
> +static const struct snd_kcontrol_new max98927_dai_controls =
> +       SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
> +
> +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = {
> +       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
> +       SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN,
> +               0, 0, max98927_dac_event,
> +               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
> +       SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
> +               &max98927_dai_controls),
> +       SND_SOC_DAPM_OUTPUT("BE_OUT"),
> +};
> +
> +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0);
> +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0);
> +
> +static bool max98927_readable_register(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B:
> +       case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B:
> +       case MAX98927_R002E_ICC_HIZ_MANUAL_MODE
> +               ... MAX98927_R004E_MEAS_ADC_CH2_READ:
> +       case MAX98927_R0051_BROWNOUT_STATUS
> +               ... MAX98927_R0055_BROWNOUT_LVL_HOLD:
> +       case MAX98927_R005A_BROWNOUT_LVL1_THRESH
> +               ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE:
> +       case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT
> +               ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ:
> +       case MAX98927_R00FF_GLOBAL_SHDN:
> +       case MAX98927_R0100_SOFT_RESET:
> +       case MAX98927_R01FF_REV_ID:
> +               return true;
> +       default:
> +               return false;
> +       }
> +};
> +
> +static bool max98927_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static const char * const max98927_boost_voltage_text[] = {
> +       "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
> +       "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
> +       "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
> +       "9.5V", "9.625V", "9.75V", "9.875V", "10V"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_boost_voltage,
> +               MAX98927_R0040_BOOST_CTRL0, 0,
> +               max98927_boost_voltage_text);
> +
> +static const char * const max98927_current_limit_text[] = {
> +       "1.00A", "1.10A", "1.20A", "1.30A", "1.40A", "1.50A", "1.60A", "1.70A",
> +       "1.80A", "1.90A", "2.00A", "2.10A", "2.20A", "2.30A", "2.40A", "2.50A",
> +       "2.60A", "2.70A", "2.80A", "2.90A", "3.00A", "3.10A", "3.20A", "3.30A",
> +       "3.40A", "3.50A", "3.60A", "3.70A", "3.80A", "3.90A", "4.00A", "4.10A"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(max98927_current_limit,
> +               MAX98927_R0042_BOOST_CTRL1, 1,
> +               max98927_current_limit_text);
> +
> +static const struct snd_kcontrol_new max98927_snd_controls[] = {
> +       SOC_SINGLE_TLV("Speaker Volume", MAX98927_R003C_SPK_GAIN,
> +               0, 6, 0,
> +               max98927_spk_tlv),
> +       SOC_SINGLE_TLV("Digital Volume", MAX98927_R0036_AMP_VOL_CTRL,
> +               0, (1<<MAX98927_AMP_VOL_WIDTH)-1, 0,
> +               max98927_digital_tlv),
> +       SOC_SINGLE("Amp DSP Switch", MAX98927_R0052_BROWNOUT_EN,
> +               MAX98927_BROWNOUT_DSP_SHIFT, 1, 0),
> +       SOC_SINGLE("Ramp Switch", MAX98927_R0037_AMP_DSP_CFG,
> +               MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0),
> +       SOC_SINGLE("DRE Switch", MAX98927_R0039_DRE_CTRL,
> +               MAX98927_DRE_EN_SHIFT, 1, 0),
> +       SOC_SINGLE("Volume Location Switch", MAX98927_R0036_AMP_VOL_CTRL,
> +               MAX98927_AMP_VOL_SEL_SHIFT, 1, 0),
> +       SOC_ENUM("Boost Output Voltage", max98927_boost_voltage),
> +       SOC_ENUM("Current Limit", max98927_current_limit),
> +};
> +
> +static const struct snd_soc_dapm_route max98927_audio_map[] = {
> +       {"Amp Enable", NULL, "DAI_OUT"},
> +       {"DAI Sel Mux", "Left", "Amp Enable"},
> +       {"DAI Sel Mux", "Right", "Amp Enable"},
> +       {"DAI Sel Mux", "LeftRight", "Amp Enable"},
> +       {"BE_OUT", NULL, "DAI Sel Mux"},
> +};
> +
> +static struct snd_soc_dai_driver max98927_dai[] = {
> +       {
> +               .name = "max98927-aif1",
> +               .playback = {
> +                       .stream_name = "HiFi Playback",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .capture = {
> +                       .stream_name = "HiFi Capture",
> +                       .channels_min = 1,
> +                       .channels_max = 2,
> +                       .rates = MAX98927_RATES,
> +                       .formats = MAX98927_FORMATS,
> +               },
> +               .ops = &max98927_dai_ops,
> +       }
> +};
> +
> +static int max98927_probe(struct snd_soc_codec *codec)
> +{
> +       struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
> +
> +       max98927->codec = codec;
> +       codec->control_data = max98927->regmap;
> +       codec->cache_bypass = 1;
> +
> +       /* Software Reset */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0100_SOFT_RESET, MAX98927_SOFT_RESET);
> +
> +       /* IV default slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +               0xFF);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0025_PCM_TO_SPK_MONOMIX_A,
> +               0x80);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0026_PCM_TO_SPK_MONOMIX_B,
> +               0x1);
> +       /* Set inital volume (+13dB) */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0036_AMP_VOL_CTRL,
> +               0x38);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003C_SPK_GAIN,
> +               0x05);
> +       /* Enable DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0037_AMP_DSP_CFG,
> +               0x03);
> +       /* Enable IMON VMON DC blocker */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R003F_MEAS_DSP_CFG,
> +               0xF7);
> +       /* Boost Output Voltage & Current limit */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0040_BOOST_CTRL0,
> +               0x1C);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0042_BOOST_CTRL1,
> +               0x3E);
> +       /* Measurement ADC config */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0043_MEAS_ADC_CFG,
> +               0x04);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0044_MEAS_ADC_BASE_MSB,
> +               0x00);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0045_MEAS_ADC_BASE_LSB,
> +               0x24);
> +       /* Brownout Level */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1,
> +               0x06);
> +       /* Envelope Tracking configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM,
> +               0x08);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0086_ENV_TRACK_CTRL,
> +               0x01);
> +       regmap_write(max98927->regmap,
> +               MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ,
> +               0x10);
> +
> +       /* voltage, current slot configuration */
> +       regmap_write(max98927->regmap,
> +               MAX98927_R001E_PCM_TX_CH_SRC_A,
> +               (max98927->i_l_slot<<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT|
> +               max98927->v_l_slot)&0xFF);
> +
> +       if (max98927->v_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->v_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->v_l_slot,
> +                       1 << max98927->v_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->v_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->v_l_slot - 8),
> +                       1 << (max98927->v_l_slot - 8));
> +       }
> +
> +       if (max98927->i_l_slot < 8) {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
> +                       1 << max98927->i_l_slot, 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001A_PCM_TX_EN_A,
> +                       1 << max98927->i_l_slot,
> +                       1 << max98927->i_l_slot);
> +       } else {
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
> +                       1 << (max98927->i_l_slot - 8), 0);
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001B_PCM_TX_EN_B,
> +                       1 << (max98927->i_l_slot - 8),
> +                       1 << (max98927->i_l_slot - 8));
> +       }
> +
> +       /* Set interleave mode */
> +       if (max98927->interleave_mode)
> +               regmap_update_bits(max98927->regmap,
> +                       MAX98927_R001F_PCM_TX_CH_SRC_B,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK,
> +                       MAX98927_PCM_TX_CH_INTERLEAVE_MASK);
> +       return 0;
> +}
> +
> +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = {
> +       .probe = max98927_probe,
> +       .component_driver = {
> +               .controls = max98927_snd_controls,
> +               .num_controls = ARRAY_SIZE(max98927_snd_controls),
> +               .dapm_widgets = max98927_dapm_widgets,
> +               .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets),
> +               .dapm_routes = max98927_audio_map,
> +               .num_dapm_routes = ARRAY_SIZE(max98927_audio_map),
> +       },
> +};
> +
> +static const struct regmap_config max98927_regmap = {
> +       .reg_bits         = 16,
> +       .val_bits         = 8,
> +       .max_register     = MAX98927_R01FF_REV_ID,
> +       .reg_defaults     = max98927_reg,
> +       .num_reg_defaults = ARRAY_SIZE(max98927_reg),
> +       .readable_reg     = max98927_readable_register,
> +       .volatile_reg     = max98927_volatile_reg,
> +       .cache_type       = REGCACHE_RBTREE,
> +};
> +
> +static void max98927_slot_config(struct i2c_client *i2c,
> +       struct max98927_priv *max98927)
> +{
> +       int value;
> +
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "vmon-slot-no", &value))
> +               max98927->v_l_slot = value & 0xF;
> +       else
> +               max98927->v_l_slot = 0;
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "imon-slot-no", &value))
> +               max98927->i_l_slot = value & 0xF;
> +       else
> +               max98927->i_l_slot = 1;
> +}
> +
> +static int max98927_i2c_probe(struct i2c_client *i2c,
> +       const struct i2c_device_id *id)
> +{
> +
> +       int ret = 0, value;
> +       int reg = 0;
> +       struct max98927_priv *max98927 = NULL;
> +
> +       max98927 = devm_kzalloc(&i2c->dev,
> +               sizeof(*max98927), GFP_KERNEL);
> +
> +       if (!max98927) {
> +               ret = -ENOMEM;
> +               return ret;
> +       }
> +       i2c_set_clientdata(i2c, max98927);
> +
> +       /* update interleave mode info */
> +       if (!of_property_read_u32(i2c->dev.of_node,
> +               "interleave_mode", &value)) {
> +               if (value > 0)
> +                       max98927->interleave_mode = 1;
> +               else
> +                       max98927->interleave_mode = 0;
> +       } else
> +               max98927->interleave_mode = 0;
> +
> +       /* regmap initialization */
> +       max98927->regmap
> +               = devm_regmap_init_i2c(i2c, &max98927_regmap);
> +       if (IS_ERR(max98927->regmap)) {
> +               ret = PTR_ERR(max98927->regmap);
> +               dev_err(&i2c->dev,
> +                       "Failed to allocate regmap: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* Check Revision ID */
> +       ret = regmap_read(max98927->regmap,
> +               MAX98927_R01FF_REV_ID, &reg);
> +       if (ret < 0) {
> +               dev_err(&i2c->dev,
> +                       "Failed to read: 0x%02X\n", MAX98927_R01FF_REV_ID);
> +               return ret;
> +       }
> +       dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n", reg);
> +
> +       /* voltage/current slot configuration */
> +       max98927_slot_config(i2c, max98927);
> +
> +       /* codec registeration */
> +       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927,
> +               max98927_dai, ARRAY_SIZE(max98927_dai));
> +       if (ret < 0)
> +               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static int max98927_i2c_remove(struct i2c_client *client)
> +{
> +       snd_soc_unregister_codec(&client->dev);
> +       return 0;
> +}
> +
> +static const struct i2c_device_id max98927_i2c_id[] = {
> +       { "max98927", 0},
> +       { },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id max98927_of_match[] = {
> +       { .compatible = "maxim,max98927", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, max98927_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id max98927_acpi_match[] = {
> +       { "MX98927", 0 },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(acpi, max98927_acpi_match);
> +#endif
> +
> +static struct i2c_driver max98927_i2c_driver = {
> +       .driver = {
> +               .name = "max98927",
> +               .of_match_table = of_match_ptr(max98927_of_match),
> +               .acpi_match_table = ACPI_PTR(max98927_acpi_match),
> +               .pm = NULL,
> +       },
> +       .probe  = max98927_i2c_probe,
> +       .remove = max98927_i2c_remove,
> +       .id_table = max98927_i2c_id,
> +};
> +
> +module_i2c_driver(max98927_i2c_driver)
> +
> +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver");
> +MODULE_AUTHOR("Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h
> new file mode 100644
> index 000000000000..ece6a608cbe1
> --- /dev/null
> +++ b/sound/soc/codecs/max98927.h
> @@ -0,0 +1,272 @@
> +/*
> + * max98927.h  --  MAX98927 ALSA Soc Audio driver
> + *
> + * Copyright 2013-15 Maxim Integrated Products
> + * Author: Ryan Lee <ryans.lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + */
> +#ifndef _MAX98927_H
> +#define _MAX98927_H
> +
> +/* Register Values */
> +#define MAX98927_R0001_INT_RAW1 0x0001
> +#define MAX98927_R0002_INT_RAW2 0x0002
> +#define MAX98927_R0003_INT_RAW3 0x0003
> +#define MAX98927_R0004_INT_STATE1 0x0004
> +#define MAX98927_R0005_INT_STATE2 0x0005
> +#define MAX98927_R0006_INT_STATE3 0x0006
> +#define MAX98927_R0007_INT_FLAG1 0x0007
> +#define MAX98927_R0008_INT_FLAG2 0x0008
> +#define MAX98927_R0009_INT_FLAG3 0x0009
> +#define MAX98927_R000A_INT_EN1 0x000A
> +#define MAX98927_R000B_INT_EN2 0x000B
> +#define MAX98927_R000C_INT_EN3 0x000C
> +#define MAX98927_R000D_INT_FLAG_CLR1   0x000D
> +#define MAX98927_R000E_INT_FLAG_CLR2   0x000E
> +#define MAX98927_R000F_INT_FLAG_CLR3   0x000F
> +#define MAX98927_R0010_IRQ_CTRL 0x0010
> +#define MAX98927_R0011_CLK_MON 0x0011
> +#define MAX98927_R0012_WDOG_CTRL 0x0012
> +#define MAX98927_R0013_WDOG_RST 0x0013
> +#define MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH 0x0014
> +#define MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH 0x0015
> +#define MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS 0x0016
> +#define MAX98927_R0017_PIN_CFG 0x0017
> +#define MAX98927_R0018_PCM_RX_EN_A 0x0018
> +#define MAX98927_R0019_PCM_RX_EN_B 0x0019
> +#define MAX98927_R001A_PCM_TX_EN_A 0x001A
> +#define MAX98927_R001B_PCM_TX_EN_B 0x001B
> +#define MAX98927_R001C_PCM_TX_HIZ_CTRL_A 0x001C
> +#define MAX98927_R001D_PCM_TX_HIZ_CTRL_B 0x001D
> +#define MAX98927_R001E_PCM_TX_CH_SRC_A 0x001E
> +#define MAX98927_R001F_PCM_TX_CH_SRC_B 0x001F
> +#define MAX98927_R0020_PCM_MODE_CFG 0x0020
> +#define MAX98927_R0021_PCM_MASTER_MODE 0x0021
> +#define MAX98927_R0022_PCM_CLK_SETUP 0x0022
> +#define MAX98927_R0023_PCM_SR_SETUP1 0x0023
> +#define MAX98927_R0024_PCM_SR_SETUP2   0x0024
> +#define MAX98927_R0025_PCM_TO_SPK_MONOMIX_A 0x0025
> +#define MAX98927_R0026_PCM_TO_SPK_MONOMIX_B 0x0026
> +#define MAX98927_R0027_ICC_RX_EN_A 0x0027
> +#define MAX98927_R0028_ICC_RX_EN_B 0x0028
> +#define MAX98927_R002B_ICC_TX_EN_A 0x002B
> +#define MAX98927_R002C_ICC_TX_EN_B 0x002C
> +#define MAX98927_R002E_ICC_HIZ_MANUAL_MODE 0x002E
> +#define MAX98927_R002F_ICC_TX_HIZ_EN_A 0x002F
> +#define MAX98927_R0030_ICC_TX_HIZ_EN_B 0x0030
> +#define MAX98927_R0031_ICC_LNK_EN 0x0031
> +#define MAX98927_R0032_PDM_TX_EN 0x0032
> +#define MAX98927_R0033_PDM_TX_HIZ_CTRL 0x0033
> +#define MAX98927_R0034_PDM_TX_CTRL 0x0034
> +#define MAX98927_R0035_PDM_RX_CTRL 0x0035
> +#define MAX98927_R0036_AMP_VOL_CTRL 0x0036
> +#define MAX98927_R0037_AMP_DSP_CFG 0x0037
> +#define MAX98927_R0038_TONE_GEN_DC_CFG 0x0038
> +#define MAX98927_R0039_DRE_CTRL 0x0039
> +#define MAX98927_R003A_AMP_EN 0x003A
> +#define MAX98927_R003B_SPK_SRC_SEL 0x003B
> +#define MAX98927_R003C_SPK_GAIN 0x003C
> +#define MAX98927_R003D_SSM_CFG 0x003D
> +#define MAX98927_R003E_MEAS_EN 0x003E
> +#define MAX98927_R003F_MEAS_DSP_CFG 0x003F
> +#define MAX98927_R0040_BOOST_CTRL0 0x0040
> +#define MAX98927_R0041_BOOST_CTRL3 0x0041
> +#define MAX98927_R0042_BOOST_CTRL1 0x0042
> +#define MAX98927_R0043_MEAS_ADC_CFG 0x0043
> +#define MAX98927_R0044_MEAS_ADC_BASE_MSB 0x0044
> +#define MAX98927_R0045_MEAS_ADC_BASE_LSB 0x0045
> +#define MAX98927_R0046_ADC_CH0_DIVIDE 0x0046
> +#define MAX98927_R0047_ADC_CH1_DIVIDE 0x0047
> +#define MAX98927_R0048_ADC_CH2_DIVIDE 0x0048
> +#define MAX98927_R0049_ADC_CH0_FILT_CFG 0x0049
> +#define MAX98927_R004A_ADC_CH1_FILT_CFG 0x004A
> +#define MAX98927_R004B_ADC_CH2_FILT_CFG 0x004B
> +#define MAX98927_R004C_MEAS_ADC_CH0_READ 0x004C
> +#define MAX98927_R004D_MEAS_ADC_CH1_READ 0x004D
> +#define MAX98927_R004E_MEAS_ADC_CH2_READ 0x004E
> +#define MAX98927_R0051_BROWNOUT_STATUS 0x0051
> +#define MAX98927_R0052_BROWNOUT_EN 0x0052
> +#define MAX98927_R0053_BROWNOUT_INFINITE_HOLD 0x0053
> +#define MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR 0x0054
> +#define MAX98927_R0055_BROWNOUT_LVL_HOLD 0x0055
> +#define MAX98927_R005A_BROWNOUT_LVL1_THRESH 0x005A
> +#define MAX98927_R005B_BROWNOUT_LVL2_THRESH 0x005B
> +#define MAX98927_R005C_BROWNOUT_LVL3_THRESH 0x005C
> +#define MAX98927_R005D_BROWNOUT_LVL4_THRESH 0x005D
> +#define MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS 0x005E
> +#define MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL 0x005F
> +#define MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL 0x0060
> +#define MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE 0x0061
> +#define MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 0x0072
> +#define MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1 0x0073
> +#define MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2 0x0074
> +#define MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3 0x0075
> +#define MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT 0x0076
> +#define MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1 0x0077
> +#define MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2 0x0078
> +#define MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3 0x0079
> +#define MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT 0x007A
> +#define MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1 0x007B
> +#define MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2 0x007C
> +#define MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3 0x007D
> +#define MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT 0x007E
> +#define MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1 0x007F
> +#define MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2 0x0080
> +#define MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3 0x0081
> +#define MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM 0x0082
> +#define MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY 0x0083
> +#define MAX98927_R0084_ENV_TRACK_REL_RATE 0x0084
> +#define MAX98927_R0085_ENV_TRACK_HOLD_RATE 0x0085
> +#define MAX98927_R0086_ENV_TRACK_CTRL 0x0086
> +#define MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ 0x0087
> +#define MAX98927_R00FF_GLOBAL_SHDN 0x00FF
> +#define MAX98927_R0100_SOFT_RESET 0x0100
> +#define MAX98927_R01FF_REV_ID 0x01FF
> +
> +/* MAX98927_R0018_PCM_RX_EN_A */
> +#define MAX98927_PCM_RX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_RX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_RX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_RX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_RX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_RX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_RX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_RX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001A_PCM_TX_EN_A */
> +#define MAX98927_PCM_TX_CH0_EN (0x1 << 0)
> +#define MAX98927_PCM_TX_CH1_EN (0x1 << 1)
> +#define MAX98927_PCM_TX_CH2_EN (0x1 << 2)
> +#define MAX98927_PCM_TX_CH3_EN (0x1 << 3)
> +#define MAX98927_PCM_TX_CH4_EN (0x1 << 4)
> +#define MAX98927_PCM_TX_CH5_EN (0x1 << 5)
> +#define MAX98927_PCM_TX_CH6_EN (0x1 << 6)
> +#define MAX98927_PCM_TX_CH7_EN (0x1 << 7)
> +
> +/* MAX98927_R001E_PCM_TX_CH_SRC_A */
> +#define MAX98927_PCM_TX_CH_SRC_A_V_SHIFT (0)
> +#define MAX98927_PCM_TX_CH_SRC_A_I_SHIFT (4)
> +
> +/* MAX98927_R001F_PCM_TX_CH_SRC_B */
> +#define MAX98927_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 5)
> +
> +/* MAX98927_R0020_PCM_MODE_CFG */
> +#define MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
> +#define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3)
> +#define MAX98927_PCM_FORMAT_I2S (0x0 << 0)
> +#define MAX98927_PCM_FORMAT_LJ (0x1 << 0)
> +
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
> +#define MAX98927_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
> +
> +/* MAX98927_R0021_PCM_MASTER_MODE */
> +#define MAX98927_PCM_MASTER_MODE_MASK (0x3 << 0)
> +#define MAX98927_PCM_MASTER_MODE_SLAVE (0x0 << 0)
> +#define MAX98927_PCM_MASTER_MODE_MASTER (0x3 << 0)
> +
> +#define MAX98927_PCM_MASTER_MODE_MCLK_MASK (0xF << 2)
> +#define MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2)
> +
> +/* MAX98927_R0022_PCM_CLK_SETUP */
> +#define MAX98927_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
> +
> +/* MAX98927_R0023_PCM_SR_SETUP1 */
> +#define MAX98927_PCM_SR_SET1_SR_MASK (0xF << 0)
> +
> +#define MAX98927_PCM_SR_SET1_SR_8000 (0x0 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_11025 (0x1 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_12000 (0x2 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_16000 (0x3 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_22050 (0x4 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_24000 (0x5 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_32000 (0x6 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_44100 (0x7 << 0)
> +#define MAX98927_PCM_SR_SET1_SR_48000 (0x8 << 0)
> +
> +/* MAX98927_R0024_PCM_SR_SETUP2 */
> +#define MAX98927_PCM_SR_SET2_SR_MASK (0xF << 4)
> +#define MAX98927_PCM_SR_SET2_SR_SHIFT (4)
> +#define MAX98927_PCM_SR_SET2_IVADC_SR_MASK (0xf << 0)
> +
> +/* MAX98927_R0025_PCM_TO_SPK_MONOMIX_A */
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
> +#define MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
> +
> +/* MAX98927_R0035_PDM_RX_CTRL */
> +#define MAX98927_PDM_RX_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R0036_AMP_VOL_CTRL */
> +#define MAX98927_AMP_VOL_SEL (0x1 << 7)
> +#define MAX98927_AMP_VOL_SEL_WIDTH (1)
> +#define MAX98927_AMP_VOL_SEL_SHIFT (7)
> +#define MAX98927_AMP_VOL_MASK (0x7f << 0)
> +#define MAX98927_AMP_VOL_WIDTH (7)
> +#define MAX98927_AMP_VOL_SHIFT (0)
> +
> +/* MAX98927_R0037_AMP_DSP_CFG */
> +#define MAX98927_AMP_DSP_CFG_DCBLK_EN (0x1 << 0)
> +#define MAX98927_AMP_DSP_CFG_DITH_EN (0x1 << 1)
> +#define MAX98927_AMP_DSP_CFG_RMP_BYPASS (0x1 << 4)
> +#define MAX98927_AMP_DSP_CFG_DAC_INV (0x1 << 5)
> +#define MAX98927_AMP_DSP_CFG_RMP_SHIFT (4)
> +
> +/* MAX98927_R0039_DRE_CTRL */
> +#define MAX98927_DRE_CTRL_DRE_EN       (0x1 << 0)
> +#define MAX98927_DRE_EN_SHIFT 0x1
> +
> +/* MAX98927_R003A_AMP_EN */
> +#define MAX98927_AMP_EN_MASK (0x1 << 0)
> +
> +/* MAX98927_R003B_SPK_SRC_SEL */
> +#define MAX98927_SPK_SRC_MASK (0x3 << 0)
> +
> +/* MAX98927_R003C_SPK_GAIN */
> +#define MAX98927_SPK_PCM_GAIN_MASK (0x7 << 0)
> +#define MAX98927_SPK_PDM_GAIN_MASK (0x7 << 4)
> +#define MAX98927_SPK_GAIN_WIDTH (3)
> +
> +/* MAX98927_R003E_MEAS_EN */
> +#define MAX98927_MEAS_V_EN (0x1 << 0)
> +#define MAX98927_MEAS_I_EN (0x1 << 1)
> +
> +/* MAX98927_R0040_BOOST_CTRL0 */
> +#define MAX98927_BOOST_CTRL0_VOUT_MASK (0x1f << 0)
> +#define MAX98927_BOOST_CTRL0_PVDD_MASK (0x1 << 7)
> +#define MAX98927_BOOST_CTRL0_PVDD_EN_SHIFT (7)
> +
> +/* MAX98927_R0052_BROWNOUT_EN */
> +#define MAX98927_BROWNOUT_BDE_EN (0x1 << 0)
> +#define MAX98927_BROWNOUT_AMP_EN (0x1 << 1)
> +#define MAX98927_BROWNOUT_DSP_EN (0x1 << 2)
> +#define MAX98927_BROWNOUT_DSP_SHIFT (2)
> +
> +/* MAX98927_R0100_SOFT_RESET */
> +#define MAX98927_SOFT_RESET (0x1 << 0)
> +
> +/* MAX98927_R00FF_GLOBAL_SHDN */
> +#define MAX98927_GLOBAL_EN_MASK (0x1 << 0)
> +
> +struct max98927_priv {
> +       struct regmap *regmap;
> +       struct snd_soc_codec *codec;
> +       struct max98927_pdata *pdata;
> +       unsigned int spk_gain;
> +       unsigned int sysclk;
> +       unsigned int v_l_slot;
> +       unsigned int i_l_slot;
> +       bool interleave_mode;
> +       unsigned int ch_size;
> +       unsigned int rate;
> +       unsigned int iface;
> +       unsigned int master;
> +       unsigned int digital_gain;
> +};
> +#endif
> --
> 2.11.0
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 2/2] fpga: lattice machxo2: Add Lattice MachXO2 support
From: Alan Tull @ 2017-04-25 15:59 UTC (permalink / raw)
  To: Paolo Pisati
  Cc: Rob Herring, Mark Rutland, Alan Tull, Moritz Fischer,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA, linux-kernel
In-Reply-To: <1492960845-342-3-git-send-email-p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Sun, Apr 23, 2017 at 10:20 AM, Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hi Paolo,

Thanks for submitting your driver.  A few things...

> Add support for the Lattice MachXO2 FPGA chip in Slave SPI configuration.
>

Please add a bit of a description here.  Format should be subject
line, skip a line,  description, skip a line, then your signoff.

> Signed-off-by: Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/fpga/Kconfig       |   7 ++
>  drivers/fpga/Makefile      |   1 +
>  drivers/fpga/machxo2-spi.c | 199 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 207 insertions(+)
>  create mode 100644 drivers/fpga/machxo2-spi.c
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index c81cb7d..cce135b 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -26,6 +26,13 @@ config FPGA_MGR_ICE40_SPI
>         help
>           FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
>
> +config FPGA_MGR_MACHXO2_SPI
> +       tristate "Lattice MachXO2 SPI"
> +       depends on SPI
> +       help
> +        FPGA manager driver support for Lattice MachXO2 configuration
> +        over slave SPI interface.
> +
>  config FPGA_MGR_SOCFPGA
>         tristate "Altera SOCFPGA FPGA Manager"
>         depends on ARCH_SOCFPGA || COMPILE_TEST
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index c6f5d74..cdab1fe 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_FPGA)                      += fpga-mgr.o
>
>  # FPGA Manager Drivers
>  obj-$(CONFIG_FPGA_MGR_ICE40_SPI)       += ice40-spi.o
> +obj-$(CONFIG_FPGA_MGR_MACHXO2_SPI)     += machxo2-spi.o
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA)         += socfpga.o
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)     += socfpga-a10.o
>  obj-$(CONFIG_FPGA_MGR_TS73XX)          += ts73xx-fpga.o
> diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c
> new file mode 100644
> index 0000000..5ee56bd
> --- /dev/null
> +++ b/drivers/fpga/machxo2-spi.c
> @@ -0,0 +1,199 @@
> +/**
> + * Lattice MachXO2 Slave SPI Driver
> + *
> + * Copyright (C) 2017 Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * Manage Lattice FPGA firmware that is loaded over SPI using
> + * the slave serial configuration interface.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/spi/spi.h>
> +
> +

Please run checkpatch and fix whatever it points out, such as not to
use double blank lines.

> +/* MachXO2 Programming Guide - sysCONFIG Programming Commands */
> +
> +#define ISC_ENABLE             0x000008c6
> +#define ISC_ERASE              0x0000040e
> +#define ISC_PROGRAMDONE                0x0000005e
> +#define LSC_CHECKBUSY          0x000000f0
> +#define LSC_INITADDRESS                0x00000046
> +#define LSC_PROGINCRNV         0x01000070
> +#define LSC_REFRESH            0x00000079
> +
> +/*
> + * Max CCLK in Slave SPI mode according to 'MachXO2 Family Data
> + * Sheet' sysCONFIG Port Timing Specifications (3-36)
> + */
> +#define MACHXO2_MAX_SPEED      66000000
> +
> +#define MACHXO2_LOW_DELAY      5       /* us */
> +#define MACHXO2_HIGH_DELAY     200     /* us */
> +
> +#define MACHXO2_OP_SIZE                sizeof(uint32_t)
> +#define MACHXO2_PAGE_SIZE      16
> +#define MACHXO2_BUF_SIZE       (MACHXO2_OP_SIZE + MACHXO2_PAGE_SIZE)
> +
> +
> +static int waituntilnotbusy(struct spi_device *spi)

Could you rename to something like wait_until_not_busy?

> +{
> +       uint8_t rx, busyflag = 0x80;

Please create a macro for the 0x80 value and use it here.

> +       uint32_t checkbusy = LSC_CHECKBUSY;

Another checkpatch: u32 is preferred over uint32_t.

> +
> +       do {
> +               if (spi_write_then_read(spi, &checkbusy, MACHXO2_OP_SIZE,
> +                                         &rx, sizeof(rx)))
> +                       return -EIO;

Please pass down the spi_write_then_read error code like:

ret = spi_write_then_read(...);
if (ret)
        return ret;

There's a few places below where I will point that out for spi_write as well.

> +       } while (rx & busyflag);

Skip a line before the return.

> +       return 0;
> +}
> +
> +static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr)
> +{
> +       return FPGA_MGR_STATE_UNKNOWN;
> +}
> +
> +static int machxo2_write_init(struct fpga_manager *mgr,
> +                             struct fpga_image_info *info,
> +                             const char *buf, size_t count)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t enable = ISC_ENABLE;
> +       uint32_t erase = ISC_ERASE;
> +       uint32_t initaddr = LSC_INITADDRESS;
> +
> +       if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
> +               dev_err(&mgr->dev,
> +                       "Partial reconfiguration is not supported\n");
> +               return -ENOTSUPP;
> +       }
> +
> +       if (spi_write(spi, &enable, MACHXO2_OP_SIZE))
> +               goto fail;

Please skip a line here.

> +       udelay(MACHXO2_LOW_DELAY);
> +       if (spi_write(spi, &erase, MACHXO2_OP_SIZE))
> +               goto fail;

Again, it's better to pass the spi_write error code.

ret = spi_write(...)
if (ret)
     goto fail;

Then skip a line.

> +       waituntilnotbusy(spi);
> +       if (spi_write(spi, &initaddr, MACHXO2_OP_SIZE))
> +               goto fail;

Pass through the error code, same as above.

> +       return 0;
> +
> +fail:
> +       dev_err(&mgr->dev, "Error during FPGA init.\n");
> +       return -EIO;

return ret;

> +}
> +
> +static int machxo2_write(struct fpga_manager *mgr, const char *buf,
> +                        size_t count)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t progincr = LSC_PROGINCRNV;
> +       uint8_t payload[MACHXO2_BUF_SIZE];
> +       int i;
> +
> +       if (count % MACHXO2_PAGE_SIZE != 0) {
> +               dev_err(&mgr->dev, "Malformed payload.\n");
> +               return -EINVAL;
> +       }
> +
> +       memcpy(payload, &progincr, MACHXO2_OP_SIZE);
> +       for (i = 0; i < count; i += MACHXO2_PAGE_SIZE) {
> +               memcpy(&payload[MACHXO2_OP_SIZE], &buf[i], MACHXO2_PAGE_SIZE);
> +               if (spi_write(spi, payload, MACHXO2_BUF_SIZE)) {
> +                       dev_err(&mgr->dev, "Error loading the bitstream.\n");
> +                       return -EIO;

Pass through spi_write error code.

> +               }
> +               udelay(MACHXO2_HIGH_DELAY);
> +       }
> +
> +       return 0;
> +}
> +
> +static int machxo2_write_complete(struct fpga_manager *mgr,
> +                                 struct fpga_image_info *info)
> +{
> +       struct spi_device *spi = mgr->priv;
> +       uint32_t progdone = ISC_PROGRAMDONE;
> +       uint32_t refresh = LSC_REFRESH;
> +
> +       if (spi_write(spi, &progdone, MACHXO2_OP_SIZE))
> +               goto fail;

Pass spi_write error code if error.  And skip a line.

> +       /* yep, LSC_REFRESH is 3 bytes long actually */
> +       if (spi_write(spi, &refresh, MACHXO2_OP_SIZE-1))
> +               goto fail;

Here too.  Also add spaces around the minus sign.

> +       return 0;
> +
> +fail:
> +       dev_err(&mgr->dev, "Refresh failed.\n");
> +       return -EIO;

Will be return ret;

> +}
> +
> +static const struct fpga_manager_ops machxo2_ops = {
> +       .state = machxo2_spi_state,
> +       .write_init = machxo2_write_init,
> +       .write = machxo2_write,
> +       .write_complete = machxo2_write_complete,
> +};
> +
> +static int machxo2_spi_probe(struct spi_device *spi)
> +{
> +       struct device *dev = &spi->dev;
> +       int ret = 0;
> +
> +       if (spi->max_speed_hz > MACHXO2_MAX_SPEED) {
> +               dev_err(dev, "Speed is too high\n");
> +               return -EINVAL;
> +       }
> +
> +       ret =  fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
> +                                &machxo2_ops, spi);
> +       if (ret)
> +               dev_err(dev, "Unable to register FPGA manager");

You can just 'return fpga_mgr_register(...);' here.

> +
> +       return ret;
> +}
> +
> +static int machxo2_spi_remove(struct spi_device *spi)
> +{
> +       struct device *dev = &spi->dev;
> +
> +       fpga_mgr_unregister(dev);

Skip  a line.

> +       return 0;
> +}
> +
> +static const struct of_device_id of_match[] = {
> +       { .compatible = "lattice,machxo2-slave-spi", },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, of_match);
> +
> +static const struct spi_device_id lattice_ids[] = {
> +       { "machxo2-slave-spi", 0 },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(spi, lattice_ids);
> +
> +static struct spi_driver machxo2_spi_driver = {
> +       .driver = {
> +               .name = "machxo2-slave-spi",
> +               .owner = THIS_MODULE,

You don't need to specify THIS_MODULE here.  spi_register_driver will
add that for you.

> +               .of_match_table = of_match_ptr(of_match),
> +       },
> +       .probe = machxo2_spi_probe,
> +       .remove = machxo2_spi_remove,
> +       .id_table = lattice_ids,
> +};
> +
> +module_spi_driver(machxo2_spi_driver)
> +
> +MODULE_AUTHOR("Paolo Pisati <p.pisati-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
> +MODULE_DESCRIPTION("Load Lattice FPGA firmware over SPI");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Thanks,
Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 15/18] dt-bindings: sound: Add bindings for Cirrus Logic Madera codecs
From: Mark Brown @ 2017-04-25 15:52 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: gnurou, alsa-devel, jason, devicetree, linus.walleij, patches,
	linux-kernel, linux-gpio, robh+dt, tglx, lee.jones
In-Reply-To: <1493050124-5970-16-git-send-email-rf@opensource.wolfsonmicro.com>


[-- Attachment #1.1: Type: text/plain, Size: 1090 bytes --]

On Mon, Apr 24, 2017 at 05:08:41PM +0100, Richard Fitzgerald wrote:
> The Cirrus Logic Madera codecs are a family of related codecs with
> extensive digital and analogue I/O, digital mixing and routing,
> signal processing and programmable DSPs.

Please submit patches using subject lines reflecting the style for the
subsystem.  This makes it easier for people to identify relevant
patches.  Look at what existing commits in the area you're changing are
doing and make sure your subject lines visually resemble what they're
doing.

> +Required properties:
> +  - compatible : One of the following chip-specific strings:
> +        "cirrus,cs47l35-codec"
> +        "cirrus,cs47l85-codec"
> +        "cirrus,cs47l90-codec"

You shouldn't have compatible strings for subfunctions of a MFD unless
these represent meaningful reusable IPs that can exist separately from
the parent chip, that's clearly not the case here.  All you're doing
here is encoding Linux internal abstractions which aren't OS neutral and
might change in future (for example clocking might move more into the
clock API).

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Applied "spi-imx: Implements handling of the SPI_READY mode flag." to the spi tree
From: Mark Brown @ 2017-04-25 15:46 UTC (permalink / raw)
  To: Leif Middelschulte; +Cc: Leif Middelschulte, Mark Brown
In-Reply-To: <20170423191958.32724-1-Leif.Middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

The patch

   spi-imx: Implements handling of the SPI_READY mode flag.

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From f72efa7e690ab5c4068ccba31c4da032bc45c29c Mon Sep 17 00:00:00 2001
From: Leif Middelschulte <leif.middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Sun, 23 Apr 2017 21:19:58 +0200
Subject: [PATCH] spi-imx: Implements handling of the SPI_READY mode flag.

This patch implements consideration of the SPI_READY mode flag as
defined in spi.h. It extends the device tree bindings to support
the values defined by the reference manual for the DRCTL field.

Thus supporting edge-triggered and level-triggered bursts.

Signed-off-by: Leif Middelschulte <Leif.Middelschulte-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/spi/fsl-imx-cspi.txt         |  7 +++++++
 drivers/spi/spi-imx.c                                | 20 ++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
index 8bc95e2fc47f..31b5b21598ff 100644
--- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -23,6 +23,12 @@ See the clock consumer binding,
 Obsolete properties:
 - fsl,spi-num-chipselects : Contains the number of the chipselect
 
+Optional properties:
+- fsl,spi-rdy-drctl: Integer, representing the value of DRCTL, the register
+controlling the SPI_READY handling. Note that to enable the DRCTL consideration,
+the SPI_READY mode-flag needs to be set too.
+Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst).
+
 Example:
 
 ecspi@70010000 {
@@ -35,4 +41,5 @@ ecspi@70010000 {
 		   <&gpio3 25 0>; /* GPIO3_25 */
 	dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
 	dma-names = "rx", "tx";
+	fsl,spi-rdy-drctl = <1>;
 };
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9a7c62f471dc..b402530a7a9a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -95,6 +95,7 @@ struct spi_imx_data {
 	unsigned int spi_bus_clk;
 
 	unsigned int bytes_per_word;
+	unsigned int spi_drctl;
 
 	unsigned int count;
 	void (*tx)(struct spi_imx_data *);
@@ -246,6 +247,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_CTRL_XCH		(1 <<  2)
 #define MX51_ECSPI_CTRL_SMC		(1 << 3)
 #define MX51_ECSPI_CTRL_MODE_MASK	(0xf << 4)
+#define MX51_ECSPI_CTRL_DRCTL(drctl)	((drctl) << 16)
 #define MX51_ECSPI_CTRL_POSTDIV_OFFSET	8
 #define MX51_ECSPI_CTRL_PREDIV_OFFSET	12
 #define MX51_ECSPI_CTRL_CS(cs)		((cs) << 18)
@@ -355,6 +357,12 @@ static int mx51_ecspi_config(struct spi_device *spi,
 	 */
 	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
+	/*
+	 * Enable SPI_RDY handling (falling edge/level triggered).
+	 */
+	if (spi->mode & SPI_READY)
+		ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
+
 	/* set clock speed */
 	ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk);
 	spi_imx->spi_bus_clk = clk;
@@ -1173,7 +1181,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct spi_imx_data *spi_imx;
 	struct resource *res;
-	int i, ret, irq;
+	int i, ret, irq, spi_drctl;
 
 	if (!np && !mxc_platform_info) {
 		dev_err(&pdev->dev, "can't get the platform data\n");
@@ -1181,6 +1189,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+	ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl);
+	if ((ret < 0) || (spi_drctl >= 0x3)) {
+		/* '11' is reserved */
+		spi_drctl = 0;
+	}
+
 	if (!master)
 		return -ENOMEM;
 
@@ -1216,7 +1230,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
 	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx))
-		spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
+		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
+
+	spi_imx->spi_drctl = spi_drctl;
 
 	init_completion(&spi_imx->xfer_done);
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Jon Mason @ 2017-04-25 15:43 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Eric Anholt, Florian Fainelli, Vivien Didelot, Andrew Lunn,
	Network Development, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-arm-kernel, open list, BCM Kernel Feedback, Ray Jui,
	Scott Branden, Jon Mason
In-Reply-To: <44d0c48c-d80f-271e-0e19-ac87a53e2e53@cogentembedded.com>

On Tue, Apr 25, 2017 at 11:23 AM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Hello!
>
> On 04/25/2017 06:15 PM, Jon Mason wrote:
>
>>>> Cygnus has a single amac controller connected to the B53 switch with 2
>>>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>>>> the external ethernet jacks.
>
>
> [...]
>
>>>> Signed-off-by: Eric Anholt <eric@anholt.net>
>>>> ---
>>>>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 60
>>>> ++++++++++++++++++++++++++++++++++
>>>>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>>>>  2 files changed, 68 insertions(+)
>>>>
>>>> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi
>>>> b/arch/arm/boot/dts/bcm-cygnus.dtsi
>>>> index 009f1346b817..318899df9972 100644
>>>> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
>>>> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
>
> [...]
>>>>
>>>> @@ -295,6 +345,16 @@
>>>>                         status = "disabled";
>>>>                 };
>>>>
>>>> +               eth0: enet@18042000 {
>>>> +                       compatible = "brcm,amac";
>>>> +                       reg = <0x18042000 0x1000>,
>>>> +                             <0x18110000 0x1000>;
>>>> +                       reg-names = "amac_base", "idm_base";
>>>
>>>
>>>
>>>    I don't think "_base" suffixes are necessary here.
>>
>>
>> 100% necessary, per the driver.  See
>> drivers/net/ethernet/broadcom/bgmac-platform.c
>
>
>    I'd recommend to fix the driver/bindings then...

They're already in use in other device trees.  So, we'd need to
support backward compatibility on them, thus removing any real benefit
to changing them.


>
> MBR, Sergei
>

^ permalink raw reply

* [PATCH 3/3] drm/sun4i: backend: Clarify sun4i_backend_layer_enable debug message
From: Chen-Yu Tsai @ 2017-04-25 15:25 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170425152505.6796-1-wens-jdAy2FN1RRM@public.gmane.org>

sun4i_backend_layer_enable can be called to enable or disable a layer.
However the debug message always says "Enable", which is confusing.

This patch makes the debug message vary according to the enable state.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index e9eca057ff35..e53107418add 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -73,7 +73,8 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 {
 	u32 val;
 
-	DRM_DEBUG_DRIVER("Enabling layer %d\n", layer);
+	DRM_DEBUG_DRIVER("%sabling layer %d\n", enable ? "En" : "Dis",
+			 layer);
 
 	if (enable)
 		val = SUN4I_BACKEND_MODCTL_LAY_EN(layer);
-- 
2.11.0

^ permalink raw reply related

* [PATCH 2/3] drm/sun4i: Set TCON clock inside sun4i_tconX_mode_set
From: Chen-Yu Tsai @ 2017-04-25 15:25 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170425152505.6796-1-wens-jdAy2FN1RRM@public.gmane.org>

Currently we are configuring the TCON's dot clock or special clock
directly from the encoder mode_set functions. Since we already
provide mode_set helper functions for the TCON's 2 channels, we
can set the respective clock from those helpers, and reduce the
exposure of the TCON's internals.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_rgb.c  | 2 --
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 ++++++
 drivers/gpu/drm/sun4i/sun4i_tv.c   | 2 --
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 1147451eb993..51ece4c39d7e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -175,8 +175,6 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
 
 	sun4i_tcon0_mode_set(tcon, mode);
 
-	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
-
 	/* FIXME: This seems to be board specific */
 	clk_set_phase(tcon->dclk, 120);
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 8301389c411d..29fd829aa54c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -131,6 +131,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 	u8 clk_delay;
 	u32 val = 0;
 
+	/* Configure the dot clock */
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
 	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
@@ -206,6 +209,9 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 
 	WARN_ON(!tcon->quirks->has_channel_1);
 
+	/* Configure the dot clock */
+	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
+
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
 	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..542da220818b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -486,8 +486,6 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
 		      SUN4I_TVE_RESYNC_FIELD : 0));
 
 	regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0);
-
-	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
 }
 
 static struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
-- 
2.11.0

^ permalink raw reply related

* [PATCH 1/3] drm/sun4i: Drop unused tcon pointer
From: Chen-Yu Tsai @ 2017-04-25 15:25 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170425152505.6796-1-wens-jdAy2FN1RRM@public.gmane.org>

The sun4i DRM driver now uses 2 lists to track backends and tcons.
During the switch, the original tcon pointer was not removed.

As it is now unused, remove it, so other new drivers can't accidentally
use it.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---

As mentioned in the cover letter, please squash this into the patch

    drm/sun4i: Use lists to track registered display backends and TCONs

---
 drivers/gpu/drm/sun4i/sun4i_drv.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 835bdb5cc0c2..250c29017ef5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -20,7 +20,6 @@
 struct sun4i_drv {
 	struct list_head	backend_list;
 	struct list_head	tcon_list;
-	struct sun4i_tcon	*tcon;
 
 	struct drm_fbdev_cma	*fbdev;
 };
-- 
2.11.0

^ permalink raw reply related

* [PATCH 0/3] drm/sun4i: More cleanups and fixes
From: Chen-Yu Tsai @ 2017-04-25 15:25 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

Hi Maxime,

The subject is probably getting old. Here are a few more cleanups.

Patch 1 should have been part of the patch

    drm/sun4i: Use lists to track registered display backends and TCONs

from my multiple pipeline support series. Please squash it in if you can.

Patch 2 just moves setting the TCON clocks back inside the TCON driver.

Patch 3 cleans up a DRM driver debug message.

Regards
ChenYu


Chen-Yu Tsai (3):
  drm/sun4i: Drop unused tcon pointer
  drm/sun4i: Set TCON clock inside sun4i_tconX_mode_set
  drm/sun4i: backend: Clarify sun4i_backend_layer_enable debug message

 drivers/gpu/drm/sun4i/sun4i_backend.c | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_drv.h     | 1 -
 drivers/gpu/drm/sun4i/sun4i_rgb.c     | 2 --
 drivers/gpu/drm/sun4i/sun4i_tcon.c    | 6 ++++++
 drivers/gpu/drm/sun4i/sun4i_tv.c      | 2 --
 5 files changed, 8 insertions(+), 6 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Sergei Shtylyov @ 2017-04-25 15:23 UTC (permalink / raw)
  To: Jon Mason
  Cc: Mark Rutland, Andrew Lunn, Florian Fainelli, Scott Branden,
	Vivien Didelot, Jon Mason, Network Development, open list,
	Eric Anholt,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Herring, BCM Kernel Feedback, Ray Jui, linux-arm-kernel
In-Reply-To: <CAC3K-4qn5oCXvyMCkFESGqMHqHXGiNUW6wfRx2LUZ8qZ39qroQ@mail.gmail.com>

Hello!

On 04/25/2017 06:15 PM, Jon Mason wrote:

>>> Cygnus has a single amac controller connected to the B53 switch with 2
>>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>>> the external ethernet jacks.

[...]

>>> Signed-off-by: Eric Anholt <eric@anholt.net>
>>> ---
>>>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 60
>>> ++++++++++++++++++++++++++++++++++
>>>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>>>  2 files changed, 68 insertions(+)
>>>
>>> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi
>>> b/arch/arm/boot/dts/bcm-cygnus.dtsi
>>> index 009f1346b817..318899df9972 100644
>>> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
>>> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
[...]
>>> @@ -295,6 +345,16 @@
>>>                         status = "disabled";
>>>                 };
>>>
>>> +               eth0: enet@18042000 {
>>> +                       compatible = "brcm,amac";
>>> +                       reg = <0x18042000 0x1000>,
>>> +                             <0x18110000 0x1000>;
>>> +                       reg-names = "amac_base", "idm_base";
>>
>>
>>    I don't think "_base" suffixes are necessary here.
>
> 100% necessary, per the driver.  See
> drivers/net/ethernet/broadcom/bgmac-platform.c

    I'd recommend to fix the driver/bindings then...

MBR, Sergei

^ permalink raw reply

* Re: [PATCH v2 2/2] dmaengine: Add DW AXI DMAC driver
From: Eugeniy Paltsev @ 2017-04-25 15:16 UTC (permalink / raw)
  To: andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org
  Cc: vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	Alexey.Brodkin-HKixBCOQz3hWk0Htik3J/w@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Eugeniy.Paltsev-HKixBCOQz3hWk0Htik3J/w@public.gmane.org,
	linux-snps-arc-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1493052970.24567.168.camel-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 12167 bytes --]

On Mon, 2017-04-24 at 19:56 +0300, Andy Shevchenko wrote:
> On Mon, 2017-04-24 at 15:55 +0000, Eugeniy Paltsev wrote:
> > Hi,
> > On Fri, 2017-04-21 at 18:13 +0300, Andy Shevchenko wrote:
> > > On Fri, 2017-04-21 at 14:29 +0000, Eugeniy Paltsev wrote:
> > > > On Tue, 2017-04-18 at 15:31 +0300, Andy Shevchenko wrote:
> > > > > On Fri, 2017-04-07 at 17:04 +0300, Eugeniy Paltsev wrote:
> > > > > > This patch adds support for the DW AXI DMAC controller.
> > > > > > +static inline void
> > > > > > +axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32
> > > > > > val)
> > > > > > +{
> > > > > > +	iowrite32(val, chip->regs + reg);
> > > > >
> > > > > Are you going to use IO ports for this IP? I don't think so.
> > > > > Wouldn't be better to call readl()/writel() instead?
> > > >
> > > > As I understand, it's better to use ioread/iowrite as more
> > > > universal
> > > > IO
> > > > access way. Am I wrong?
> > >
> > > As I said above the ioreadX/iowriteX makes only sense when your
> > > IP
> > > would be accessed via IO region or MMIO. I'm pretty sure IO is
> > > not
> > > the case at all for this IP.
> >
> > MMIO? This IP works exactly via memory-mapped I/O.
>
> Yes, and why do you need to check this on each IO read/write?
> Please, switch to plain readX()/writeX() instead.
Ok, I'll switch to readX()/writeX().

> > > > > > +		val = axi_chan_ioread32(chan,
> > > > > > CH_INTSTATUS_ENA);
> > > > > > +		val &= ~irq_mask;
> > > > > > +		axi_chan_iowrite32(chan, CH_INTSTATUS_ENA,
> > > > > > val);
> > > > > > +	}
> > > > > > +
> > > > > > +	return min_t(size_t, __ffs(sdl), max_width);
> > > > > > +}
> > > > > > +static void axi_desc_put(struct axi_dma_desc *desc)
> > > > > > +{
> > > > > > +	struct axi_dma_chan *chan = desc->chan;
> > > > > > +	struct dw_axi_dma *dw = chan->chip->dw;
> > > > > > +	struct axi_dma_desc *child, *_next;
> > > > > > +	unsigned int descs_put = 0;
> > > > > > +	list_for_each_entry_safe(child, _next, &desc-
> > > > > > > xfer_list,
> > > > > >
> > > > > > xfer_list) {
> > > > >
> > > > > xfer_list looks redundant.
> > > > > Can you elaborate why virtual channel management is not
> > > > > working
> > > > > for
> > > > > you?
> > > >
> > > > Each virtual descriptor encapsulates several hardware
> > > > descriptors,
> > > > which belong to same transfer.
> > > > This list (xfer_list) is used only for allocating/freeing these
> > > > descriptors and it doesn't affect on virtual dma work logic.
> > > > I can see this approach in several drivers with VirtDMA (but
> > > > they
> > > > mostly use array instead of list)
> > >
> > > You described how most of the DMA drivers are implemented, though
> > > they
> > > are using just sg_list directly. I would recommend to do the same
> > > and
> > > get rid of this list.
> >
> > This IP can be (ans is) configured with small block size.
> > (note, that I am not saying about runtime HW configuration)
> >
> > And there is opportunity what we can't use sg_list directly and
> > need
> > to
> > split sg_list to a smaller chunks.
>
> That's what I have referred quite ago. The driver should provide an
> interface to tell potential caller what maximum block (number of
> items
> with given bus width) it supports.
>
> We have struct dma_parms in struct device, but what we actually need
> is
> to support similar on per channel basis in DMAengine framework.
>
> So, instead of working around this I recommend either to implement it
> properly or rely on the fact that in the future someone eventually
> does that for you.
>
> Each driver which has this re-splitting mechanism should be cleaned
> up and refactored.
I still can't see any pros of this implementation.
There is no performance profit: we anyway need to re-splitt sg_list
(but now in dma-user driver instead of dma driver)

If we want to use same descriptors several times we just can use
DMA_CTRL_REUSE option - the descriptors will be created one time and
re-splitting will be сompleted only one time.

But there are cons of this implementation:
we need to implement re-splitting mechanism in each place we use dma
instead of one dma driver. So there are more places for bugs and etc...

> > > > > Btw, are you planning to use priority at all? For now on I
> > > > > didn't
> > > > > see
> > > > > a single driver (from the set I have checked, like 4-5 of
> > > > > them)
> > > > > that
> > > > > uses priority anyhow. It makes driver more complex for
> > > > > nothing.
> > > >
> > > > Only for dma slave operations.
> > >
> > > So, in other words you *have* an actual two or more users that
> > > *need*
> > > prioritization?
> >
> > As I remember there was an idea to give higher priority to audio
> > dma
> > chanels.
>
> I don't see cyclic transfers support in the driver. So, I would
> suggest
> just drop entire prioritization for now. When it would be actual user
> one may start thinking of it.
> Just a rule of common sense: do not implement something which will
> have no user or solve non-existing problem.

Ok, I'll drop prioritization untill I implement cyclic transfers.

> > > > > As I said earlier dw_dmac is *bad* example of the (virtual
> > > > > channel
> > > > > based) DMA driver.
> > > > >
> > > > > I guess you may just fail the descriptor and don't pretend it
> > > > > has
> > > > > been processed successfully.
> > > >
> > > > What do you mean by saying "fail the descriptor"?
> > > > After I get error I cancel current transfer and free all
> > > > descriptors
> > > > from it (by calling vchan_cookie_complete).
> > > > I can't store error status in descriptor structure because it
> > > > will
> > > > be
> > > > freed by vchan_cookie_complete.
> > > > I can't store error status in channel structure because it will
> > > > be
> > > > overwritten by next transfer.
> > >
> > > Better not to pretend that it has been processed successfully.
> > > Don't
> > > call callback on it and set its status to DMA_ERROR (that's why
> > > descriptors in many drivers have dma_status field). When user
> > > asks for
> > > status (using cookie) the saved value would be returned until
> > > descriptor
> > > is active.
> > >
> > > Do you have some other workflow in mind?
> >
> > Hmm...
> > Do you mean I should left error descriptors in desc_issued list
> > or I should create another list (like desc_error) in my driver and
> > move
> > error descriptors to desc_error list?
> >
> > And when exactly should I free error descriptors?
> See below.
>
> > I checked hsu/hsu.c dma driver implementation:
> >   vdma descriptor is deleted from desc_issued list when transfer
> >   starts. When descriptor marked as error descriptor
> >   vchan_cookie_complete isn't called for this descriptor. And this
> >   descriptor isn't placed in any list. So error descriptors *never*
> >   will be freed.
> >   I don't actually like this approach.
>
> Descriptor is active until terminate_all() is called or new
> descriptor
> is supplied. So, the caller has a quite time to check on it.
>
> So, what's wrong on it by your opinion?

Hmm, this looks OK. (In my example (hsu/hsu.c driver) error descriptors
are not freed even after terminate_all is called)

> Of course, if you want to keep by some reason (should be stated what
> the reason in comment) erred descriptors, you can do that.

So, I'll create desc_error list and store failed descriptors in this
list until terminate_all() is called.
Is it OK implementation?

> > > > > > +static const struct dev_pm_ops dw_axi_dma_pm_ops = {
> > > > > > +	SET_RUNTIME_PM_OPS(axi_dma_runtime_suspend,
> > > > > > axi_dma_runtime_resume, NULL)
> > > > > > +};
> > > > >
> > > > > Have you tried to build with CONFIG_PM disabled?
> > > >
> > > > Yes.
> > > >
> > > > > I'm pretty sure you need __maybe_unused applied to your PM
> > > > > ops.
> > > >
> > > > I call axi_dma_runtime_suspend / axi_dma_runtime_resume even I
> > > > dont't
> > > > use PM.
> > > > (I call them in probe / remove function.)
> > >
> > > Hmm... I didn't check your ->probe() and ->remove(). Do you mean
> > > you
> > > call them explicitly by those names?
> > >
> > > If so, please don't do that. Use pm_runtime_*() instead. And...
> > >
> > > > So I don't need to declare them with __maybe_unused.
> > >
> > > ...in that case it's possible you have them defined but not used.
> > >
> >
> > From my ->probe() function:
> >
> > pm_runtime_get_noresume(chip->dev);
> > ret = axi_dma_runtime_resume(chip->dev);
> >
> > Firstly I only incrememt counter.
> > Secondly explicitly call my resume function.
> >
> > I call them explicitly because I need driver to work also without
> > Runtime PM. So I can't just call pm_runtime_get here instead of
> > pm_runtime_get_noresume + axi_dma_runtime_resume.
> >
> > Of course I can copy *all* code from axi_dma_runtime_resume
> > to ->probe() function, but I don't really like this idea.
>
> It looks like you need more time to investigate how runtime PM works
> from driver point of view, but you shouldn't call your PM callbacks
> directly without a really good reason (weird silicon bugs,
> architectural impediments). I don't think that is the case here.
>
There is a simple reason:
I had to do same actions in probe/remove as in
runtime_resume/runtime_suspend.
(like enabling clock, enabling dma)

If my driver is build with RUNTIME_PM this actions will be
automatically handled by runtime pm (clock and dma will be enabled
before using and disabled after using).
Otherwise, if my driver is build without RUNTIME_PM clock and dma will
be enabled only one time - when ->probe() is called.
So I use runtime_resume callback directly for this purpose (because if
my driver is build without RUNTIME_PM this callback wiil not be called
at all)

> > > > > > +	bool		is_paused;
> > > > >
> > > > > I still didn't get (already forgot) why you can't use
> > > > > dma_status
> > > > > instead for the active descriptor?
> > > >
> > > > As I said before, I checked several driver, which have status
> > > > variable
> > > > in their channel structure - it is used *only* for
> > > > determinating
> > > > is
> > > > channel paused or not. So there is no much sense in replacing
> > > > "is_paused" to "status" and I left "is_paused" variable
> > > > untouched.
> > >
> > > Not only (see above), the errored descriptor keeps that status.
> > >
> > > > (I described above why we can't use status in channel structure
> > > > for
> > > > error handling)
> > >
> > > Ah, I'm talking about descriptor.
> >
> > Again - PAUSED is per-channel flag. So, even if we have status
> > field
> > in
> > each descriptor, it is simpler to use one per-channel flag instead
> > of
> > plenty per-descriptor flags.
> > When we pausing/resuming dma channel it is simpler to set only one
> > flag
> > instead of writing DMA_PAUSED to *each* descriptor status field.
>
> What do you mean by "each"? I don't recall the driver which can
> handle
> more than one *active* descriptor per channel. Do you?
>
> In that case status of active descriptor == status of channel. That
> trick (I also already referred to earlier) is used in some drivers.

Ok, I'll recheck others implementation.

> > > I mean, who are the users of them? If it's only one module, there
> > > is
> > > no need to put them in header.
> >
> > Yes, only one module.
> > Should I move all this definitions to axi_dma_platform.c file and
> > rid
> > of both axi_dma_platform_reg.h and axi_dma_platform.h headers?
> Depends on your design.
>
> If it would be just one C module it might make sense to use driver.c
> and driver.h or just driver.c.
> I see several drivers in current linux-next that are using latter and
> some that are using former, and number of plain driver.c variant is
> bigger.

Ok.

--
 Eugeniy PaltsevN‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·zøœzÚÞz)í…æèw*\x1fjg¬±¨\x1e¶‰šŽŠÝ¢j.ïÛ°\½½MŽúgjÌæa×\x02››–' ™©Þ¢¸\f¢·¦j:+v‰¨ŠwèjØm¶Ÿÿ¾\a«‘êçzZ+ƒùšŽŠÝ¢j"ú!¶i

^ permalink raw reply

* Re: [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Jon Mason @ 2017-04-25 15:15 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Eric Anholt, Florian Fainelli, Vivien Didelot, Andrew Lunn,
	Network Development, Rob Herring, Mark Rutland,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-arm-kernel, open list, BCM Kernel Feedback, Ray Jui,
	Scott Branden, Jon Mason
In-Reply-To: <f870339f-2fa1-411d-5ce8-adbe8802d8a8-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>

On Tue, Apr 25, 2017 at 5:40 AM, Sergei Shtylyov
<sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org> wrote:
> Hello.
>
> On 4/25/2017 12:50 AM, Eric Anholt wrote:
>
>> Cygnus has a single amac controller connected to the B53 switch with 2
>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>> the external ethernet jacks.
>
>
>    My spell checker trips on "amac" and "ethernet" -- perhaps they need
> capitalization?
>
>> Signed-off-by: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> ---
>>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 60
>> ++++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>>  2 files changed, 68 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi
>> b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> index 009f1346b817..318899df9972 100644
>> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
>> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
>> @@ -142,6 +142,56 @@
>>                         interrupts = <0>;
>>                 };
>>
>> +               mdio: mdio@18002000 {
>> +                       compatible = "brcm,iproc-mdio";
>> +                       reg = <0x18002000 0x8>;
>> +                       #size-cells = <1>;
>> +                       #address-cells = <0>;
>> +
>> +                       gphy0: eth-gphy@0 {
>
>
>    The node anmes must be generic, the DT spec has standardized
> "ethernet-phy" name for this case.
>
>> +                               reg = <0>;
>> +                               max-speed = <1000>;
>> +                       };
>> +
>> +                       gphy1: eth-gphy@1 {
>> +                               reg = <1>;
>> +                               max-speed = <1000>;
>> +                       };
>> +               };
>
> [...]
>>
>> @@ -295,6 +345,16 @@
>>                         status = "disabled";
>>                 };
>>
>> +               eth0: enet@18042000 {
>> +                       compatible = "brcm,amac";
>> +                       reg = <0x18042000 0x1000>,
>> +                             <0x18110000 0x1000>;
>> +                       reg-names = "amac_base", "idm_base";
>
>
>    I don't think "_base" suffixes are necessary here.

100% necessary, per the driver.  See
drivers/net/ethernet/broadcom/bgmac-platform.c


>
> [...]
>
> MBR, Sergei
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox