Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v2] Extend pca9532 device tree support
From: Jacek Anaszewski @ 2017-04-06 19:00 UTC (permalink / raw)
  To: Pavel Machek, Felix Brack
  Cc: rpurdie-Fm38FmjxZ/leoWH0uzbU5w, mark.rutland-5wv7dgnIgG8,
	riku.voipio-X3B1VOXEql0, linux-leds-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170406155005.GA10363@amd>

Hi Pavel,

On 04/06/2017 05:50 PM, Pavel Machek wrote:
> Hi!
> 
>>> diff --git a/Documentation/devicetree/bindings/leds/leds-pca9532.txt b/Documentation/devicetree/bindings/leds/leds-pca9532.txt
>>> index 198f3ba..8374075 100644
>>> --- a/Documentation/devicetree/bindings/leds/leds-pca9532.txt
>>> +++ b/Documentation/devicetree/bindings/leds/leds-pca9532.txt
>>> @@ -17,6 +17,8 @@ Optional sub-node properties:
>>>  	- label: see Documentation/devicetree/bindings/leds/common.txt
>>>  	- type: Output configuration, see dt-bindings/leds/leds-pca9532.h (default NONE)
>>>  	- linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt
>>> +	- default-state: see Documentation/devicetree/bindings/leds/common.txt
>>> +	  This property is only valid for sub-nodes of type <PCA9532_TYPE_LED>.
>>>  
>>>  Example:
>>>    #include <dt-bindings/leds/leds-pca9532.h>
>>> @@ -33,6 +35,14 @@ Example:
>>>        label = "pca:green:power";
>>>        type = <PCA9532_TYPE_LED>;
>>>      };
>>> +    kernel-booting {
>>> +    	type = <PCA9532_TYPE_LED>;
>>> +    	default-state = "on";
>>> +    };
>>> +    sys-stat {
>>> +    	type = <PCA9532_TYPE_LED>;
>>> +    	default-state = "keep"; // don't touch, was set by U-Boot
>>> +    };
>>
>> Adjusted above indentation to match the preceding lines.
> 
>>> @@ -475,6 +494,16 @@ pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
>>>  		of_property_read_u32(child, "type", &pdata->leds[i].type);
>>>  		of_property_read_string(child, "linux,default-trigger",
>>>  					&pdata->leds[i].default_trigger);
>>> +		if (!of_property_read_string(child, "default-state", &state)) {
>>> +			if (!strcmp(state, "on"))
>>> +				pdata->leds[i].state = PCA9532_ON;
>>> +			else if (!strcmp(state, "keep"))
>>> +				pdata->leds[i].state = PCA9532_KEEP;
>>> +			else if (!strcmp(state, "pwm0"))
>>> +				pdata->leds[i].state = PCA9532_PWM0;
>>> +			else if (!strcmp(state, "pwm1"))
>>> +				pdata->leds[i].state = PCA9532_PWM1;
>>> +		}
>>>  		if (++i >= maxleds) {
>>>  			of_node_put(child);
>>>  			break;
> 
> This seems to look for "pwm0" and "pwm1" strings, which do not seem to
> be documented.
> 
> Plus... is it useful to have default-state? We already have default
> trigger. If we keep the value by default (on PC, we do something like
> that) this patch should not be neccessary?

Thanks for the heads-up. Dropping the patch for now.
I guess that pwm0/1 got propagated to v2 by an omission.

Regarding default-on: Felix, do you have any use case that require
default-on set to "keep"?

-- 
Best regards,
Jacek Anaszewski
--
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] memory: ti-emif-sram: introduce relocatable suspend/resume handlers
From: Russell King - ARM Linux @ 2017-04-06 19:00 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Tony Lindgren, Rob Herring, Santosh Shilimkar,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Keerthy J
In-Reply-To: <5cd63e14-52df-6010-4193-c926cdd76839-l0cyMroinI0@public.gmane.org>

On Wed, Apr 05, 2017 at 09:48:26AM -0500, Dave Gerlach wrote:
> Russell,
> On 04/05/2017 09:33 AM, Tony Lindgren wrote:
> >* Russell King - ARM Linux <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org> [170405 07:02]:
> >>I'm not going to comment on this yet, but I'll instead comment on the
> >>newly appeared sram_exec_copy() stuff.
> >>
> >>So, a few years ago, we went to significant effort in ARM land to come
> >>up with a way to _safely_ copy assembler from the kernel into SRAM,
> >>because copying code to SRAM that is compiled in thumb mode and then
> >>executing it is _not_ as simple as memcpy(), cast the pointer to a
> >>function pointer, and then call the function pointer.
> >>
> >>The SRAM stuff throws all that out, instead preferring the dumb memcpy()
> >>approach.
> >>
> >>This needs resolving, and I'd like to see it resolved to the satisfaction
> >>of architecture maintainers before we progress any further down this
> >>route.
> 
> I'm sure you are referring to fncpy, correct? This is what we used before
> with ARM specific code to do the copy, but we've moved into drivers now.

Right, and as I explained above, fncpy() exists with very good reason.
The following does not work on ARM:

	sram = alloc(function_size);

	memcpy(sram, function, function_size);

	sram_ptr = (function_cast_t)sram;

	sram_ptr(args);

when the function is Thumb.  There are two problems with the above code
that fncpy() solves, both stemming from the same root cause:

1. The address of "function" will be offset by one byte, so the memcpy()
   will miss copying the first byte of the function.

2. sram_ptr will not be offset by one byte.

This is because, with Thumb functions, the "address" of the function is
offset by one byte - by the architecture requirements - to indicate that
it is to be called in Thumb mode.

> What are your thoughts on exposing fncpy outside of arch/arm?

You may use it by including asm/fncpy.h, but you may not move it out of
that file.  fncpy() is there exactly because it's _architecture_ specific.

If you're looking to make this generic, then we need cross-arch agreement
on how we can copy functions, and I'd recommend that fncpy() becomes that
generic copy function.  fncpy() has advantages over memcpy() besides
encoding the architecture specific knowledge - the biggest one is that
it guarantees type safety as well.  It ensures that the function pointer
that it's returning conforms with the function it's being asked to copy.

It strikes me, looking at the SRAM stuff, that the baby has been
completely thrown out with the bath water...

And really, this SRAM stuff _should_ have been through architecture
maintainer review before being merged into mainline so that these issues
could have been highlighted before hand.

This looks to me like yet another huge big review failure in kernel land,
because people are insistant on continually dividing stuff up by
sub-directory.  This has got to stop.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
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

* Applied "regulator: helpers: Add regmap set_soft_start helper" to the regulator tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  To: Charles Keepax; +Cc: Mark Brown
In-Reply-To: <1490710484-25277-4-git-send-email-ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>

The patch

   regulator: helpers: Add regmap set_soft_start helper

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.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 a7a453f56a1a116027f84ac53b365eb045a0e279 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Date: Tue, 28 Mar 2017 15:14:40 +0100
Subject: [PATCH] regulator: helpers: Add regmap set_soft_start helper

Add a helper function regulator_set_soft_start_regmap to allow regmap
based regulators to easily enable soft start.

Signed-off-by: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/regulator/helpers.c      | 18 ++++++++++++++++++
 include/linux/regulator/driver.h |  8 ++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 379cdacc05d8..a75e7da49af8 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -446,6 +446,24 @@ int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
 EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
 
 /**
+ * regulator_set_soft_start_regmap - Default set_soft_start() using regmap
+ *
+ * @rdev: device to operate on.
+ */
+int regulator_set_soft_start_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+
+	val = rdev->desc->soft_start_val_on;
+	if (!val)
+		val = rdev->desc->soft_start_mask;
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->soft_start_reg,
+				  rdev->desc->soft_start_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_set_soft_start_regmap);
+
+/**
  * regulator_get_bypass_regmap - Default get_bypass() using regmap
  *
  * @rdev: device to operate on.
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index dac8e7b16bc6..1054c033e783 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -292,6 +292,10 @@ enum regulator_type {
  *			   set_active_discharge
  * @active_discharge_reg: Register for control when using regmap
  *			  set_active_discharge
+ * @soft_start_reg: Register for control when using regmap set_soft_start
+ * @soft_start_mask: Mask for control when using regmap set_soft_start
+ * @soft_start_val_on: Enabling value for control when using regmap
+ *                     set_soft_start
  *
  * @enable_time: Time taken for initial enable of regulator (in uS).
  * @off_on_delay: guard time (in uS), before re-enabling a regulator
@@ -345,6 +349,9 @@ struct regulator_desc {
 	unsigned int active_discharge_off;
 	unsigned int active_discharge_mask;
 	unsigned int active_discharge_reg;
+	unsigned int soft_start_reg;
+	unsigned int soft_start_mask;
+	unsigned int soft_start_val_on;
 
 	unsigned int enable_time;
 
@@ -476,6 +483,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 				   unsigned int new_selector);
 int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable);
 int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable);
+int regulator_set_soft_start_regmap(struct regulator_dev *rdev);
 
 int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
 					  bool enable);
-- 
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

* Applied "regulator: helpers: Add regmap set_pull_down helper" to the regulator tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  To: Charles Keepax; +Cc: Mark Brown
In-Reply-To: <1490710484-25277-5-git-send-email-ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>

The patch

   regulator: helpers: Add regmap set_pull_down helper

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.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 f7d37bc3cb20828ac43b22cbd40222877ee2c46a Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Date: Tue, 28 Mar 2017 15:14:41 +0100
Subject: [PATCH] regulator: helpers: Add regmap set_pull_down helper

Add a helper function regulator_set_pull_down_regmap to allow regmap
based regulators to easily enable pull down.

Signed-off-by: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/regulator/helpers.c      | 18 ++++++++++++++++++
 include/linux/regulator/driver.h |  8 ++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index a75e7da49af8..2ae7c3ac5940 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -464,6 +464,24 @@ int regulator_set_soft_start_regmap(struct regulator_dev *rdev)
 EXPORT_SYMBOL_GPL(regulator_set_soft_start_regmap);
 
 /**
+ * regulator_set_pull_down_regmap - Default set_pull_down() using regmap
+ *
+ * @rdev: device to operate on.
+ */
+int regulator_set_pull_down_regmap(struct regulator_dev *rdev)
+{
+	unsigned int val;
+
+	val = rdev->desc->pull_down_val_on;
+	if (!val)
+		val = rdev->desc->pull_down_mask;
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->pull_down_reg,
+				  rdev->desc->pull_down_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_set_pull_down_regmap);
+
+/**
  * regulator_get_bypass_regmap - Default get_bypass() using regmap
  *
  * @rdev: device to operate on.
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 1054c033e783..8a9078dd2a5f 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -296,6 +296,10 @@ enum regulator_type {
  * @soft_start_mask: Mask for control when using regmap set_soft_start
  * @soft_start_val_on: Enabling value for control when using regmap
  *                     set_soft_start
+ * @pull_down_reg: Register for control when using regmap set_pull_down
+ * @pull_down_mask: Mask for control when using regmap set_pull_down
+ * @pull_down_val_on: Enabling value for control when using regmap
+ *                     set_pull_down
  *
  * @enable_time: Time taken for initial enable of regulator (in uS).
  * @off_on_delay: guard time (in uS), before re-enabling a regulator
@@ -352,6 +356,9 @@ struct regulator_desc {
 	unsigned int soft_start_reg;
 	unsigned int soft_start_mask;
 	unsigned int soft_start_val_on;
+	unsigned int pull_down_reg;
+	unsigned int pull_down_mask;
+	unsigned int pull_down_val_on;
 
 	unsigned int enable_time;
 
@@ -484,6 +491,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable);
 int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable);
 int regulator_set_soft_start_regmap(struct regulator_dev *rdev);
+int regulator_set_pull_down_regmap(struct regulator_dev *rdev);
 
 int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
 					  bool enable);
-- 
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

* Applied "ASoC: Add support for Maxim Integrated MAX98927 Amplifier" to the asoc tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  Cc: Mark Brown, lgirdwood
In-Reply-To: <1490922994-19294-1-git-send-email-ryans.lee@maximintegrated.com>

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@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 related

* Applied "ASoC: cs35l35: Improve power down time" to the asoc tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  To: Charles Keepax; +Cc: Brian Austin, Mark Brown
In-Reply-To: <1491483134-28079-1-git-send-email-ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>

The patch

   ASoC: cs35l35: Improve power down time

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 2c84afb52ebea59e9862fcb8234126b7ae1d1960 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Date: Thu, 6 Apr 2017 13:52:12 +0100
Subject: [PATCH] ASoC: cs35l35: Improve power down time

Shorten the time it takes to power down the amp by disabling the volume
ramp whilst doing the final shutdown. The driver has already muted the
amplifier at this stage so doing the volume ramp serves no purpose.

Signed-off-by: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Acked-by: Brian Austin <brian.austin-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 sound/soc/codecs/cs35l35.c | 8 ++++++++
 sound/soc/codecs/cs35l35.h | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index 9688274f7c90..1db07a6296a4 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -187,6 +187,10 @@ static int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
 		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
 					  CS35L35_PDN_ALL_MASK, 1);
 
+		/* Already muted, so disable volume ramp for faster shutdown */
+		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
+				   CS35L35_AMP_DIGSFT_MASK, 0);
+
 		reinit_completion(&cs35l35->pdn_done);
 
 		ret = wait_for_completion_timeout(&cs35l35->pdn_done,
@@ -199,6 +203,10 @@ static int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
 		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
 					CS35L35_MCLK_DIS_MASK,
 					1 << CS35L35_MCLK_DIS_SHIFT);
+
+		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
+				   CS35L35_AMP_DIGSFT_MASK,
+				   1 << CS35L35_AMP_DIGSFT_SHIFT);
 		break;
 	default:
 		dev_err(codec->dev, "Invalid event = 0x%x\n", event);
diff --git a/sound/soc/codecs/cs35l35.h b/sound/soc/codecs/cs35l35.h
index 156d2f0e6fd8..54e9ac536b20 100644
--- a/sound/soc/codecs/cs35l35.h
+++ b/sound/soc/codecs/cs35l35.h
@@ -190,6 +190,9 @@
 #define CS35L35_AMP_GAIN_ZC_MASK	0x10
 #define CS35L35_AMP_GAIN_ZC_SHIFT	4
 
+#define CS35L35_AMP_DIGSFT_MASK		0x02
+#define CS35L35_AMP_DIGSFT_SHIFT	1
+
 /* CS35L35_SP_FMT_CTL3 */
 #define CS35L35_SP_I2S_DRV_MASK		0x03
 #define CS35L35_SP_I2S_DRV_SHIFT	0
-- 
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

* Applied "ASoC: cs35l35: Correct handling of PDN_DONE with external boost" to the asoc tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  To: Charles Keepax; +Cc: Brian Austin, Mark Brown
In-Reply-To: <1491483134-28079-2-git-send-email-ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>

The patch

   ASoC: cs35l35: Correct handling of PDN_DONE with external boost

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 77b329d1943d38a5acdbaf9d57754975bce701d4 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Date: Thu, 6 Apr 2017 13:52:13 +0100
Subject: [PATCH] ASoC: cs35l35: Correct handling of PDN_DONE with external
 boost

When using an external boost supply the PDN_DONE bit is not set, update
the handling in this case to use to use an appropriate fixed delay.

Signed-off-by: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Acked-by: Brian Austin <brian.austin-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 include/sound/cs35l35.h    |  2 ++
 sound/soc/codecs/cs35l35.c | 32 ++++++++++++++++++++++++--------
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/include/sound/cs35l35.h b/include/sound/cs35l35.h
index 983c610eba2e..88744bbd6728 100644
--- a/include/sound/cs35l35.h
+++ b/include/sound/cs35l35.h
@@ -96,6 +96,8 @@ struct cs35l35_platform_data {
 	int adv_channel;
 	/* Shared Boost for stereo */
 	bool shared_bst;
+	/* Specifies this amp is using an external boost supply */
+	bool ext_bst;
 	/* ClassH Algorithm */
 	struct classh_cfg classh_algo;
 	/* Monitor Config */
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index 1db07a6296a4..6ecb7ddae9cf 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -162,6 +162,27 @@ static bool cs35l35_precious_register(struct device *dev, unsigned int reg)
 	}
 }
 
+static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
+{
+	int ret;
+
+	if (cs35l35->pdata.ext_bst) {
+		usleep_range(5000, 5500);
+		return 0;
+	}
+
+	reinit_completion(&cs35l35->pdn_done);
+
+	ret = wait_for_completion_timeout(&cs35l35->pdn_done,
+					  msecs_to_jiffies(100));
+	if (ret == 0) {
+		dev_err(cs35l35->dev, "PDN_DONE did not complete\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 static int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
@@ -191,14 +212,7 @@ static int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
 		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
 				   CS35L35_AMP_DIGSFT_MASK, 0);
 
-		reinit_completion(&cs35l35->pdn_done);
-
-		ret = wait_for_completion_timeout(&cs35l35->pdn_done,
-							msecs_to_jiffies(100));
-		if (ret == 0) {
-			dev_err(codec->dev, "TIMEOUT PDN_DONE did not complete in 100ms\n");
-			ret = -ETIMEDOUT;
-		}
+		ret = cs35l35_wait_for_pdn(cs35l35);
 
 		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
 					CS35L35_MCLK_DIS_MASK,
@@ -1198,6 +1212,8 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client,
 						"cirrus,shared-boost");
 	}
 
+	pdata->ext_bst = of_property_read_bool(np, "cirrus,external-boost");
+
 	pdata->gain_zc = of_property_read_bool(np, "cirrus,amp-gain-zc");
 
 	classh = of_get_child_by_name(np, "cirrus,classh-internal-algo");
-- 
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

* Applied "ASoC: cs35l35: Add DT binding to specify usage of an external boost supply" to the asoc tree
From: Mark Brown @ 2017-04-06 18:55 UTC (permalink / raw)
  To: Charles Keepax; +Cc: Brian Austin, Mark Brown
In-Reply-To: <1491483134-28079-3-git-send-email-ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>

The patch

   ASoC: cs35l35: Add DT binding to specify usage of an external boost supply

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 0c67fb5544061cb990e07a73e1b7ba1f8ca22479 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Date: Thu, 6 Apr 2017 13:52:14 +0100
Subject: [PATCH] ASoC: cs35l35: Add DT binding to specify usage of an external
 boost supply

Add a device tree binding to let the driver know that the amplifier is
configured to use an external boost supply.

Signed-off-by: Charles Keepax <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
Acked-by: Brian Austin <brian.austin-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 Documentation/devicetree/bindings/sound/cs35l35.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/cs35l35.txt b/Documentation/devicetree/bindings/sound/cs35l35.txt
index 958f0eabfdfc..457d176dcee0 100644
--- a/Documentation/devicetree/bindings/sound/cs35l35.txt
+++ b/Documentation/devicetree/bindings/sound/cs35l35.txt
@@ -33,6 +33,10 @@ Optional properties:
   - cirrus,shared-boost : Boolean to enable ClassH tracking of Advisory Signal
   if 2 Devices share Boost BST_CTL
 
+  - cirrus,external-boost : Boolean to specify the device is using an external
+  boost supply, note that sharing a boost from another cs35l35 would constitute
+  using an external supply for the slave device
+
   - cirrus,sp-drv-strength : Value for setting the Serial Port drive strength
   Table 3-10 of the datasheet lists drive-strength specifications
   0 = 1x (Default)
-- 
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: [RFC 4/8] regulator: core: Check enabling bypass respects constraints
From: Mark Brown @ 2017-04-06 18:52 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Sascha Hauer, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
	Shawn Guo, Robin Gong, Anson Huang, Irina Tirdea, Rob Herring,
	Mark Rutland, Fabio Estevam, Octavian Purdila,
	linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1490730595.15830.1.camel-3arQi8VN3Tc@public.gmane.org>

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

On Tue, Mar 28, 2017 at 10:49:55PM +0300, Leonard Crestez wrote:
> On Tue, 2017-03-28 at 17:47 +0100, Mark Brown wrote:

> > To repeat what I said previously the whole point of bypassing is to not
> > do regulation and generally the constraints in the unregulated idle case
> > are substantially more relaxed.  This would break use cases relying on
> > the existing behaviour which wouldn't expect to affect the parent
> > voltage at all, either stopping things working or making them less
> > efficient by needlessly regulating the voltage down which defeats the
> > main point of bypassing.

> So what you want is to prevent voltage changes unless strictly
> required, even lowering? What I want is to get the minimum voltage in
> the SOC because that's where power is being consumed.

So your end goal here is to bypass a regulator which is forced into your
system design by being integrated into the SoC which isn't able to
regulate down to a low enough voltage for your use case?  I guess one
question is if you need to use the regulator at all?

> It's not at all obvious that in bypass mode the output constraints of a
> regulator need not be respected by the core. I expected the opposite,
> this is something that should be documented.

SubmittingPatches...  Bear in mind that most regulators are fixed
voltage in a given system so bypass would be very difficult to use if it
tried to pass the constraints upstream.

> But if the bypassed regulator has a downstream consumer then it's
> requirements should definitely still be met in bypass mode, right? I
> could set my maximum voltage directly from cpufreq in that case.

What we're interpreting bypass mode as meaning is "stop regulating".
There will still be some limits but we're expecting them to be enforced
in the extremes of the constraints in the parent regulators.

> Or should a bypassed regulator ignore all other requests? One of the
> behaviors that this patch series relies on is that calling set_voltage
> on a bypassed regulator propagates this request to the supply and picks
> the minimum voltage there. An alternative implementation would be to

Yes, the expectation is that if anything is being changed it won't have
any effect until regulation is reenabled but we're not particularly
expecting much activity on bypassed regulators.

> call set_voltage directly on the supply regulator by changing the
> "{arm,soc,pu}-supply" references in DT to point to the PMIC instead.
> Would that be better?

That's more what's expected here.

> Both approaches work. Relying on propagation feels like it is the
> "right way" to handle this, even if it's harder to get right and the
> regulator core does not entirely support it. But it's possible that
> this is based on a misunderstanding of what "bypass" is actually
> supposed to do.

Another option would be to add a regulator configuration which allowed
the regulator to transparently go into bypass mode if the parent could
do things directly, only enabling regulation if the parent couldn't
support.  That would mean you'd loose the supply cleanup function which
is typically part of why there are LDOs in the system but it sounds like
you're OK with that in at least your use case.

We could also perhaps have a way to set the regulator into permanent
bypass mode from the constraints for use cases that just never need it
and then remap the supply relationship at probe time (which avoids any
special runtime casing) for something even simpler.

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

^ permalink raw reply

* Re: [PATCH V10 00/12] IOMMU probe deferral support
From: Frank Rowand @ 2017-04-06 18:46 UTC (permalink / raw)
  To: Rob Herring, Sricharan R
  Cc: Robin Murphy, Will Deacon, Joerg Roedel, Lorenzo Pieralisi,
	Linux IOMMU, linux-arm-kernel@lists.infradead.org, linux-arm-msm,
	Marek Szyprowski, bhelgaas@google.com, linux-pci@vger.kernel.org,
	linux-acpi@vger.kernel.org, Tomasz Nowicki, Hanjun Guo,
	Sinan Kaya, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <CAL_JsqJH9C9sNGBSLH88bJ=uKF7RibHDAUZUW9M2xeO2AM-FUw@mail.gmail.com>

On 04/04/17 18:23, Rob Herring wrote:
> On Tue, Apr 4, 2017 at 5:18 AM, Sricharan R <sricharan@codeaurora.org> wrote:
>> This series calls the dma ops configuration for the devices
>> at a generic place so that it works for all busses.
>> The dma_configure_ops for a device is now called during
>> the device_attach callback just before the probe of the
>> bus/driver is called. Similarly dma_deconfigure is called during
>> device/driver_detach path.
> 
> For patches 3, 4, 6, 7, 8:
> 
> Acked-by: Rob Herring <robh@kernel.org>
> .
> 

And a few hours later, I had the opposite opinion on a couple of
patches, so there is some ongoing discussion working this out.

-Frank

^ permalink raw reply

* Re: [PATCH] of: change fixup of dma-ranges size to error
From: Frank Rowand @ 2017-04-06 18:37 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAL_Jsq+GLBtaezUiTbm0DAA2+MjcvxAcCsS-qJrr05YcTO5tdw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 04/06/17 07:03, Rob Herring wrote:
> On Thu, Apr 6, 2017 at 1:18 AM,  <frowand.list-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> From: Frank Rowand <frank.rowand-7U/KSKJipcs@public.gmane.org>
>>
>> of_dma_get_range() has workaround code to fixup a device tree that
>> incorrectly specified a mask instead of a size for property
>> dma-ranges.  That device tree was fixed a year ago in v4.6, so
>> the workaround is no longer needed.  Leave a data validation
>> check in place, but no longer do the fixup.  Move the check
>> one level deeper in the call stack so that other possible users
>> of dma-ranges will also be protected.
>>
>> The fix to the device tree was in
>> commit c91cb9123cdd ("dtb: amd: Fix DMA ranges in device tree").
> 
> NACK.
> This was by design. You can't represent a size of 2^64 or 2^32.

I agree that being unable to represent a size of 2^32 in a u32 and
a size of 2^64 in a u64 is the underlying issue.

But the code to convert a mask to a size is _not_ design, it is a
hack that temporarily worked around a device tree that did not follow
the dma-ranges binding in the ePAPR.

That device tree was corrected a year ago to provide a size instead of
a mask.

> Well, technically you can for the latter, but then you have to grow
> #size-cells to 2 for an otherwise all 32-bit system which seems kind
> of pointless and wasteful. You could further restrict this to only
> allow ~0 and not just any case with bit 0 set.
> 
> I'm pretty sure AMD is not the only system. There were 32-bit systems too.

I examined all instances of property dma-ranges in in tree dts files in
Linux 4.11-rc1.  There are none that incorrectly specify mask instead of
size.

#size-cells only changes to 2 for the dma-ranges property and the ranges
property when size is 2^32, so that is a very small amount of space.

The patch does not allow for a size of 2^64.  If a system requires a
size of 2^64 then the type of size needs to increase to be larger
than a u64.  If you would like for the code to be defensive and
detect a device tree providing a size of 2^64 then I can add a
check to of_dma_get_range() to return -EINVAL if #size-cells > 2.
When that error triggers, the type of size can be changed.

> 
> Rob
> 

--
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 v3] regulator: Add driver for voltage controlled regulators
From: Mark Brown @ 2017-04-06 18:21 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: Liam Girdwood, Rob Herring, Mark Rutland,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Douglas Anderson, Brian Norris
In-Reply-To: <20170331205035.126001-1-mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

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

On Fri, Mar 31, 2017 at 01:50:35PM -0700, Matthias Kaehlcke wrote:

> +- compatible		  : must be "vctrl-regulator".
> +- regulator-min-microvolt : smallest voltage consumers may set
> +- regulator-max-microvolt : largest voltage consumers may set
> +- ctrl-regulator:	  : the name of the regulator supplying the control
> +			    voltage.

This looks good except for this bit where we read the regulator name out
of the DT, that's generally a sign of bad practice for things that are
less simple passives than things like this or fixed voltage regulators.
As with the supplies for fixed voltage regulators just pick a name for
the supply (ctrl seems fine to me) and use that, neither option is
perfect but at elast this less typing for everyone and it's consistent
with what other similar things are already doing.

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

^ permalink raw reply

* [PATCH v3 9/9] ARM: dts: imx6ul-isiot: Add FEC node support
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer, Fabio Estevam,
	Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan-oRp2ZoJdM/RWk0Htik3J/w@public.gmane.org>

From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

Add support for fec1 node on Engicam Is.IoT variant boards.

Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Changes for v3:
- none
Changes for v2:
- Newly added patch

 arch/arm/boot/dts/imx6ul-isiot.dtsi | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/imx6ul-isiot.dtsi
index 7e947e5..ccc5477 100644
--- a/arch/arm/boot/dts/imx6ul-isiot.dtsi
+++ b/arch/arm/boot/dts/imx6ul-isiot.dtsi
@@ -129,6 +129,24 @@
 	status = "okay";
 };
 
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
+};
+
 &pwm8 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_pwm8>;
@@ -159,6 +177,21 @@
 };
 
 &iomuxc {
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_DATA0__ENET1_MDIO	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET1_MDC	0x1b0b0
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+			MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10	0x1b0b0
+		>;
+	};
+
 	pinctrl_i2c1: i2c1grp {
 		fsl,pins = <
 			MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
-- 
1.9.1

--
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 v3 8/9] ARM: dts: imx6qdl-icore-rqs: Add CAN nodes
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, devicetree, linux-kernel, Sascha Hauer,
	Fabio Estevam, Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

Add support for can1 and can2 nodes on Engicam i.CoreM6 RQS
QDL module boards.

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Matteo Lisi <matteo.lisi@engicam.com>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- none
Changes for v2:
- s/flexcan/can
- s/pinctrl_flexcan/pinctrl_can

 arch/arm/boot/dts/imx6dl-icore-rqs.dts   |  8 ++++++++
 arch/arm/boot/dts/imx6q-icore-rqs.dts    |  8 ++++++++
 arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi | 26 ++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/imx6dl-icore-rqs.dts b/arch/arm/boot/dts/imx6dl-icore-rqs.dts
index 053e7cb..74335c4 100644
--- a/arch/arm/boot/dts/imx6dl-icore-rqs.dts
+++ b/arch/arm/boot/dts/imx6dl-icore-rqs.dts
@@ -60,3 +60,11 @@
 		VDDD-supply = <&reg_1p8v>;
 	};
 };
+
+&can1 {
+	status = "okay";
+};
+
+&can2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-rqs.dts b/arch/arm/boot/dts/imx6q-icore-rqs.dts
index d45e4f5..2d4539a 100644
--- a/arch/arm/boot/dts/imx6q-icore-rqs.dts
+++ b/arch/arm/boot/dts/imx6q-icore-rqs.dts
@@ -49,6 +49,14 @@
 	compatible = "engicam,imx6-icore-rqs", "fsl,imx6q";
 };
 
+&can1 {
+	status = "okay";
+};
+
+&can2 {
+	status = "okay";
+};
+
 &i2c3 {
 	sgtl5000: codec@a {
 		compatible = "fsl,sgtl5000";
diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
index 0e79a5b..998fa77 100644
--- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
@@ -145,6 +145,18 @@
 	};
 };
 
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	xceiver-supply = <&reg_3p3v>;
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can2>;
+	xceiver-supply = <&reg_3p3v>;
+};
+
 &clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LVDS2_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_OSC>;
@@ -296,6 +308,20 @@
 		>;
 	};
 
+	pinctrl_can1: can1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b020
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b020
+		>;
+	};
+
+	pinctrl_can2: can2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b020
+			MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b020
+		>;
+	};
+
 	pinctrl_i2c1: i2c1grp {
 		fsl,pins = <
 			MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 7/9] ARM: dts: imx6dl-icore: Add touchscreen node
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer, Fabio Estevam,
	Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan-oRp2ZoJdM/RWk0Htik3J/w@public.gmane.org>

From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

max11801 touchscreen on Engicam iCoreM6 DualLite/Solo module is
connected via i2c1, so add max11801: touchscreen@48 on i2c1.

Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Changes for v3,v2:
- none

 arch/arm/boot/dts/imx6dl-icore.dts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/imx6dl-icore.dts b/arch/arm/boot/dts/imx6dl-icore.dts
index ea9ab05..27f37cd 100644
--- a/arch/arm/boot/dts/imx6dl-icore.dts
+++ b/arch/arm/boot/dts/imx6dl-icore.dts
@@ -58,6 +58,15 @@
 	status = "okay";
 };
 
+&i2c1 {
+	max11801: touchscreen@48 {
+		compatible = "maxim,max11801";
+		reg = <0x48>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
 &i2c3 {
 	sgtl5000: codec@a {
 		compatible = "fsl,sgtl5000";
-- 
1.9.1

--
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 v3 6/9] ARM: dts: imx6dl-icore: Add LVDS support
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, devicetree, linux-kernel, Sascha Hauer,
	Fabio Estevam, Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

Add LVDS display support for OpenFrame Capacitive touch 7 inc
display which is supported by Engicam i.CoreM6 DualLite/Solo Starter Kit.

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Matteo Lisi <matteo.lisi@engicam.com>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3,v2:
- none

 arch/arm/boot/dts/imx6dl-icore.dts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/imx6dl-icore.dts b/arch/arm/boot/dts/imx6dl-icore.dts
index 0562ce4..ea9ab05 100644
--- a/arch/arm/boot/dts/imx6dl-icore.dts
+++ b/arch/arm/boot/dts/imx6dl-icore.dts
@@ -68,3 +68,28 @@
 		VDDD-supply = <&reg_1p8v>;
 	};
 };
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: timing0 {
+				clock-frequency = <60000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <30>;
+				hfront-porch = <30>;
+				vback-porch = <5>;
+				vfront-porch = <5>;
+				hsync-len = <64>;
+				vsync-len = <20>;
+			};
+		};
+	};
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 5/9] ARM: dts: imx6qdl-icore-rqs: Replace to use simple-audio-card
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: devicetree, Matteo Lisi, linux-kernel, Jagan Teki, Sascha Hauer,
	Fabio Estevam, Michael Trimarchi, linux-arm-kernel
In-Reply-To: <1491501735-1649-1-git-send-email-jagan@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

This patch replace fsl,imx-audio-sgtl5000 and use simple-audio-card
for Engicam i.CoreM6 RQS QDL platform boards.

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Matteo Lisi <matteo.lisi@engicam.com>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- Newly added patch

 arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
index d24e531..0e79a5b 100644
--- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
@@ -120,16 +120,28 @@
 	};
 
 	sound {
-		compatible = "fsl,imx-audio-sgtl5000";
-		model = "imx-audio-sgtl5000";
-		ssi-controller = <&ssi1>;
-		audio-codec = <&sgtl5000>;
-		audio-routing =
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "imx6qdl-icore-sgtl5000";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
 			"MIC_IN", "Mic Jack",
 			"Mic Jack", "Mic Bias",
 			"Headphone Jack", "HP_OUT";
-		mux-int-port = <1>;
-		mux-ext-port = <4>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&ssi1>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&sgtl5000>;
+		};
 	};
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 4/9] ARM: dts: imx6dl-icore-rqs: Add sgtl5000 codec node
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, devicetree, linux-kernel, Sascha Hauer,
	Fabio Estevam, Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

- Moved sound card node to imx6qdl-icore-rqs.dtsi
- Added codec node in imx6dl-icore-rqs
- Replace codec: sgtl5000@0a => sgtl5000: codec@a
  on imx6q-icore-rqs.dts to [label:] node-name[@unit-address]
  according to devicetree specification from ePAPER v1.1

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Matteo Lisi <matteo.lisi@engicam.com>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- squash previous [PATCH v2 10/15] and [PATCH v2 11/15]
Changes for v2:
- Newly added patch

 arch/arm/boot/dts/imx6dl-icore-rqs.dts   | 11 +++++++++++
 arch/arm/boot/dts/imx6q-icore-rqs.dts    | 15 +--------------
 arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi | 13 +++++++++++++
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/arch/arm/boot/dts/imx6dl-icore-rqs.dts b/arch/arm/boot/dts/imx6dl-icore-rqs.dts
index cf42c2f..053e7cb 100644
--- a/arch/arm/boot/dts/imx6dl-icore-rqs.dts
+++ b/arch/arm/boot/dts/imx6dl-icore-rqs.dts
@@ -49,3 +49,14 @@
 	model = "Engicam i.CoreM6 DualLite/Solo RQS Starter Kit";
 	compatible = "engicam,imx6-icore-rqs", "fsl,imx6dl";
 };
+
+&i2c3 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-rqs.dts b/arch/arm/boot/dts/imx6q-icore-rqs.dts
index e451b4c..d45e4f5 100644
--- a/arch/arm/boot/dts/imx6q-icore-rqs.dts
+++ b/arch/arm/boot/dts/imx6q-icore-rqs.dts
@@ -47,23 +47,10 @@
 / {
 	model = "Engicam i.CoreM6 Quad/Dual RQS Starter Kit";
 	compatible = "engicam,imx6-icore-rqs", "fsl,imx6q";
-
-	sound {
-		compatible = "fsl,imx-audio-sgtl5000";
-		model = "imx-audio-sgtl5000";
-		ssi-controller = <&ssi1>;
-		audio-codec = <&codec>;
-		audio-routing =
-			"MIC_IN", "Mic Jack",
-			"Mic Jack", "Mic Bias",
-			"Headphone Jack", "HP_OUT";
-		mux-int-port = <1>;
-		mux-ext-port = <4>;
-	};
 };
 
 &i2c3 {
-	codec: sgtl5000@0a {
+	sgtl5000: codec@a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
 		clocks = <&clks IMX6QDL_CLK_CKO>;
diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
index 5fab5be..d24e531 100644
--- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi
@@ -118,6 +118,19 @@
 		clocks = <&clks IMX6QDL_CLK_LVDS2_GATE>;
 		clock-names = "refclk";
 	};
+
+	sound {
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "imx-audio-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
 };
 
 &clks {
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 3/9] ARM: dts: imx6qdl-icore: Add Sound card with codec node
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, devicetree, linux-kernel, Sascha Hauer,
	Fabio Estevam, Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

Add support for Sound card and related codec(via i2c1) nodes
on below Engicam module boards.
- i.CoreM6 DualLite/Solo Starter kit
- i.CoreM6 Quad/Dual Starter kit
- i.CoreM6 Quad/Dual OpenFrame Cap touch 10.1
- i.CoreM6 Quad/Dual OpenFrame Cap touch 12.3

Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Matteo Lisi <matteo.lisi@engicam.com>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- Replace fsl,imx-audio-sgtl5000 and use simple-audio-card
Changes for v2:
- Use proper [label:] node-name[@unit-address] for codec

 arch/arm/boot/dts/imx6dl-icore.dts        | 11 +++++++
 arch/arm/boot/dts/imx6q-icore-ofcap10.dts | 11 +++++++
 arch/arm/boot/dts/imx6q-icore-ofcap12.dts | 11 +++++++
 arch/arm/boot/dts/imx6q-icore.dts         | 11 +++++++
 arch/arm/boot/dts/imx6qdl-icore.dtsi      | 48 +++++++++++++++++++++++++++++++
 5 files changed, 92 insertions(+)

diff --git a/arch/arm/boot/dts/imx6dl-icore.dts b/arch/arm/boot/dts/imx6dl-icore.dts
index 6de83c7..0562ce4 100644
--- a/arch/arm/boot/dts/imx6dl-icore.dts
+++ b/arch/arm/boot/dts/imx6dl-icore.dts
@@ -57,3 +57,14 @@
 &can2 {
 	status = "okay";
 };
+
+&i2c3 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts b/arch/arm/boot/dts/imx6q-icore-ofcap10.dts
index 49b60ca..f63b87f 100644
--- a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts
+++ b/arch/arm/boot/dts/imx6q-icore-ofcap10.dts
@@ -50,6 +50,17 @@
 	compatible = "engicam,imx6-icore", "fsl,imx6q";
 };
 
+&i2c3 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
+
 &ldb {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
index 9e230f5..68ca828 100644
--- a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
+++ b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
@@ -50,6 +50,17 @@
 	compatible = "engicam,imx6-icore", "fsl,imx6q";
 };
 
+&i2c3 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
+
 &ldb {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/imx6q-icore.dts b/arch/arm/boot/dts/imx6q-icore.dts
index 5613dd9..1ae7294 100644
--- a/arch/arm/boot/dts/imx6q-icore.dts
+++ b/arch/arm/boot/dts/imx6q-icore.dts
@@ -67,6 +67,17 @@
 	};
 };
 
+&i2c3 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
+
 &ldb {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/imx6qdl-icore.dtsi b/arch/arm/boot/dts/imx6qdl-icore.dtsi
index 56d0c5d..1bd7cdb 100644
--- a/arch/arm/boot/dts/imx6qdl-icore.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore.dtsi
@@ -55,6 +55,25 @@
 		default-brightness-level = <7>;
 	};
 
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+
+	reg_2p5v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	reg_3p3v: regulator-3p3v {
 		compatible = "regulator-fixed";
 		regulator-name = "3P3V";
@@ -87,6 +106,31 @@
 		#clock-cells = <0>;
 		clock-frequency = <25000000>;  /* 25MHz for example */
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "imx6qdl-icore-sgtl5000";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+
+		simple-audio-card,cpu {
+			sound-dai = <&ssi1>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&sgtl5000>;
+		};
+	};
 };
 
 &can1 {
@@ -149,6 +193,10 @@
 	status = "okay";
 };
 
+&ssi1 {
+	status = "okay";
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart4>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 2/9] ARM: dts: imx6ul-geam: Add Sound card with codec node
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer, Fabio Estevam,
	Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan-oRp2ZoJdM/RWk0Htik3J/w@public.gmane.org>

From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

Add support for Sound card and related codec(via i2c1) nodes
on Engicam GEAM6UL variant module boards.

Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Changes for v3:
- Replace fsl,imx-audio-sgtl5000 and use simple-audio-card
Changes for v2:
- Use proper [label:] node-name[@unit-address] for codec
- Remove incorrect codec property 'wlf,shared-lrclk'
- Remove 'gpr' from sound card node

 arch/arm/boot/dts/imx6ul-geam-kit.dts | 12 ++++++++++++
 arch/arm/boot/dts/imx6ul-geam.dtsi    | 26 ++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-geam-kit.dts b/arch/arm/boot/dts/imx6ul-geam-kit.dts
index 142e60c..02edcba 100644
--- a/arch/arm/boot/dts/imx6ul-geam-kit.dts
+++ b/arch/arm/boot/dts/imx6ul-geam-kit.dts
@@ -58,6 +58,18 @@
 	status = "okay";
 };
 
+&i2c1 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6UL_CLK_OSC>;
+		clock-names = "mclk";
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+};
+
 &lcdif {
 	display = <&display0>;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-geam.dtsi b/arch/arm/boot/dts/imx6ul-geam.dtsi
index eb94d95..3bc3238 100644
--- a/arch/arm/boot/dts/imx6ul-geam.dtsi
+++ b/arch/arm/boot/dts/imx6ul-geam.dtsi
@@ -87,6 +87,32 @@
 		regulator-always-on;
 		regulator-boot-on;
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "imx6ul-geam-sgtl5000";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&sgtl5000>;
+			clocks = <&clks IMX6UL_CLK_SAI2>;
+		};
+	};
 };
 
 &can1 {
-- 
1.9.1

--
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 v3 1/9] ARM: dts: imx6ul-isiot: Add Sound card with codec node
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer, Fabio Estevam,
	Matteo Lisi, Michael Trimarchi, Jagan Teki
In-Reply-To: <1491501735-1649-1-git-send-email-jagan-oRp2ZoJdM/RWk0Htik3J/w@public.gmane.org>

From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>

Add support for Sound card and related codec(via i2c1) nodes
on Engicam Is.IoT MX6UL variant module boards.

Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Changes for v3:
- Replace fsl,imx-audio-sgtl5000 and use simple-audio-card
Changes for v2:
- Use proper [label:] node-name[@unit-address] for codec
- Remove incorrect codec property 'wlf,shared-lrclk'
- Remove 'gpr' from sound card node

 arch/arm/boot/dts/imx6ul-isiot-common.dtsi | 10 +++++++
 arch/arm/boot/dts/imx6ul-isiot.dtsi        | 44 ++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-isiot-common.dtsi b/arch/arm/boot/dts/imx6ul-isiot-common.dtsi
index 2beaab6..d456080 100644
--- a/arch/arm/boot/dts/imx6ul-isiot-common.dtsi
+++ b/arch/arm/boot/dts/imx6ul-isiot-common.dtsi
@@ -41,6 +41,16 @@
  */
 
 &i2c1 {
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6UL_CLK_OSC>;
+		clock-names = "mclk";
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+		VDDD-supply = <&reg_1p8v>;
+	};
+
 	stmpe811: gpio-expander@44 {
 		compatible = "st,stmpe811";
 		reg = <0x44>;
diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/imx6ul-isiot.dtsi
index ea30380..7e947e5 100644
--- a/arch/arm/boot/dts/imx6ul-isiot.dtsi
+++ b/arch/arm/boot/dts/imx6ul-isiot.dtsi
@@ -69,6 +69,50 @@
 				    100>;
 		default-brightness-level = <100>;
 	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "imx6ul-isiot-sgtl5000";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&sgtl5000>;
+			clocks = <&clks IMX6UL_CLK_SAI2>;
+		};
+	};
 };
 
 &i2c1 {
-- 
1.9.1

--
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 v3 0/9] ARM: dts: i.MX6: Add lcdif/sound nodes on Engicam SOMs
From: Jagan Teki @ 2017-04-06 18:02 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, devicetree, linux-kernel, Sascha Hauer,
	Fabio Estevam, Matteo Lisi, Michael Trimarchi, Jagan Teki

From: Jagan Teki <jagan@amarulasolutions.com>

This patchset, add support for LVDS, touchscreen, sound card and related codec
and can nodes all Engicam SOM's which are supporting mainline as of now.

Jagan Teki (9):
  ARM: dts: imx6ul-isiot: Add Sound card with codec node
  ARM: dts: imx6ul-geam: Add Sound card with codec node
  ARM: dts: imx6qdl-icore: Add Sound card with codec node
  ARM: dts: imx6dl-icore-rqs: Add sgtl5000 codec node
  ARM: dts: imx6qdl-icore-rqs: Replace to use simple-audio-card
  ARM: dts: imx6dl-icore: Add LVDS support
  ARM: dts: imx6dl-icore: Add touchscreen node
  ARM: dts: imx6qdl-icore-rqs: Add CAN nodes
  ARM: dts: imx6ul-isiot: Add FEC node support

 arch/arm/boot/dts/imx6dl-icore-rqs.dts     | 19 ++++++++
 arch/arm/boot/dts/imx6dl-icore.dts         | 45 +++++++++++++++++
 arch/arm/boot/dts/imx6q-icore-ofcap10.dts  | 11 +++++
 arch/arm/boot/dts/imx6q-icore-ofcap12.dts  | 11 +++++
 arch/arm/boot/dts/imx6q-icore-rqs.dts      | 21 ++++----
 arch/arm/boot/dts/imx6q-icore.dts          | 11 +++++
 arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi   | 51 ++++++++++++++++++++
 arch/arm/boot/dts/imx6qdl-icore.dtsi       | 48 +++++++++++++++++++
 arch/arm/boot/dts/imx6ul-geam-kit.dts      | 12 +++++
 arch/arm/boot/dts/imx6ul-geam.dtsi         | 26 ++++++++++
 arch/arm/boot/dts/imx6ul-isiot-common.dtsi | 10 ++++
 arch/arm/boot/dts/imx6ul-isiot.dtsi        | 77 ++++++++++++++++++++++++++++++
 12 files changed, 329 insertions(+), 13 deletions(-)

-- 
1.9.1

^ permalink raw reply

* Re: [PATCH 1/1] gpio: core: Decouple open drain/source flag with active low/high
From: Andy Shevchenko @ 2017-04-06 17:30 UTC (permalink / raw)
  To: Laxman Dewangan
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Frank Rowand, linux-gpio@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree
In-Reply-To: <58E67328.5040805@nvidia.com>

On Thu, Apr 6, 2017 at 7:56 PM, Laxman Dewangan <ldewangan@nvidia.com> wrote:
> On Thursday 06 April 2017 09:40 PM, Andy Shevchenko wrote:
>> On Thu, Apr 6, 2017 at 4:35 PM, Laxman Dewangan <ldewangan@nvidia.com>
>> wrote:

>>> Adding different flag for the Open Drain/Open Source which is valid
>>> only when Single ended flag is enabled.
>>>          if (single_ended) {
>>> -               if (active_low)
>>> +               if (open_drain)
>>
>> This breaks ACPI case, right?

> In acpi case, single_ended is not handled. It only handles the active LOW.
>
> From code:

Fair enough.
I would look into ACPI spec for possibility to add this kind of functionality.

Thanks.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH v2 4/4] drm: zte: add VGA driver support
From: Sean Paul @ 2017-04-06 17:12 UTC (permalink / raw)
  To: Shawn Guo
  Cc: devicetree, Xin Zhou, Daniel Vetter, Baoyou Xie, dri-devel,
	Rob Herring, Jun Nie
In-Reply-To: <1491490870-6330-5-git-send-email-shawnguo@kernel.org>

On Thu, Apr 06, 2017 at 11:01:10PM +0800, Shawn Guo wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
> 
> It adds VGA driver support, which needs to configure corresponding VOU
> interface in RGB_888 format, and thus the following changes are needed
> on zx_vou.
> 
> - Rename the CSC block of Graphic Layer a bit to make it more specific,
>   and add CSC of Channel to support RGB output.
> - Bypass Dither block for RGB output.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/zte/Makefile      |   1 +
>  drivers/gpu/drm/zte/zx_drm_drv.c  |   1 +
>  drivers/gpu/drm/zte/zx_drm_drv.h  |   1 +
>  drivers/gpu/drm/zte/zx_vga.c      | 530 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/zte/zx_vga_regs.h |  36 +++
>  drivers/gpu/drm/zte/zx_vou.c      |  33 ++-
>  drivers/gpu/drm/zte/zx_vou_regs.h |  12 +-
>  7 files changed, 610 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/gpu/drm/zte/zx_vga.c
>  create mode 100644 drivers/gpu/drm/zte/zx_vga_regs.h
> 
> diff --git a/drivers/gpu/drm/zte/Makefile b/drivers/gpu/drm/zte/Makefile
> index 01352b56c418..9df7766a7f9d 100644
> --- a/drivers/gpu/drm/zte/Makefile
> +++ b/drivers/gpu/drm/zte/Makefile
> @@ -3,6 +3,7 @@ zxdrm-y := \
>  	zx_hdmi.o \
>  	zx_plane.o \
>  	zx_tvenc.o \
> +	zx_vga.o \
>  	zx_vou.o
>  
>  obj-$(CONFIG_DRM_ZTE) += zxdrm.o
> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
> index 5c6944a1e72c..8a6892eeb44f 100644
> --- a/drivers/gpu/drm/zte/zx_drm_drv.c
> +++ b/drivers/gpu/drm/zte/zx_drm_drv.c
> @@ -248,6 +248,7 @@ static int zx_drm_remove(struct platform_device *pdev)
>  	&zx_crtc_driver,
>  	&zx_hdmi_driver,
>  	&zx_tvenc_driver,
> +	&zx_vga_driver,
>  	&zx_drm_platform_driver,
>  };
>  
> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.h b/drivers/gpu/drm/zte/zx_drm_drv.h
> index 5ca035b079c7..2a8cdc5f8be4 100644
> --- a/drivers/gpu/drm/zte/zx_drm_drv.h
> +++ b/drivers/gpu/drm/zte/zx_drm_drv.h
> @@ -14,6 +14,7 @@
>  extern struct platform_driver zx_crtc_driver;
>  extern struct platform_driver zx_hdmi_driver;
>  extern struct platform_driver zx_tvenc_driver;
> +extern struct platform_driver zx_vga_driver;
>  
>  static inline u32 zx_readl(void __iomem *reg)
>  {
> diff --git a/drivers/gpu/drm/zte/zx_vga.c b/drivers/gpu/drm/zte/zx_vga.c
> new file mode 100644
> index 000000000000..0d850d9ea700
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_vga.c
> @@ -0,0 +1,530 @@
> +/*
> + * Copyright (C) 2017 Sanechips Technology Co., Ltd.
> + * Copyright 2017 Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "zx_drm_drv.h"
> +#include "zx_vga_regs.h"
> +#include "zx_vou.h"
> +
> +struct zx_vga_pwrctrl {
> +	struct regmap *regmap;
> +	u32 reg;
> +	u32 mask;
> +};
> +
> +struct zx_vga_i2c {
> +	struct i2c_adapter adap;
> +	struct mutex lock;
> +};
> +
> +struct zx_vga {
> +	struct drm_connector connector;
> +	struct drm_encoder encoder;
> +	struct zx_vga_i2c *ddc;
> +	struct device *dev;
> +	void __iomem *mmio;
> +	struct clk *i2c_wclk;
> +	struct zx_vga_pwrctrl pwrctrl;
> +	spinlock_t lock;
> +	struct completion complete;
> +	bool connected;
> +};
> +
> +#define to_zx_vga(x) container_of(x, struct zx_vga, x)
> +
> +static void zx_vga_encoder_enable(struct drm_encoder *encoder)
> +{
> +	struct zx_vga *vga = to_zx_vga(encoder);
> +	struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
> +
> +	/* Set bit to power up VGA DACs */
> +	regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask,
> +			   pwrctrl->mask);
> +
> +	vou_inf_enable(VOU_VGA, encoder->crtc);
> +}
> +
> +static void zx_vga_encoder_disable(struct drm_encoder *encoder)
> +{
> +	struct zx_vga *vga = to_zx_vga(encoder);
> +	struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
> +
> +	vou_inf_disable(VOU_VGA, encoder->crtc);
> +
> +	/* Clear bit to power down VGA DACs */
> +	regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask, 0);
> +}
> +
> +static const struct drm_encoder_helper_funcs zx_vga_encoder_helper_funcs = {
> +	.enable	= zx_vga_encoder_enable,
> +	.disable = zx_vga_encoder_disable,
> +};
> +
> +static const struct drm_encoder_funcs zx_vga_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +static int zx_vga_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct zx_vga *vga = to_zx_vga(connector);
> +	unsigned long flags;
> +	struct edid *edid;
> +	int ret;
> +
> +	/*
> +	 * Clear both detection bits to switch I2C bus from device
> +	 * detecting to EDID reading.
> +	 */
> +	spin_lock_irqsave(&vga->lock, flags);
> +	zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, 0);
> +	spin_unlock_irqrestore(&vga->lock, flags);
> +
> +	edid = drm_get_edid(connector, &vga->ddc->adap);
> +	if (!edid)
> +		return 0;
> +
> +	/*
> +	 * As edid reading succeeds, device must be connected, so we set
> +	 * up detection bit for unplug interrupt here.
> +	 */
> +	spin_lock_irqsave(&vga->lock, flags);
> +	zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, VGA_DETECT_SEL_HAS_DEVICE);
> +	spin_unlock_irqrestore(&vga->lock, flags);
> +
> +	drm_mode_connector_update_edid_property(connector, edid);
> +	ret = drm_add_edid_modes(connector, edid);
> +	kfree(edid);
> +
> +	return ret;
> +}
> +
> +static enum drm_mode_status
> +zx_vga_connector_mode_valid(struct drm_connector *connector,
> +			    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_connector_helper_funcs zx_vga_connector_helper_funcs = {
> +	.get_modes = zx_vga_connector_get_modes,
> +	.mode_valid = zx_vga_connector_mode_valid,
> +};
> +
> +static enum drm_connector_status
> +zx_vga_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	struct zx_vga *vga = to_zx_vga(connector);
> +
> +	return vga->connected ? connector_status_connected :
> +				connector_status_disconnected;
> +}
> +
> +static const struct drm_connector_funcs zx_vga_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.detect = zx_vga_connector_detect,
> +	.destroy = drm_connector_cleanup,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int zx_vga_register(struct drm_device *drm, struct zx_vga *vga)
> +{
> +	struct drm_encoder *encoder = &vga->encoder;
> +	struct drm_connector *connector = &vga->connector;
> +	struct device *dev = vga->dev;
> +	int ret;
> +
> +	encoder->possible_crtcs = VOU_CRTC_MASK;
> +
> +	ret = drm_encoder_init(drm, encoder, &zx_vga_encoder_funcs,
> +			       DRM_MODE_ENCODER_DAC, NULL);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to init encoder: %d\n", ret);
> +		return ret;
> +	};
> +
> +	drm_encoder_helper_add(encoder, &zx_vga_encoder_helper_funcs);
> +
> +	vga->connector.polled = DRM_CONNECTOR_POLL_HPD;
> +
> +	ret = drm_connector_init(drm, connector, &zx_vga_connector_funcs,
> +				 DRM_MODE_CONNECTOR_VGA);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to init connector: %d\n", ret);
> +		goto clean_encoder;
> +	};
> +
> +	drm_connector_helper_add(connector, &zx_vga_connector_helper_funcs);
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to attach encoder: %d\n", ret);
> +		goto clean_connector;
> +	};
> +
> +	return 0;
> +
> +clean_connector:
> +	drm_connector_cleanup(connector);
> +clean_encoder:
> +	drm_encoder_cleanup(encoder);
> +	return ret;
> +}
> +
> +static int zx_vga_pwrctrl_init(struct zx_vga *vga)
> +{
> +	struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
> +	struct device *dev = vga->dev;
> +	struct of_phandle_args out_args;
> +	struct regmap *regmap;
> +	int ret;
> +
> +	ret = of_parse_phandle_with_fixed_args(dev->of_node,
> +				"zte,vga-power-control", 2, 0, &out_args);
> +	if (ret)
> +		return ret;
> +
> +	regmap = syscon_node_to_regmap(out_args.np);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		goto out;
> +	}
> +
> +	pwrctrl->regmap = regmap;
> +	pwrctrl->reg = out_args.args[0];
> +	pwrctrl->mask = out_args.args[1];
> +
> +out:
> +	of_node_put(out_args.np);
> +	return ret;
> +}
> +
> +static int zx_vga_i2c_read(struct zx_vga *vga, struct i2c_msg *msg)
> +{
> +	int len = msg->len;
> +	u8 *buf = msg->buf;
> +	u32 offset = 0;
> +	int i;
> +
> +	reinit_completion(&vga->complete);
> +
> +	/* Select combo write */
> +	zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_COMBO, VGA_CMD_COMBO);
> +	zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_RW, 0);
> +
> +	while (len > 0) {
> +		u32 cnt;
> +
> +		/* Clear RX FIFO */
> +		zx_writel_mask(vga->mmio + VGA_RXF_CTRL, VGA_RX_FIFO_CLEAR,
> +			       VGA_RX_FIFO_CLEAR);
> +
> +		/* Data offset to read from */
> +		zx_writel(vga->mmio + VGA_SUB_ADDR, offset);
> +
> +		/* Kick off the transfer */
> +		zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_TRANS,
> +			       VGA_CMD_TRANS);
> +
> +		if (!wait_for_completion_timeout(&vga->complete,
> +						 msecs_to_jiffies(1000))) {
> +			DRM_DEV_ERROR(vga->dev, "transfer timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		cnt = zx_readl(vga->mmio + VGA_RXF_STATUS);
> +		cnt = (cnt & VGA_RXF_COUNT_MASK) >> VGA_RXF_COUNT_SHIFT;
> +		/* FIFO status may report more data than we need to read */
> +		cnt = min_t(u32, len, cnt);
> +
> +		for (i = 0; i < cnt; i++)
> +			*buf++ = zx_readl(vga->mmio + VGA_DATA);
> +
> +		len -= cnt;
> +		offset += cnt;
> +	}
> +
> +	return 0;
> +}
> +
> +static int zx_vga_i2c_write(struct zx_vga *vga, struct i2c_msg *msg)
> +{
> +	/*
> +	 * The DDC I2C adapter is only for reading EDID data, so we assume
> +	 * that the write to this adapter must be the EDID data offset.
> +	 */
> +	if ((msg->len != 1) || ((msg->addr != DDC_ADDR)))
> +		return -EINVAL;
> +
> +	/* Hardware will take care of the slave address shifting */
> +	zx_writel(vga->mmio + VGA_DEVICE_ADDR, msg->addr);
> +
> +	return 0;
> +}
> +
> +static int zx_vga_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
> +			   int num)
> +{
> +	struct zx_vga *vga = i2c_get_adapdata(adap);
> +	struct zx_vga_i2c *ddc = vga->ddc;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock(&ddc->lock);
> +
> +	for (i = 0; i < num; i++) {
> +		if (msgs[i].flags & I2C_M_RD)
> +			ret = zx_vga_i2c_read(vga, &msgs[i]);
> +		else
> +			ret = zx_vga_i2c_write(vga, &msgs[i]);
> +
> +		if (ret < 0)
> +			break;
> +	}
> +
> +	if (!ret)
> +		ret = num;
> +
> +	mutex_unlock(&ddc->lock);
> +
> +	return ret;
> +}
> +
> +static u32 zx_vga_i2c_func(struct i2c_adapter *adapter)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +static const struct i2c_algorithm zx_vga_algorithm = {
> +	.master_xfer	= zx_vga_i2c_xfer,
> +	.functionality	= zx_vga_i2c_func,
> +};
> +
> +static int zx_vga_ddc_register(struct zx_vga *vga)
> +{
> +	struct device *dev = vga->dev;
> +	struct i2c_adapter *adap;
> +	struct zx_vga_i2c *ddc;
> +	int ret;
> +
> +	ddc = devm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL);
> +	if (!ddc)
> +		return -ENOMEM;
> +
> +	vga->ddc = ddc;
> +	mutex_init(&ddc->lock);
> +
> +	adap = &ddc->adap;
> +	adap->owner = THIS_MODULE;
> +	adap->class = I2C_CLASS_DDC;
> +	adap->dev.parent = dev;
> +	adap->algo = &zx_vga_algorithm;
> +	snprintf(adap->name, sizeof(adap->name), "zx vga i2c");
> +
> +	ret = i2c_add_adapter(adap);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to add I2C adapter: %d\n", ret);
> +		return ret;
> +	}
> +
> +	i2c_set_adapdata(adap, vga);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t zx_vga_irq_thread(int irq, void *dev_id)
> +{
> +	struct zx_vga *vga = dev_id;
> +
> +	drm_helper_hpd_irq_event(vga->connector.dev);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t zx_vga_irq_handler(int irq, void *dev_id)
> +{
> +	struct zx_vga *vga = dev_id;
> +	u32 status;
> +
> +	status = zx_readl(vga->mmio + VGA_I2C_STATUS);
> +
> +	/* Clear interrupt status */
> +	zx_writel_mask(vga->mmio + VGA_I2C_STATUS, VGA_CLEAR_IRQ,
> +		       VGA_CLEAR_IRQ);
> +
> +	if (status & VGA_DEVICE_CONNECTED) {
> +		/*
> +		 * Since VGA_DETECT_SEL bits need to be reset for switching DDC
> +		 * bus from device detection to EDID read, rather than setting
> +		 * up HAS_DEVICE bit here, we need to do that in .get_modes
> +		 * hook for unplug detecting after EDID read succeeds.
> +		 */
> +		vga->connected = true;
> +		return IRQ_WAKE_THREAD;
> +	}
> +
> +	if (status & VGA_DEVICE_DISCONNECTED) {
> +		spin_lock(&vga->lock);
> +		zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL,
> +			  VGA_DETECT_SEL_NO_DEVICE);
> +		spin_unlock(&vga->lock);

I think you still have the race here. If you get a disconnect between get_edid
successfully finishing, and resetting the DETECT_SEL register, you will end up
with the device being disconnected and DETECT_SEL == VGA_DETECT_SEL_HAS_DEVICE.

In order to close this, you'll need to hold the lock across the edid read.

Sean


> +		vga->connected = false;
> +		return IRQ_WAKE_THREAD;
> +	}
> +
> +	if (status & VGA_TRANS_DONE) {
> +		complete(&vga->complete);
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static void zx_vga_hw_init(struct zx_vga *vga)
> +{
> +	unsigned long ref = clk_get_rate(vga->i2c_wclk);
> +	int div;
> +
> +	/*
> +	 * Set up I2C fast speed divider per formula below to get 400kHz.
> +	 *   scl = ref / ((div + 1) * 4)
> +	 */
> +	div = DIV_ROUND_UP(ref / 1000, 400 * 4) - 1;
> +	zx_writel(vga->mmio + VGA_CLK_DIV_FS, div);
> +
> +	/* Set up device detection */
> +	zx_writel(vga->mmio + VGA_AUTO_DETECT_PARA, 0x80);
> +	zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, VGA_DETECT_SEL_NO_DEVICE);
> +
> +	/*
> +	 * We need to poke monitor via DDC bus to get connection irq
> +	 * start working.
> +	 */
> +	zx_writel(vga->mmio + VGA_DEVICE_ADDR, DDC_ADDR);
> +	zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_TRANS, VGA_CMD_TRANS);
> +}
> +
> +static int zx_vga_bind(struct device *dev, struct device *master, void *data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct drm_device *drm = data;
> +	struct resource *res;
> +	struct zx_vga *vga;
> +	int irq;
> +	int ret;
> +
> +	vga = devm_kzalloc(dev, sizeof(*vga), GFP_KERNEL);
> +	if (!vga)
> +		return -ENOMEM;
> +
> +	vga->dev = dev;
> +	dev_set_drvdata(dev, vga);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	vga->mmio = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(vga->mmio))
> +		return PTR_ERR(vga->mmio);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	vga->i2c_wclk = devm_clk_get(dev, "i2c_wclk");
> +	if (IS_ERR(vga->i2c_wclk)) {
> +		ret = PTR_ERR(vga->i2c_wclk);
> +		DRM_DEV_ERROR(dev, "failed to get i2c_wclk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = zx_vga_pwrctrl_init(vga);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to init power control: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = zx_vga_ddc_register(vga);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = zx_vga_register(drm, vga);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to register vga: %d\n", ret);
> +		return ret;
> +	}
> +
> +	init_completion(&vga->complete);
> +	spin_lock_init(&vga->lock);
> +
> +	ret = devm_request_threaded_irq(dev, irq, zx_vga_irq_handler,
> +					zx_vga_irq_thread, IRQF_SHARED,
> +					dev_name(dev), vga);
> +	if (ret) {
> +		DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(vga->i2c_wclk);
> +	if (ret)
> +		return ret;
> +
> +	zx_vga_hw_init(vga);
> +
> +	return 0;
> +}
> +
> +static void zx_vga_unbind(struct device *dev, struct device *master,
> +			  void *data)
> +{
> +	struct zx_vga *vga = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(vga->i2c_wclk);
> +}
> +
> +static const struct component_ops zx_vga_component_ops = {
> +	.bind = zx_vga_bind,
> +	.unbind = zx_vga_unbind,
> +};
> +
> +static int zx_vga_probe(struct platform_device *pdev)
> +{
> +	return component_add(&pdev->dev, &zx_vga_component_ops);
> +}
> +
> +static int zx_vga_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &zx_vga_component_ops);
> +	return 0;
> +}
> +
> +static const struct of_device_id zx_vga_of_match[] = {
> +	{ .compatible = "zte,zx296718-vga", },
> +	{ /* end */ },
> +};
> +MODULE_DEVICE_TABLE(of, zx_vga_of_match);
> +
> +struct platform_driver zx_vga_driver = {
> +	.probe = zx_vga_probe,
> +	.remove = zx_vga_remove,
> +	.driver	= {
> +		.name = "zx-vga",
> +		.of_match_table	= zx_vga_of_match,
> +	},
> +};
> diff --git a/drivers/gpu/drm/zte/zx_vga_regs.h b/drivers/gpu/drm/zte/zx_vga_regs.h
> new file mode 100644
> index 000000000000..feaa345fe6a6
> --- /dev/null
> +++ b/drivers/gpu/drm/zte/zx_vga_regs.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (C) 2017 Sanechips Technology Co., Ltd.
> + * Copyright 2017 Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ZX_VGA_REGS_H__
> +#define __ZX_VGA_REGS_H__
> +
> +#define VGA_CMD_CFG			0x04
> +#define VGA_CMD_TRANS			BIT(6)
> +#define VGA_CMD_COMBO			BIT(5)
> +#define VGA_CMD_RW			BIT(4)
> +#define VGA_SUB_ADDR			0x0c
> +#define VGA_DEVICE_ADDR			0x10
> +#define VGA_CLK_DIV_FS			0x14
> +#define VGA_RXF_CTRL			0x20
> +#define VGA_RX_FIFO_CLEAR		BIT(7)
> +#define VGA_DATA			0x24
> +#define VGA_I2C_STATUS			0x28
> +#define VGA_DEVICE_DISCONNECTED		BIT(7)
> +#define VGA_DEVICE_CONNECTED		BIT(6)
> +#define VGA_CLEAR_IRQ			BIT(4)
> +#define VGA_TRANS_DONE			BIT(0)
> +#define VGA_RXF_STATUS			0x30
> +#define VGA_RXF_COUNT_SHIFT		2
> +#define VGA_RXF_COUNT_MASK		GENMASK(7, 2)
> +#define VGA_AUTO_DETECT_PARA		0x34
> +#define VGA_AUTO_DETECT_SEL		0x38
> +#define VGA_DETECT_SEL_HAS_DEVICE	BIT(1)
> +#define VGA_DETECT_SEL_NO_DEVICE	BIT(0)
> +
> +#endif /* __ZX_VGA_REGS_H__ */
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> index 2a2d90bd9425..cc5bdfc53e8e 100644
> --- a/drivers/gpu/drm/zte/zx_vou.c
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -23,6 +23,7 @@
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drmP.h>
>  
> +#include "zx_common_regs.h"
>  #include "zx_drm_drv.h"
>  #include "zx_plane.h"
>  #include "zx_vou.h"
> @@ -122,6 +123,8 @@ struct zx_crtc {
>  	struct drm_plane *primary;
>  	struct zx_vou_hw *vou;
>  	void __iomem *chnreg;
> +	void __iomem *chncsc;
> +	void __iomem *dither;
>  	const struct zx_crtc_regs *regs;
>  	const struct zx_crtc_bits *bits;
>  	enum vou_chn_type chn_type;
> @@ -204,6 +207,11 @@ struct vou_inf {
>  		.clocks_en_bits = BIT(15),
>  		.clocks_sel_bits = BIT(11) | BIT(0),
>  	},
> +	[VOU_VGA] = {
> +		.data_sel = VOU_RGB_888,
> +		.clocks_en_bits = BIT(1),
> +		.clocks_sel_bits = BIT(10),
> +	},
>  };
>  
>  static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
> @@ -227,9 +235,26 @@ void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
>  	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
>  	struct zx_vou_hw *vou = zcrtc->vou;
>  	struct vou_inf *inf = &vou_infs[id];
> +	void __iomem *dither = zcrtc->dither;
> +	void __iomem *csc = zcrtc->chncsc;
>  	bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
>  	u32 data_sel_shift = id << 1;
>  
> +	if (inf->data_sel != VOU_YUV444) {
> +		/* Enable channel CSC for RGB output */
> +		zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
> +			       CSC_BT709_IMAGE_YCBCR2RGB << CSC_COV_MODE_SHIFT);
> +		zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE,
> +			       CSC_WORK_ENABLE);
> +
> +		/* Bypass Dither block for RGB output */
> +		zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
> +			       DITHER_BYSPASS);
> +	} else {
> +		zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
> +		zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
> +	}
> +
>  	/* Select data format */
>  	zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
>  		       inf->data_sel << data_sel_shift);
> @@ -502,20 +527,24 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>  
>  	if (chn_type == VOU_CHN_MAIN) {
>  		zplane->layer = vou->osd + MAIN_GL_OFFSET;
> -		zplane->csc = vou->osd + MAIN_CSC_OFFSET;
> +		zplane->csc = vou->osd + MAIN_GL_CSC_OFFSET;
>  		zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
>  		zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
>  		zplane->bits = &zx_gl_bits[0];
>  		zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
> +		zcrtc->chncsc = vou->osd + MAIN_CHN_CSC_OFFSET;
> +		zcrtc->dither = vou->osd + MAIN_DITHER_OFFSET;
>  		zcrtc->regs = &main_crtc_regs;
>  		zcrtc->bits = &main_crtc_bits;
>  	} else {
>  		zplane->layer = vou->osd + AUX_GL_OFFSET;
> -		zplane->csc = vou->osd + AUX_CSC_OFFSET;
> +		zplane->csc = vou->osd + AUX_GL_CSC_OFFSET;
>  		zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
>  		zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
>  		zplane->bits = &zx_gl_bits[1];
>  		zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
> +		zcrtc->chncsc = vou->osd + AUX_CHN_CSC_OFFSET;
> +		zcrtc->dither = vou->osd + AUX_DITHER_OFFSET;
>  		zcrtc->regs = &aux_crtc_regs;
>  		zcrtc->bits = &aux_crtc_bits;
>  	}
> diff --git a/drivers/gpu/drm/zte/zx_vou_regs.h b/drivers/gpu/drm/zte/zx_vou_regs.h
> index c066ef123434..5a218351b497 100644
> --- a/drivers/gpu/drm/zte/zx_vou_regs.h
> +++ b/drivers/gpu/drm/zte/zx_vou_regs.h
> @@ -13,13 +13,17 @@
>  
>  /* Sub-module offset */
>  #define MAIN_GL_OFFSET			0x130
> -#define MAIN_CSC_OFFSET			0x580
> +#define MAIN_GL_CSC_OFFSET		0x580
> +#define MAIN_CHN_CSC_OFFSET		0x6c0
>  #define MAIN_HBSC_OFFSET		0x820
> +#define MAIN_DITHER_OFFSET		0x960
>  #define MAIN_RSZ_OFFSET			0x600 /* OTFPPU sub-module */
>  
>  #define AUX_GL_OFFSET			0x200
> -#define AUX_CSC_OFFSET			0x5d0
> +#define AUX_GL_CSC_OFFSET		0x5d0
> +#define AUX_CHN_CSC_OFFSET		0x710
>  #define AUX_HBSC_OFFSET			0x860
> +#define AUX_DITHER_OFFSET		0x970
>  #define AUX_RSZ_OFFSET			0x800
>  
>  #define OSD_VL0_OFFSET			0x040
> @@ -78,6 +82,10 @@
>  #define CHN_INTERLACE_BUF_CTRL		0x24
>  #define CHN_INTERLACE_EN		BIT(2)
>  
> +/* Dither registers */
> +#define OSD_DITHER_CTRL0		0x00
> +#define DITHER_BYSPASS			BIT(31)
> +
>  /* TIMING_CTRL registers */
>  #define TIMING_TC_ENABLE		0x04
>  #define AUX_TC_EN			BIT(1)
> -- 
> 1.9.1

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH V2 2/4] pwm: tegra: Increase precision in pwm rate calculation
From: Laxman Dewangan @ 2017-04-06 17:03 UTC (permalink / raw)
  To: Thierry Reding
  Cc: robh+dt, jonathanh, mark.rutland, linux-pwm, devicetree,
	linux-tegra, linux-kernel
In-Reply-To: <20170406162417.GB19312@ulmo.ba.sec>

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


On Thursday 06 April 2017 09:54 PM, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Thu, Apr 06, 2017 at 07:50:59PM +0530, Laxman Dewangan wrote:
>> The rate of the PWM calculated as follows:
>> 	hz = NSEC_PER_SEC / period_ns;
>>   	rate = (rate + (hz / 2)) / hz;
>>
>> This has the precision loss in lower PWM rate.
>> Changing this to have more precision as:
>> 	hz = DIV_ROUND_CLOSE(NSEC_PER_SEC * 100, period_ns);
>> 	rate = DIV_ROUND_CLOSE(rate * 100, hz)
> DIV_ROUND_CLOSEST(). And I much prefer this to the actual code below. I
> don't think it's necessary to have a local variable for the precision.
Do you suggest to use DIV_ROUND_CLOSEST() instead of 
DIV_ROUND_CLOSEST_ULL()?

This is ULL division and so we need to use this one.

Or am I missing something

[-- Attachment #2: Type: text/html, Size: 1288 bytes --]

^ 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