All of lore.kernel.org
 help / color / mirror / Atom feed
* [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
@ 2015-02-05 20:53 Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 01/10] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
                   ` (7 more replies)
  0 siblings, 8 replies; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

This patch series adds support for I2S audio playback on the Qualcomm
Technologies ipq806x SOC.

The ipq806x SOC has audio-related hardware blocks in its low-power audio
subsystem (or LPASS).  One of the relevant blocks in the LPASS is its low-power
audio interface (or LPAIF).  This contains an MI2S port, which is what these
drivers are configured to use.  The LPAIF also contains a DMA engine that is
dedicated to moving audio samples into the transmit FIFO of the MI2S port.  In
addition, there is also low-power memory (LPM) within the audio subsystem, which
is used for buffering the audio samples.

The development board being used for testing contains the ipq806x SOC and a
Maxim max98357a DAC/amp.  One bus from the MI2S port of the SOC is connected to
the DAC/amp for stereo playback.  This bus is configured so that the SOC is bus
master and consists of DATA, LRCLK, and BCLK.  The DAC/amp does not need MCLK to
operate.  In addition, a single GPIO pin from the SOC is connected to the same
DAC/amp, which gives enable/disable control over the DAC/amp.

The specific drivers added are:
  * a codec DAI driver for controlling the DAC/amp
  * a CPU DAI driver for controlling the MI2S port
  * a platform driver for controlling the LPAIF DMA engine

These drivers, together, are tied into simple-audio-card to complete the audio
implementation.  Corresponding additions to the device tree for the ipq806x SOC
and its documentation has also been added.  Also, as this is a new directory,
the MAINTAINERS file has been updated as well.

The LPASS also contains clocks that need to be controlled.  Those drivers have
been submitted as a separate patch series:  
  [PATCH v3 0/8] qcom audio clock control drivers
  http://lkml.org/lkml/2015/1/19/656

= Changes since V3
  [Patch V3 00/10] ASoC: QCOM: Add support for ipq806x SOC
  http://mailman.alsa-project.org/pipermail/alsa-devel/2014-December/085694.html

  * Placed the content of the inline functions into the callbacks.
  * Replaced use of readl/writel register access functions with regmap access
    functions.  Notable exception is the ISR, which uses ioread32/iowrite32.
  * Rearranged the sequencing of the hardware block enables to fit within the
    ASoC framework callbacks, while remaining functional.
    REQ 1: The hardware requires the enable sequence to be:
              LPAIF-DMA[enable],then LPAIF-MI2S[enable], then DAC-GPIO[enable]
    REQ 2: The hardware requires the disable sequence to be:
              DAC-GPIO[disable], then LPAIF-MI2S[disable]
  * Corrected the implementation of the pointer callback.
  * Utilize the LPM to buffer audio samples, rather than memory external to
    LPASS.
  * Corrected the interrupt clearing in the ISR.
  * Implemented a default system clock (defined by the simple-card DT node), and
    optional LPASS DT node modifiers that can alter the system clock in order to
    expand the range of available bit clock frequencies.
  * Addressed all of the remaining issues raised by Mark Brown.
  * General code cleanup.

= Changes since V2
  [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC
  http://mailman.alsa-project.org/pipermail/alsa-devel/2014-December/085186.html

  * Removed the PCM platform driver from the DTS platform and tied it to the CPU
    DAI driver.
  * Changed I2S pinctrl to use generic naming convention and moved control to
    CPU DAI driver.  It should be controlled now by soc-core's pinctrl_pm_*
    functionality.
  * Added stub DAPM support in codec driver.  As the DAC GPIO needs to be
    enabled last when starting playback, and disabled first when stopping
    playback, it seems as though the trigger function may be the place for this.
    Suggestions are welcome for a better place to put this.
  * Removed machine driver and tied DAI drivers to simple-audio-card.
  * Packaged the build files and Maxim codec files together in one change.
  * Removed QCOM as vendor from Maxim code and documentation.
  * Separated the SOC and board definitions into the correct DTS files.
  * Update device tree documentation to reflect changes.
  * General code cleanup.

= Changes since V1
  [PATCH 0/9] ASoC: QCOM: Add support for ipq806x SOC
  http://mailman.alsa-project.org/pipermail/alsa-devel/2014-November/084322.html

  * Remove the native LPAIF driver, and move its functionality to the CPU DAI
    driver.
  * Add a codec driver to manage the pins going to the external DAC (previously
    managed by the machine driver).
  * Use devm_* and dev_* where possible.
  * ISR only handles relevant DMA channel now.
  * Update device tree documentation to reflect changes.
  * General code cleanup.

Kenneth Westfield (10):
  MAINTAINERS: Add QCOM audio ASoC maintainer
  ASoC: max98357a: Document MAX98357A bindings
  ASoC: qcom: Document LPASS CPU bindings
  ASoC: codec: Add MAX98357A codec driver
  ASoC: ipq806x: add LPASS header files
  ASoC: ipq806x: Add LPASS CPU DAI driver
  ASoC: ipq806x: Add LPASS platform driver
  ASoC: qcom: Add ability to build QCOM drivers
  ASoC: Allow for building QCOM drivers
  ARM: dts: Model IPQ LPASS audio hardware

 .../devicetree/bindings/sound/max98357a.txt        |  14 +
 .../devicetree/bindings/sound/qcom,lpass-cpu.txt   |  66 +++
 MAINTAINERS                                        |   7 +
 arch/arm/boot/dts/qcom-ipq8064.dtsi                |  23 +
 sound/soc/Kconfig                                  |   1 +
 sound/soc/Makefile                                 |   1 +
 sound/soc/codecs/Kconfig                           |   4 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/max98357a.c                       | 138 +++++
 sound/soc/qcom/Kconfig                             |  27 +
 sound/soc/qcom/Makefile                            |   6 +
 sound/soc/qcom/lpass-cpu.c                         | 557 +++++++++++++++++++++
 sound/soc/qcom/lpass-lpaif-ipq806x.h               | 170 +++++++
 sound/soc/qcom/lpass-platform.c                    | 514 +++++++++++++++++++
 sound/soc/qcom/lpass.h                             |  64 +++
 15 files changed, 1594 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/max98357a.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt
 create mode 100644 sound/soc/codecs/max98357a.c
 create mode 100644 sound/soc/qcom/Kconfig
 create mode 100644 sound/soc/qcom/Makefile
 create mode 100644 sound/soc/qcom/lpass-cpu.c
 create mode 100644 sound/soc/qcom/lpass-lpaif-ipq806x.h
 create mode 100644 sound/soc/qcom/lpass-platform.c
 create mode 100644 sound/soc/qcom/lpass.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
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	[flat|nested] 27+ messages in thread

* [Patch V4 01/10] MAINTAINERS: Add QCOM audio ASoC maintainer
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings Kenneth Westfield
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add maintainers for the Qualcomm Technologies
sound drivers.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f1763c50f071a19df82ef6980c2c6e7f18cbc280..4cb829d0bd0ef452e23a687d9b9ec726e6dd0633 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5183,6 +5183,13 @@ F:	drivers/char/ipmi/
 F:	include/linux/ipmi*
 F:	include/uapi/linux/ipmi*
 
+QCOM AUDIO (ASoC) DRIVERS
+M:	Patrick Lai <plai@codeaurora.org>
+M:	Banajit Goswami <bgoswami@codeaurora.org>
+L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:	Supported
+F:	sound/soc/qcom/
+
 IPS SCSI RAID DRIVER
 M:	Adaptec OEM Raid Solutions <aacraid@adaptec.com>
 L:	linux-scsi@vger.kernel.org
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 01/10] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
  2015-02-06 22:12   ` Mark Brown
  2015-02-05 20:53 ` [Patch V4 04/10] ASoC: codec: Add MAX98357A codec driver Kenneth Westfield
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add documentation to the sound directory of the
device-tree bindings for the Maxim MAX98357A audio
DAC.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 Documentation/devicetree/bindings/sound/max98357a.txt | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/max98357a.txt

diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a7a149a236e55b8372b7cb3622cd6a6c664d4e2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98357a.txt
@@ -0,0 +1,14 @@
+Maxim MAX98357A audio DAC
+
+This node models the Maxim MAX98357A DAC.
+
+Required properties:
+- compatible   : "maxim,max98357a"
+- sdmode-gpios : GPIO specifier for the GPIO -> DAC SDMODE pin
+
+Example:
+
+max98357a {
+	compatible = "maxim,max98357a";
+	sdmode-gpios = <&qcom_pinmux 25 0>;
+};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-02-05 20:53   ` Kenneth Westfield
  2015-02-06 22:18     ` Mark Brown
  2015-02-05 20:53   ` [Patch V4 05/10] ASoC: ipq806x: add LPASS header files Kenneth Westfield
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add documentation to the sound directory of the
device-tree bindings for the IPQ806x LPASS CPU DAI
device.

Signed-off-by: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Banajit Goswami <bgoswami-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 .../devicetree/bindings/sound/qcom,lpass-cpu.txt   | 66 ++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt

diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7406ae52aec196f136883eb01afbc6c425bdc465
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt
@@ -0,0 +1,66 @@
+* Qualcomm Technologies LPASS CPU DAI
+
+This node models the Qualcomm Technologies LPASS DAI ports.
+
+Required properties:
+
+- compatible		: "qcom,lpass-cpu"
+- clocks		: Must contain an entry for each entry in clock-names.
+- clock-names		: A list which must include the following entries:
+				* "ahbix-clk"
+				* "mi2s-osr-clk"
+				* "mi2s-bit-clk"
+- interrupts		: Must contain an entry for each entry in
+			  interrupt-names.
+- interrupt-names	: A list which must include the following entries:
+				* "lpass-irq-lpaif"
+- pinctrl-N		: One property must exist for each entry in
+			  pinctrl-names.  See ../pinctrl/pinctrl-bindings.txt
+			  for details of the property values.
+- pinctrl-names		: Must contain a "default" entry.
+- reg			: Must contain an address for each entry in reg-names.
+- reg-names		: A list which must include the following entries:
+				* "lpass-lpaif"
+				* "lpass-lpm"
+
+Optional properties:
+
+- qcom,system-clock-shift		: Add this bool property if the default
+					  frequency of the system clock needs to
+					  be reduced.
+- qcom,system-clock-shift-compare	: A numerical value used to right-shift
+					  the default system clock frequency for
+					  comparison with the target bit clock
+					  frequency.
+- qcom,system-clock-shift-amount	: A numerical value used to right-shift
+					  the default system clock frequency.
+- qcom,alternate-sysclk			: Add this bool property if the default
+					  frequency of the system clock cannot
+					  divide down to the target bit clock
+					  frequency.
+- qcom,alternate-sysclk-bitwidth	: A numerical value representing the
+					  sample bitwidth which requires use of
+					  the alternate system clock frequency.
+- qcom,alternate-sysclk-frequency	: A numerical value representing the new
+					  system clock frequency to use.
+
+Example:
+
+lpass-cpu@28100000 {
+	compatible = "qcom,lpass-cpu";
+	clocks = <&lcc AHBIX_CLK>, <&lcc MI2S_OSR_CLK>, <&lcc MI2S_BIT_CLK>;
+	clock-names = "ahbix-clk", "mi2s-osr-clk", "mi2s-bit-clk";
+	interrupts = <0 85 1>;
+	interrupt-names = "lpass-irq-lpaif";
+	pinctrl-names = "default", "idle";
+	pinctrl-0 = <&mi2s_default>;
+	pinctrl-1 = <&mi2s_idle>;
+	reg = <0x28100000 0x10000>, <0x28400000 0x4000>;
+	reg-names = "lpass-lpaif", "lpass-lpm";
+	qcom,system-clock-shift;
+	qcom,system-clock-shift-compare = <4>;
+	qcom,system-clock-shift-amount = <3>;
+	qcom,alternate-sysclk;
+	qcom,alternate-systclk-bitwidth = <24>;
+	qcom,alternate-systclk-frequency = <4608000>;
+};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
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	[flat|nested] 27+ messages in thread

* [Patch V4 04/10] ASoC: codec: Add MAX98357A codec driver
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 01/10] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
  2015-02-06 22:13   ` Mark Brown
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add codec driver for the Maxim MAX98357A DAC.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/codecs/Kconfig     |   4 ++
 sound/soc/codecs/Makefile    |   2 +
 sound/soc/codecs/max98357a.c | 138 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 sound/soc/codecs/max98357a.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3190eed43c38d8145536d1804f7686b108f97641..064e6c18e10923fd75609b750405dbc33f9db6af 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -69,6 +69,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98090 if I2C
 	select SND_SOC_MAX98095 if I2C
+	select SND_SOC_MAX98357A
 	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9768 if I2C
 	select SND_SOC_MAX9877 if I2C
@@ -456,6 +457,9 @@ config SND_SOC_MAX98090
 config SND_SOC_MAX98095
        tristate
 
+config SND_SOC_MAX98357A
+       tristate
+
 config SND_SOC_MAX9850
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bbdfd1e1c182f9ee102f532f391f522e77a8922b..69b8666d187a0e8d1e2a532e68e2509acc95da7e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -64,6 +64,7 @@ snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
 snd-soc-max98095-objs := max98095.o
+snd-soc-max98357a-objs := max98357a.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
@@ -245,6 +246,7 @@ obj-$(CONFIG_SND_SOC_MAX9768)	+= snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98090)	+= snd-soc-max98090.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
+obj-$(CONFIG_SND_SOC_MAX98357A)	+= snd-soc-max98357a.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
new file mode 100644
index 0000000000000000000000000000000000000000..98b915314d7a00390060411fb1b910aec6f46e9d
--- /dev/null
+++ b/sound/soc/codecs/max98357a.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * max98357a.c -- MAX98357A ALSA SoC Codec driver
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "max98357a"
+
+static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *dai)
+{
+	struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		gpiod_set_value(sdmode, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		gpiod_set_value(sdmode, 0);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_OUTPUT("Speaker"),
+};
+
+static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
+	{"Speaker", NULL, "SDMode"},
+};
+
+static int max98357a_codec_probe(struct snd_soc_codec *codec)
+{
+	struct gpio_desc *sdmode;
+
+	sdmode = devm_gpiod_get(codec->dev, "sdmode");
+	if (IS_ERR(sdmode)) {
+		dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n",
+				__func__, PTR_ERR(sdmode));
+		return PTR_ERR(sdmode);
+	}
+	gpiod_direction_output(sdmode, 0);
+	snd_soc_codec_set_drvdata(codec, sdmode);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver max98357a_codec_driver = {
+	.probe			= max98357a_codec_probe,
+	.dapm_widgets		= max98357a_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(max98357a_dapm_widgets),
+	.dapm_routes		= max98357a_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(max98357a_dapm_routes),
+};
+
+static struct snd_soc_dai_ops max98357a_dai_ops = {
+	.trigger	= max98357a_daiops_trigger,
+};
+
+static struct snd_soc_dai_driver max98357a_dai_driver = {
+	.name = DRV_NAME,
+	.playback = {
+		.stream_name	= DRV_NAME "-playback",
+		.formats	= SNDRV_PCM_FMTBIT_S16 |
+					SNDRV_PCM_FMTBIT_S24 |
+					SNDRV_PCM_FMTBIT_S32,
+		.rates		= SNDRV_PCM_RATE_8000 |
+					SNDRV_PCM_RATE_16000 |
+					SNDRV_PCM_RATE_48000 |
+					SNDRV_PCM_RATE_96000,
+		.rate_min	= 8000,
+		.rate_max	= 96000,
+		.channels_min	= 1,
+		.channels_max	= 2,
+	},
+	.ops    = &max98357a_dai_ops,
+};
+
+static int max98357a_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver,
+			&max98357a_dai_driver, 1);
+	if (ret)
+		dev_err(&pdev->dev, "%s() error registering codec driver: %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static int max98357a_platform_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id max98357a_device_id[] = {
+	{ .compatible = "maxim," DRV_NAME, },
+	{}
+};
+#endif
+
+static struct platform_driver max98357a_platform_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = of_match_ptr(max98357a_device_id),
+	},
+	.probe	= max98357a_platform_probe,
+	.remove = max98357a_platform_remove,
+};
+module_platform_driver(max98357a_platform_driver);
+
+MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, max98357a_device_id);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 05/10] ASoC: ipq806x: add LPASS header files
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2015-02-05 20:53   ` [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings Kenneth Westfield
@ 2015-02-05 20:53   ` Kenneth Westfield
       [not found]     ` <1423169626-22166-6-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2015-02-05 20:53   ` [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver Kenneth Westfield
  2015-02-06 22:32   ` [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Mark Brown
  3 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add the LPASS header files for ipq806x SOC.  This
includes the register definitions for the ipq806x
LPAIF, and the structure definition for the driver
data.

Signed-off-by: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Banajit Goswami <bgoswami-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 sound/soc/qcom/lpass-lpaif-ipq806x.h | 170 +++++++++++++++++++++++++++++++++++
 sound/soc/qcom/lpass.h               |  64 +++++++++++++
 2 files changed, 234 insertions(+)
 create mode 100644 sound/soc/qcom/lpass-lpaif-ipq806x.h
 create mode 100644 sound/soc/qcom/lpass.h

diff --git a/sound/soc/qcom/lpass-lpaif-ipq806x.h b/sound/soc/qcom/lpass-lpaif-ipq806x.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f6dc74e37a2b182865497585365974703a5a8b8
--- /dev/null
+++ b/sound/soc/qcom/lpass-lpaif-ipq806x.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LPASS_LPAIF_H__
+#define __LPASS_LPAIF_H__
+
+#define LPAIF_BANK_OFFSET		0x1000
+
+/* LPAIF I2S */
+
+#define LPAIF_I2SCTL_REG_BASE		0x0010
+#define LPAIF_I2SCTL_REG_STRIDE		0x4
+#define LPAIF_I2SCTL_REG_ADDR(addr, port) \
+	(LPAIF_I2SCTL_REG_BASE + (addr) + (LPAIF_I2SCTL_REG_STRIDE * (port)))
+
+enum lpaif_i2s_ports {
+	LPAIF_I2S_PORT_MIN		= 0,
+
+	LPAIF_I2S_PORT_CODEC_SPK	= 0,
+	LPAIF_I2S_PORT_CODEC_MIC	= 1,
+	LPAIF_I2S_PORT_SEC_SPK		= 2,
+	LPAIF_I2S_PORT_SEC_MIC		= 3,
+	LPAIF_I2S_PORT_MI2S		= 4,
+
+	LPAIF_I2S_PORT_MAX		= 4,
+	LPAIF_I2S_PORT_NUM		= 5,
+};
+
+#define LPAIF_I2SCTL_REG(port)		LPAIF_I2SCTL_REG_ADDR(0x0, (port))
+
+#define LPAIF_I2SCTL_LOOPBACK_MASK	0x8000
+#define LPAIF_I2SCTL_LOOPBACK_SHIFT	15
+#define LPAIF_I2SCTL_LOOPBACK_DISABLE	(0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
+#define LPAIF_I2SCTL_LOOPBACK_ENABLE	(1 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
+
+#define LPAIF_I2SCTL_SPKEN_MASK		0x4000
+#define LPAIF_I2SCTL_SPKEN_SHIFT	14
+#define LPAIF_I2SCTL_SPKEN_DISABLE	(0 << LPAIF_I2SCTL_SPKEN_SHIFT)
+#define LPAIF_I2SCTL_SPKEN_ENABLE	(1 << LPAIF_I2SCTL_SPKEN_SHIFT)
+
+#define LPAIF_I2SCTL_SPKMODE_MASK	0x3C00
+#define LPAIF_I2SCTL_SPKMODE_SHIFT	10
+#define LPAIF_I2SCTL_SPKMODE_NONE	(0 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_SD0	(1 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_SD1	(2 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_SD2	(3 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_SD3	(4 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_QUAD01	(5 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_QUAD23	(6 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_6CH	(7 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE_8CH	(8 << LPAIF_I2SCTL_SPKMODE_SHIFT)
+
+#define LPAIF_I2SCTL_SPKMONO_MASK	0x0200
+#define LPAIF_I2SCTL_SPKMONO_SHIFT	9
+#define LPAIF_I2SCTL_SPKMONO_STEREO	(0 << LPAIF_I2SCTL_SPKMONO_SHIFT)
+#define LPAIF_I2SCTL_SPKMONO_MONO	(1 << LPAIF_I2SCTL_SPKMONO_SHIFT)
+
+#define LPAIF_I2SCTL_WSSRC_MASK		0x0004
+#define LPAIF_I2SCTL_WSSRC_SHIFT	2
+#define LPAIF_I2SCTL_WSSRC_INTERNAL	(0 << LPAIF_I2SCTL_WSSRC_SHIFT)
+#define LPAIF_I2SCTL_WSSRC_EXTERNAL	(1 << LPAIF_I2SCTL_WSSRC_SHIFT)
+
+#define LPAIF_I2SCTL_BITWIDTH_MASK	0x0003
+#define LPAIF_I2SCTL_BITWIDTH_SHIFT	0
+#define LPAIF_I2SCTL_BITWIDTH_16	(0 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
+#define LPAIF_I2SCTL_BITWIDTH_24	(1 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
+#define LPAIF_I2SCTL_BITWIDTH_32	(2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
+
+/* LPAIF IRQ */
+
+#define LPAIF_IRQ_REG_BASE		0x3000
+#define LPAIF_IRQ_REG_STRIDE		0x1000
+#define LPAIF_IRQ_REG_ADDR(addr, port) \
+	(LPAIF_IRQ_REG_BASE + (addr) + (LPAIF_IRQ_REG_STRIDE * (port)))
+
+enum lpaif_irq_ports {
+	LPAIF_IRQ_PORT_MIN		= 0,
+
+	LPAIF_IRQ_PORT_HOST		= 0,
+	LPAIF_IRQ_PORT_ADSP		= 1,
+
+	LPAIF_IRQ_PORT_MAX		= 2,
+	LPAIF_IRQ_PORT_NUM		= 3,
+};
+
+#define LPAIF_IRQEN_REG(port)		LPAIF_IRQ_REG_ADDR(0x0, (port))
+#define LPAIF_IRQSTAT_REG(port)		LPAIF_IRQ_REG_ADDR(0x4, (port))
+#define LPAIF_IRQCLEAR_REG(port)	LPAIF_IRQ_REG_ADDR(0xC, (port))
+
+#define LPAIF_IRQ_BITSTRIDE		3
+#define LPAIF_IRQ_PER(chan)		(1 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_XRUN(chan)		(2 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_ERR(chan)		(4 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+#define LPAIF_IRQ_ALL(chan)		(7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
+
+/* LPAIF DMA */
+
+#define LPAIF_RDMA_REG_BASE		0x6000
+#define LPAIF_RDMA_REG_STRIDE		0x1000
+#define LPAIF_RDMA_REG_ADDR(addr, chan) \
+	(LPAIF_RDMA_REG_BASE + (addr) + (LPAIF_RDMA_REG_STRIDE * (chan)))
+
+enum lpaif_dma_channels {
+	LPAIF_RDMA_CHAN_MIN		= 0,
+
+	LPAIF_RDMA_CHAN_MI2S		= 0,
+	LPAIF_RDMA_CHAN_PCM0		= 1,
+	LPAIF_RDMA_CHAN_PCM1		= 2,
+
+	LPAIF_RDMA_CHAN_MAX		= 4,
+	LPAIF_RDMA_CHAN_NUM		= 5,
+};
+
+#define LPAIF_RDMACTL_REG(chan)		LPAIF_RDMA_REG_ADDR(0x00, (chan))
+#define LPAIF_RDMABASE_REG(chan)	LPAIF_RDMA_REG_ADDR(0x04, (chan))
+#define	LPAIF_RDMABUFF_REG(chan)	LPAIF_RDMA_REG_ADDR(0x08, (chan))
+#define LPAIF_RDMACURR_REG(chan)	LPAIF_RDMA_REG_ADDR(0x0C, (chan))
+#define	LPAIF_RDMAPER_REG(chan)		LPAIF_RDMA_REG_ADDR(0x10, (chan))
+
+#define LPAIF_RDMACTL_BURSTEN_MASK	0x800
+#define LPAIF_RDMACTL_BURSTEN_SHIFT	11
+#define LPAIF_RDMACTL_BURSTEN_SINGLE	(0 << LPAIF_RDMACTL_BURSTEN_SHIFT)
+#define LPAIF_RDMACTL_BURSTEN_INCR4	(1 << LPAIF_RDMACTL_BURSTEN_SHIFT)
+
+#define LPAIF_RDMACTL_WPSCNT_MASK	0x700
+#define LPAIF_RDMACTL_WPSCNT_SHIFT	8
+#define LPAIF_RDMACTL_WPSCNT_ONE	(0 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+#define LPAIF_RDMACTL_WPSCNT_TWO	(1 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+#define LPAIF_RDMACTL_WPSCNT_THREE	(2 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+#define LPAIF_RDMACTL_WPSCNT_FOUR	(3 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+#define LPAIF_RDMACTL_WPSCNT_SIX	(5 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+#define LPAIF_RDMACTL_WPSCNT_EIGHT	(7 << LPAIF_RDMACTL_WPSCNT_SHIFT)
+
+#define LPAIF_RDMACTL_AUDINTF_MASK	0x0F0
+#define LPAIF_RDMACTL_AUDINTF_SHIFT	4
+#define LPAIF_RDMACTL_AUDINTF_NONE	(0 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_CODEC	(1 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_PCM	(2 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_SEC_I2S	(3 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_MI2S	(4 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_HDMI	(5 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+#define LPAIF_RDMACTL_AUDINTF_SEC_PCM	(7 << LPAIF_RDMACTL_AUDINTF_SHIFT)
+
+#define LPAIF_RDMACTL_FIFOWM_MASK	0x00E
+#define LPAIF_RDMACTL_FIFOWM_SHIFT	1
+#define LPAIF_RDMACTL_FIFOWM_1		(0 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_2		(1 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_3		(2 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_4		(3 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_5		(4 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_6		(5 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_7		(6 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+#define LPAIF_RDMACTL_FIFOWM_8		(7 << LPAIF_RDMACTL_FIFOWM_SHIFT)
+
+#define LPAIF_RDMACTL_ENABLE_MASK	0x1
+#define LPAIF_RDMACTL_ENABLE_SHIFT	0
+#define LPAIF_RDMACTL_ENABLE_OFF	(0 << LPAIF_RDMACTL_ENABLE_SHIFT)
+#define LPAIF_RDMACTL_ENABLE_ON		(1 << LPAIF_RDMACTL_ENABLE_SHIFT)
+
+#endif /* __LPASS_LPAIF_H__ */
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bb7ac5db397dcd0614ee276cc20727bdf55ad64
--- /dev/null
+++ b/sound/soc/qcom/lpass.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LPASS_H__
+#define __LPASS_H__
+
+#define LPASS_AHBIX_CLOCK_FREQUENCY		131072
+
+/* Both the CPU DAI driver and platform driver will access this data */
+struct lpass_data {
+
+	/* clocks inside the low-power audio subsystem (LPASS) domain */
+	struct clk *ahbix_clk;
+	struct clk *mi2s_bit_clk;
+	struct clk *mi2s_osr_clk;
+
+	/* default system (or OSR) clock frequency */
+	unsigned int default_sysclk_freq;
+
+	/*
+	 * if enabled and the target BIT clock frequency is below the range of
+	 * the clock divider, then the system clock needs to be reduced by
+	 * right-shifting the default clock frequency
+	 */
+	bool sysclk_shift_enable;
+	unsigned int sysclk_shift_compare;
+	unsigned int sysclk_shift_amount;
+
+	/*
+	 * if enabled and the target BIT clock frequency can not be accurately
+	 * derived by the clock divider for the given bitwidth, then use an
+	 * alternate system clock frequency
+	 */
+	bool alt_sysclk_enable;
+	unsigned int alt_sysclk_enable_bitwidth;
+	unsigned int alt_sysclk_freq;
+
+	/* memory-mapped registers for the low-power audio interface (LPAIF) */
+	void __iomem *lpaif;
+	struct regmap *lpaif_map;
+
+	/* handle for the low-power audio interface (LPAIF) interrupts */
+	int lpaif_irq;
+
+	/* memory-mapped RAM designated for holding the audio buffer(s) */
+	void __iomem *lpm;
+	dma_addr_t lpm_phys;
+	unsigned int lpm_size;
+	atomic_t lpm_lock;
+};
+
+int asoc_qcom_lpass_platform_register(struct platform_device *);
+
+#endif /* __LPASS_H__ */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
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	[flat|nested] 27+ messages in thread

* [Patch V4 06/10] ASoC: ipq806x: Add LPASS CPU DAI driver
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (3 preceding siblings ...)
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-02-05 20:53 ` Kenneth Westfield
  2015-02-06 22:40   ` Mark Brown
  2015-02-05 20:53 ` [Patch V4 08/10] ASoC: qcom: Add ability to build QCOM drivers Kenneth Westfield
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add the CPU DAI driver for the Qualcomm
Technologies low-power audio subsystem (LPASS).

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/qcom/lpass-cpu.c | 557 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 557 insertions(+)
 create mode 100644 sound/soc/qcom/lpass-cpu.c

diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e58fa628667eca058bfbf35e29085b202f471f6
--- /dev/null
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "lpass-lpaif-ipq806x.h"
+#include "lpass.h"
+
+#define DRV_NAME			"lpass-cpu"
+
+static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+		unsigned int freq, int dir)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+
+	drvdata->default_sysclk_freq = freq;
+
+	return 0;
+}
+
+static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	ret = clk_prepare_enable(drvdata->mi2s_osr_clk);
+	if (ret) {
+		dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(drvdata->mi2s_bit_clk);
+	if (ret) {
+		dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n",
+				__func__, ret);
+		clk_disable_unprepare(drvdata->mi2s_osr_clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+
+	clk_disable_unprepare(drvdata->mi2s_bit_clk);
+	clk_disable_unprepare(drvdata->mi2s_osr_clk);
+}
+
+static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int channels = params_channels(params);
+	unsigned int rate = params_rate(params);
+	unsigned long bclk_freq, oclk_freq;
+	unsigned int regval;
+	int bitwidth, ret;
+
+	bitwidth = snd_pcm_format_width(format);
+	if (bitwidth < 0) {
+		dev_err(dai->dev, "%s() invalid bit width given\n", __func__);
+		return bitwidth;
+	}
+
+	regval = 0;
+	regval |= LPAIF_I2SCTL_LOOPBACK_DISABLE;
+	regval |= LPAIF_I2SCTL_WSSRC_INTERNAL;
+
+	switch (bitwidth) {
+	case 16:
+		regval |= LPAIF_I2SCTL_BITWIDTH_16;
+		break;
+	case 24:
+		regval |= LPAIF_I2SCTL_BITWIDTH_24;
+		break;
+	case 32:
+		regval |= LPAIF_I2SCTL_BITWIDTH_32;
+		break;
+	default:
+		dev_err(dai->dev, "%s() invalid bitwidth given: %u\n",
+				__func__, bitwidth);
+		return -EINVAL;
+	}
+
+	switch (channels) {
+	case 1:
+		regval |= LPAIF_I2SCTL_SPKMODE_SD0;
+		regval |= LPAIF_I2SCTL_SPKMONO_MONO;
+		break;
+	case 2:
+		regval |= LPAIF_I2SCTL_SPKMODE_SD0;
+		regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+		break;
+	case 4:
+		regval |= LPAIF_I2SCTL_SPKMODE_QUAD01;
+		regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+		break;
+	case 6:
+		regval |= LPAIF_I2SCTL_SPKMODE_6CH;
+		regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+		break;
+	case 8:
+		regval |= LPAIF_I2SCTL_SPKMODE_8CH;
+		regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+		break;
+	default:
+		dev_err(dai->dev, "%s() invalid channels given: %u\n",
+				__func__, channels);
+		return -EINVAL;
+	}
+
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), regval);
+	if (ret) {
+		dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	/*
+	 * adjust the OSR clock so that the BIT clock can successfully be
+	 * derived from it by the hardware
+	 */
+	bclk_freq = rate * bitwidth * 2;
+	if (bitwidth == drvdata->alt_sysclk_enable_bitwidth &&
+			drvdata->alt_sysclk_enable)
+		oclk_freq = drvdata->alt_sysclk_freq;
+	else if (!drvdata->sysclk_shift_enable)
+		oclk_freq = drvdata->default_sysclk_freq;
+	else if (bclk_freq >= drvdata->default_sysclk_freq >>
+			drvdata->sysclk_shift_compare)
+		oclk_freq = drvdata->default_sysclk_freq;
+	else
+		oclk_freq = drvdata->default_sysclk_freq >>
+				drvdata->sysclk_shift_amount;
+
+	ret = clk_set_rate(drvdata->mi2s_osr_clk, oclk_freq);
+	if (ret) {
+		dev_err(dai->dev, "%s() error setting mi2s osrclk to %lu: %d\n",
+				__func__, oclk_freq, ret);
+		return ret;
+	}
+
+	ret = clk_set_rate(drvdata->mi2s_bit_clk, bclk_freq);
+	if (ret) {
+		dev_err(dai->dev, "%s() error setting mi2s bitclk to %lu: %d\n",
+				__func__, bclk_freq, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0);
+	if (ret)
+		dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	unsigned int reg, mask, val;
+	int ret;
+
+	reg = LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S);
+	mask = LPAIF_I2SCTL_SPKEN_MASK;
+	val = LPAIF_I2SCTL_SPKEN_ENABLE;
+	ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+	if (ret)
+		dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	unsigned int reg, mask, val;
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		reg = LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S);
+		mask = LPAIF_I2SCTL_SPKEN_MASK;
+		val = LPAIF_I2SCTL_SPKEN_ENABLE;
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret)
+			dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+					__func__, ret);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		reg = LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S);
+		mask = LPAIF_I2SCTL_SPKEN_MASK;
+		val = LPAIF_I2SCTL_SPKEN_DISABLE;
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret)
+			dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+					__func__, ret);
+		break;
+	}
+
+	return ret;
+}
+
+static struct snd_soc_dai_ops lpass_cpu_dai_ops = {
+	.set_sysclk	= lpass_cpu_daiops_set_sysclk,
+	.startup	= lpass_cpu_daiops_startup,
+	.shutdown	= lpass_cpu_daiops_shutdown,
+	.hw_params	= lpass_cpu_daiops_hw_params,
+	.hw_free	= lpass_cpu_daiops_hw_free,
+	.prepare	= lpass_cpu_daiops_prepare,
+	.trigger	= lpass_cpu_daiops_trigger,
+};
+
+static int lpass_cpu_dai_probe(struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	/* ensure audio hardware is disabled */
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0);
+	if (ret)
+		dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static struct snd_soc_dai_driver lpass_cpu_dai_driver = {
+	.playback = {
+		.stream_name	= DRV_NAME "-playback",
+		.formats	= SNDRV_PCM_FMTBIT_S16 |
+					SNDRV_PCM_FMTBIT_S24 |
+					SNDRV_PCM_FMTBIT_S32,
+		.rates		= SNDRV_PCM_RATE_8000 |
+					SNDRV_PCM_RATE_16000 |
+					SNDRV_PCM_RATE_32000 |
+					SNDRV_PCM_RATE_48000 |
+					SNDRV_PCM_RATE_96000,
+		.rate_min	= 8000,
+		.rate_max	= 96000,
+		.channels_min	= 1,
+		.channels_max	= 8,
+	},
+	.probe	= &lpass_cpu_dai_probe,
+	.ops    = &lpass_cpu_dai_ops,
+};
+
+static const struct snd_soc_component_driver lpass_cpu_comp_driver = {
+	.name = DRV_NAME,
+};
+
+static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i)
+		if (reg == LPAIF_I2SCTL_REG(i))
+			return true;
+
+	for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) {
+		if (reg == LPAIF_IRQEN_REG(i))
+			return true;
+		if (reg == LPAIF_IRQCLEAR_REG(i))
+			return true;
+	}
+
+	for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) {
+		if (reg == LPAIF_RDMACTL_REG(i))
+			return true;
+		if (reg == LPAIF_RDMABASE_REG(i))
+			return true;
+		if (reg == LPAIF_RDMABUFF_REG(i))
+			return true;
+		if (reg == LPAIF_RDMAPER_REG(i))
+			return true;
+	}
+
+	return false;
+}
+
+static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i)
+		if (reg == LPAIF_I2SCTL_REG(i))
+			return true;
+
+	for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) {
+		if (reg == LPAIF_IRQEN_REG(i))
+			return true;
+		if (reg == LPAIF_IRQSTAT_REG(i))
+			return true;
+	}
+
+	for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) {
+		if (reg == LPAIF_RDMACTL_REG(i))
+			return true;
+		if (reg == LPAIF_RDMABASE_REG(i))
+			return true;
+		if (reg == LPAIF_RDMABUFF_REG(i))
+			return true;
+		if (reg == LPAIF_RDMACURR_REG(i))
+			return true;
+		if (reg == LPAIF_RDMAPER_REG(i))
+			return true;
+	}
+
+	return false;
+}
+
+static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i)
+		if (reg == LPAIF_IRQSTAT_REG(i))
+			return true;
+
+	for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i)
+		if (reg == LPAIF_RDMACURR_REG(i))
+			return true;
+
+	return false;
+}
+
+static const struct regmap_config lpass_cpu_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MAX),
+	.writeable_reg = lpass_cpu_regmap_writeable,
+	.readable_reg = lpass_cpu_regmap_readable,
+	.volatile_reg = lpass_cpu_regmap_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int lpass_cpu_parse_of(struct device *dev, struct lpass_data *drvdata)
+{
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	if (!np || !of_device_is_available(np)) {
+		dev_err(dev, "%s() no available info for %s\n", __func__,
+				DRV_NAME);
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(np, "qcom,system-clock-shift")) {
+		ret = of_property_read_u32(np,
+				"qcom,system-clock-shift-compare",
+				&drvdata->sysclk_shift_compare);
+		if (ret) {
+			dev_err(dev, "%s() qcom,system-clock-shift-compare not found: %d\n",
+					__func__, ret);
+			return -EINVAL;
+		}
+		ret = of_property_read_u32(np,
+				"qcom,system-clock-shift-amount",
+				&drvdata->sysclk_shift_amount);
+		if (ret) {
+			dev_err(dev, "%s() qcom,system-clock-shift-amount not found: %d\n",
+					__func__, ret);
+			return -EINVAL;
+		}
+		drvdata->sysclk_shift_enable = true;
+	} else {
+		drvdata->sysclk_shift_enable = false;
+	}
+
+	if (of_property_read_bool(np, "qcom,alternate-sysclk")) {
+		ret = of_property_read_u32(np,
+				"qcom,alternate-sysclk-bitwidth",
+				&drvdata->alt_sysclk_enable_bitwidth);
+		if (ret) {
+			dev_err(dev, "%s() qcom,alternate-sysclk-bitwidth not found: %d\n",
+					__func__, ret);
+			return -EINVAL;
+		}
+		ret = of_property_read_u32(np,
+				"qcom,alternate-sysclk-frequency",
+				&drvdata->alt_sysclk_freq);
+		if (ret) {
+			dev_err(dev, "%s() qcom,alternate-sysclk-frequency not found: %d\n",
+					__func__, ret);
+			return -EINVAL;
+		}
+		drvdata->alt_sysclk_enable = true;
+	} else {
+		drvdata->alt_sysclk_enable = false;
+	}
+
+	return 0;
+}
+
+static int lpass_cpu_platform_probe(struct platform_device *pdev)
+{
+	struct lpass_data *drvdata;
+	struct resource *res;
+	int ret;
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct lpass_data),
+			GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drvdata);
+
+	ret = lpass_cpu_parse_of(&pdev->dev, drvdata);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
+	if (!res) {
+		dev_err(&pdev->dev, "%s() error getting resource\n", __func__);
+		return -ENODEV;
+	}
+
+	drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR((void const __force *)drvdata->lpaif)) {
+		dev_err(&pdev->dev, "%s() error mapping reg resource: %ld\n",
+				__func__,
+				PTR_ERR((void const __force *)drvdata->lpaif));
+		return PTR_ERR((void const __force *)drvdata->lpaif);
+	}
+
+	drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif,
+			&lpass_cpu_regmap_config);
+	if (IS_ERR(drvdata->lpaif_map)) {
+		dev_err(&pdev->dev, "%s() error initializing regmap: %ld\n",
+				__func__, PTR_ERR(drvdata->lpaif_map));
+		return PTR_ERR(drvdata->lpaif_map);
+	}
+
+	drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk");
+	if (IS_ERR(drvdata->mi2s_osr_clk)) {
+		dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n",
+				__func__, PTR_ERR(drvdata->mi2s_osr_clk));
+		return PTR_ERR(drvdata->mi2s_osr_clk);
+	}
+
+	drvdata->mi2s_bit_clk = devm_clk_get(&pdev->dev, "mi2s-bit-clk");
+	if (IS_ERR(drvdata->mi2s_bit_clk)) {
+		dev_err(&pdev->dev, "%s() error getting mi2s-bit-clk: %ld\n",
+				__func__, PTR_ERR(drvdata->mi2s_bit_clk));
+		return PTR_ERR(drvdata->mi2s_bit_clk);
+	}
+
+	drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk");
+	if (IS_ERR(drvdata->ahbix_clk)) {
+		dev_err(&pdev->dev, "%s() error getting ahbix-clk: %ld\n",
+				__func__, PTR_ERR(drvdata->ahbix_clk));
+		return PTR_ERR(drvdata->ahbix_clk);
+	}
+
+	ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() error setting rate on ahbix_clk: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(drvdata->ahbix_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() Error enabling ahbix_clk: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+			&lpass_cpu_comp_driver, &lpass_cpu_dai_driver, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n",
+				__func__, ret);
+		goto err_clk;
+	}
+
+	ret = asoc_qcom_lpass_platform_register(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() error registering platform driver: %d\n",
+				__func__, ret);
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	clk_disable_unprepare(drvdata->ahbix_clk);
+	return ret;
+}
+
+static int lpass_cpu_platform_remove(struct platform_device *pdev)
+{
+	struct lpass_data *drvdata = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(drvdata->ahbix_clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id lpass_cpu_device_id[] = {
+	{.compatible = "qcom," DRV_NAME},
+	{}
+};
+#endif
+
+static struct platform_driver lpass_cpu_platform_driver = {
+	.driver	= {
+		.name		= DRV_NAME,
+		.of_match_table	= of_match_ptr(lpass_cpu_device_id),
+	},
+	.probe	= lpass_cpu_platform_probe,
+	.remove	= lpass_cpu_platform_remove,
+};
+module_platform_driver(lpass_cpu_platform_driver);
+
+MODULE_DESCRIPTION("QTi LPASS CPU Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, lpass_cpu_device_id);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2015-02-05 20:53   ` [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings Kenneth Westfield
  2015-02-05 20:53   ` [Patch V4 05/10] ASoC: ipq806x: add LPASS header files Kenneth Westfield
@ 2015-02-05 20:53   ` Kenneth Westfield
  2015-02-06 22:55     ` Mark Brown
  2015-02-06 22:32   ` [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Mark Brown
  3 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add platform driver for the Qualcomm Technologies
low-power audio subsystem (LPASS) ports.

Signed-off-by: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Banajit Goswami <bgoswami-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 sound/soc/qcom/lpass-platform.c | 514 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 514 insertions(+)
 create mode 100644 sound/soc/qcom/lpass-platform.c

diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce526119a2c4a38537e8c9777e0556f15e5a660f
--- /dev/null
+++ b/sound/soc/qcom/lpass-platform.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "lpass-lpaif-ipq806x.h"
+#include "lpass.h"
+
+#define DRV_NAME			"lpass-platform"
+
+#define LPASS_PLATFORM_CHANNELS_MIN	1
+#define LPASS_PLATFORM_CHANNELS_MAX	8
+#define LPASS_PLATFORM_PERIODS_MIN	2
+#define LPASS_PLATFORM_PERIODS_MAX	2
+#define LPASS_PLATFORM_RATE_MIN		8000
+#define LPASS_PLATFORM_RATE_MAX		192000
+
+static struct snd_pcm_hardware lpass_platform_hardware = {
+	.info			=	SNDRV_PCM_INFO_INTERLEAVED |
+					SNDRV_PCM_INFO_PAUSE |
+					SNDRV_PCM_INFO_RESUME,
+	.formats		=	SNDRV_PCM_FMTBIT_S16 |
+					SNDRV_PCM_FMTBIT_S24 |
+					SNDRV_PCM_FMTBIT_S32,
+	.rates			=	SNDRV_PCM_RATE_8000_192000,
+	.rate_min		=	LPASS_PLATFORM_RATE_MIN,
+	.rate_max		=	LPASS_PLATFORM_RATE_MAX,
+	.channels_min		=	LPASS_PLATFORM_CHANNELS_MIN,
+	.channels_max		=	LPASS_PLATFORM_CHANNELS_MAX,
+	.periods_min		=	LPASS_PLATFORM_PERIODS_MIN,
+	.periods_max		=	LPASS_PLATFORM_PERIODS_MAX,
+};
+
+static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	int ret;
+
+	lpass_platform_hardware.buffer_bytes_max = drvdata->lpm_size;
+	lpass_platform_hardware.period_bytes_max =
+		drvdata->lpm_size / LPASS_PLATFORM_PERIODS_MIN;
+	lpass_platform_hardware.period_bytes_min =
+		drvdata->lpm_size / LPASS_PLATFORM_PERIODS_MAX;
+	snd_soc_set_runtime_hwparams(substream, &lpass_platform_hardware);
+
+	runtime->dma_bytes = drvdata->lpm_size;
+
+	ret = snd_pcm_hw_constraint_integer(runtime,
+			SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0) {
+		dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n",
+				__func__, ret);
+		return -EINVAL;
+	}
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+	return 0;
+}
+
+static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int channels = params_channels(params);
+	unsigned int regval;
+	int bitwidth;
+	int ret;
+
+	bitwidth = snd_pcm_format_width(format);
+	if (bitwidth < 0) {
+		dev_err(soc_runtime->dev, "%s() invalid bit width given\n",
+				__func__);
+		return bitwidth;
+	}
+
+	regval = 0;
+	regval |= LPAIF_RDMACTL_BURSTEN_INCR4;
+	regval |= LPAIF_RDMACTL_AUDINTF_MI2S;
+	regval |= LPAIF_RDMACTL_FIFOWM_8;
+
+	switch (bitwidth) {
+	case 16:
+		switch (channels) {
+		case 1:
+		case 2:
+			regval |= LPAIF_RDMACTL_WPSCNT_ONE;
+			break;
+		case 4:
+			regval |= LPAIF_RDMACTL_WPSCNT_TWO;
+			break;
+		case 6:
+			regval |= LPAIF_RDMACTL_WPSCNT_THREE;
+			break;
+		case 8:
+			regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
+			break;
+		default:
+			dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%u, ch=%u\n",
+					__func__, bitwidth, channels);
+			return -EINVAL;
+		}
+		break;
+	case 24:
+	case 32:
+		switch (channels) {
+		case 1:
+			regval |= LPAIF_RDMACTL_WPSCNT_ONE;
+			break;
+		case 2:
+			regval |= LPAIF_RDMACTL_WPSCNT_TWO;
+			break;
+		case 4:
+			regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
+			break;
+		case 6:
+			regval |= LPAIF_RDMACTL_WPSCNT_SIX;
+			break;
+		case 8:
+			regval |= LPAIF_RDMACTL_WPSCNT_EIGHT;
+			break;
+		default:
+			dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%u, ch=%u\n",
+					__func__, bitwidth, channels);
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%u, ch=%u\n",
+				__func__, bitwidth, channels);
+		return -EINVAL;
+	}
+
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), regval);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	int ret;
+
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	unsigned int reg, mask, val;
+	int ret;
+
+	reg = LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S);
+	val = runtime->dma_addr;
+	ret = regmap_write(drvdata->lpaif_map, reg, val);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	reg = LPAIF_RDMABUFF_REG(LPAIF_RDMA_CHAN_MI2S);
+	val = (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1;
+	ret = regmap_write(drvdata->lpaif_map, reg, val);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	reg = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MI2S);
+	val = (snd_pcm_lib_period_bytes(substream) >> 2) - 1;
+	ret = regmap_write(drvdata->lpaif_map, reg, val);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	reg = LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S);
+	mask = LPAIF_RDMACTL_ENABLE_MASK;
+	val = LPAIF_RDMACTL_ENABLE_ON;
+	ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
+		int cmd)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	unsigned int reg, mask, val;
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		/* clear status before enabling interrupts */
+		reg = LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST);
+		val = LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
+		ret = regmap_write(drvdata->lpaif_map, reg, val);
+		if (ret) {
+			dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
+					__func__, ret);
+			return ret;
+		}
+
+		reg = LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST);
+		mask = LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
+		val = LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret) {
+			dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
+					__func__, ret);
+			return ret;
+		}
+
+		reg = LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S);
+		mask = LPAIF_RDMACTL_ENABLE_MASK;
+		val = LPAIF_RDMACTL_ENABLE_ON;
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret) {
+			dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+					__func__, ret);
+			return ret;
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		reg = LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S);
+		mask = LPAIF_RDMACTL_ENABLE_MASK;
+		val = LPAIF_RDMACTL_ENABLE_OFF;
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret) {
+			dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+					__func__, ret);
+			return ret;
+		}
+
+		reg = LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST);
+		mask = LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
+		val = 0;
+		ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);
+		if (ret) {
+			dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
+					__func__, ret);
+			return ret;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
+		struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+			snd_soc_platform_get_drvdata(soc_runtime->platform);
+	unsigned int base_addr, curr_addr;
+	int ret;
+
+	ret = regmap_read(drvdata->lpaif_map,
+			LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), &base_addr);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = regmap_read(drvdata->lpaif_map,
+			LPAIF_RDMACURR_REG(LPAIF_RDMA_CHAN_MI2S), &curr_addr);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return bytes_to_frames(substream->runtime, curr_addr - base_addr);
+}
+
+static struct snd_pcm_ops lpass_platform_pcm_ops = {
+	.open		= lpass_platform_pcmops_open,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= lpass_platform_pcmops_hw_params,
+	.hw_free	= lpass_platform_pcmops_hw_free,
+	.prepare	= lpass_platform_pcmops_prepare,
+	.trigger	= lpass_platform_pcmops_trigger,
+	.pointer	= lpass_platform_pcmops_pointer,
+};
+
+static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
+{
+	struct snd_pcm_substream *substream = data;
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	const u32 status_offset = LPAIF_IRQSTAT_REG(LPAIF_IRQ_PORT_HOST);
+	const u32 clear_offset = LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST);
+	const u32 period_bitmask = LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S);
+	const u32 xrun_bitmask = LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S);
+	const u32 error_bitmask = LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S);
+	const u32 chan_bitmask = LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
+	u32 interrupts;
+	irqreturn_t ret = IRQ_NONE;
+
+	interrupts = ioread32(drvdata->lpaif + status_offset) & chan_bitmask;
+
+	if (likely(interrupts & period_bitmask)) {
+		iowrite32(period_bitmask, drvdata->lpaif + clear_offset);
+		snd_pcm_period_elapsed(substream);
+		ret = IRQ_HANDLED;
+	}
+
+	if (unlikely(interrupts & xrun_bitmask)) {
+		iowrite32(xrun_bitmask, drvdata->lpaif + clear_offset);
+		dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__);
+		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		ret = IRQ_HANDLED;
+	}
+
+	if (unlikely(interrupts & error_bitmask)) {
+		iowrite32(error_bitmask, drvdata->lpaif + clear_offset);
+		dev_err(soc_runtime->dev, "%s() bus access error\n", __func__);
+		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream,
+		struct snd_soc_pcm_runtime *soc_runtime)
+{
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+
+	if (atomic_cmpxchg(&drvdata->lpm_lock, 0, 1)) {
+		dev_err(soc_runtime->dev, "%s() buffer already in use\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = soc_runtime->dev;
+	buf->private_data = NULL;
+	buf->area = (unsigned char __force *)drvdata->lpm;
+	buf->addr = drvdata->lpm_phys;
+	buf->bytes = drvdata->lpm_size;
+
+	return 0;
+}
+
+static void lpass_platform_free_buffer(struct snd_pcm_substream *substream,
+		struct snd_soc_pcm_runtime *soc_runtime)
+{
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+
+	if (buf->area == (unsigned char __force *)drvdata->lpm) {
+		buf->area = NULL;
+		atomic_dec(&drvdata->lpm_lock);
+	} else {
+		dev_warn(soc_runtime->dev, "%s() attempting to free invalid buffer\n",
+				__func__);
+	}
+}
+
+static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
+{
+	struct snd_pcm *pcm = soc_runtime->pcm;
+	struct snd_pcm_substream *substream =
+		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct lpass_data *drvdata =
+		snd_soc_platform_get_drvdata(soc_runtime->platform);
+	int ret;
+
+	ret = lpass_platform_alloc_buffer(substream, soc_runtime);
+	if (ret)
+		return ret;
+
+	ret = devm_request_irq(soc_runtime->dev, drvdata->lpaif_irq,
+			lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
+			"lpass-irq-lpaif", substream);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() irq request failed: %d\n",
+				__func__, ret);
+		goto err_buf;
+	}
+
+	/* ensure audio hardware is disabled */
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 0);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+	ret = regmap_write(drvdata->lpaif_map,
+			LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0);
+	if (ret) {
+		dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+
+err_buf:
+	lpass_platform_free_buffer(substream, soc_runtime);
+	return ret;
+}
+
+static void lpass_platform_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream =
+		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+
+	lpass_platform_free_buffer(substream, soc_runtime);
+}
+
+static struct snd_soc_platform_driver lpass_platform_driver = {
+	.pcm_new	= lpass_platform_pcm_new,
+	.pcm_free	= lpass_platform_pcm_free,
+	.ops		= &lpass_platform_pcm_ops,
+};
+
+int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
+{
+	struct lpass_data *drvdata = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpm");
+	if (!res) {
+		dev_err(&pdev->dev, "%s() error getting resource\n", __func__);
+		return -ENODEV;
+	}
+
+	drvdata->lpm = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR((unsigned char __force *)drvdata->lpm)) {
+		dev_err(&pdev->dev, "%s() error mapping lpm resource: %ld\n",
+				__func__,
+				PTR_ERR((unsigned char __force *)drvdata->lpm));
+		return PTR_ERR((unsigned char __force *)drvdata->lpm);
+	}
+	drvdata->lpm_phys = res->start;
+	drvdata->lpm_size = resource_size(res);
+	atomic_set(&drvdata->lpm_lock, 0);
+
+	drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
+	if (drvdata->lpaif_irq < 0) {
+		dev_err(&pdev->dev, "%s() error getting irq handle: %d\n",
+				__func__, drvdata->lpaif_irq);
+		return -ENODEV;
+	}
+
+	return devm_snd_soc_register_platform(&pdev->dev,
+			&lpass_platform_driver);
+}
+EXPORT_SYMBOL(asoc_qcom_lpass_platform_register);
+
+MODULE_DESCRIPTION("QTi LPASS Platform Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
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	[flat|nested] 27+ messages in thread

* [Patch V4 08/10] ASoC: qcom: Add ability to build QCOM drivers
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (4 preceding siblings ...)
  2015-02-05 20:53 ` [Patch V4 06/10] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
       [not found]   ` <1423169626-22166-9-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2015-02-05 20:53 ` [Patch V4 09/10] ASoC: Allow for building " Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 10/10] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield
  7 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Define the LPASS platform driver and the LPASS
CPU DAI driver configuration, and how to build
them.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/qcom/Kconfig  | 27 +++++++++++++++++++++++++++
 sound/soc/qcom/Makefile |  6 ++++++
 2 files changed, 33 insertions(+)
 create mode 100644 sound/soc/qcom/Kconfig
 create mode 100644 sound/soc/qcom/Makefile

diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..d33fc5db86a34dc2e3f8146a1aea28c0e2ae8839
--- /dev/null
+++ b/sound/soc/qcom/Kconfig
@@ -0,0 +1,27 @@
+config SND_SOC_QCOM
+	tristate "SoC Audio support for QCOM platforms"
+	help
+          Support for audio in Qualcomm Technologies SOC-based systems.
+          Say Y if you want to use audio devices such as I2S, PCM,
+          S/PDIF, etc.
+
+config SND_SOC_LPASS_CPU
+	tristate
+	depends on SND_SOC_QCOM
+
+config SND_SOC_IPQ806X
+	tristate "SoC Audio support for IPQ806x based platforms"
+	depends on SND_SOC_QCOM || ARCH_QCOM || COMPILE_TEST
+        select SND_SIMPLE_CARD
+	select SND_SOC_LPASS_CPU
+	select SND_SOC_LPASS_PLATFORM
+        select SND_SOC_MAX98357A
+	help
+          Support for Qualcomm Technologies LPASS audio block in
+          IPQ806X SOC-based systems.
+          Say Y if you want to use audio devices such as I2S, PCM,
+          S/PDIF, etc.
+
+config SND_SOC_LPASS_PLATFORM
+	tristate
+	depends on SND_SOC_QCOM
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..2b8b0230eeb53acf36bb333c78abf7e95147ac2a
--- /dev/null
+++ b/sound/soc/qcom/Makefile
@@ -0,0 +1,6 @@
+# Platform
+snd-soc-lpass-cpu-objs := lpass-cpu.o
+snd-soc-lpass-platform-objs := lpass-platform.o
+
+obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
+obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 09/10] ASoC: Allow for building QCOM drivers
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (5 preceding siblings ...)
  2015-02-05 20:53 ` [Patch V4 08/10] ASoC: qcom: Add ability to build QCOM drivers Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
  2015-02-05 20:53 ` [Patch V4 10/10] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield
  7 siblings, 0 replies; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Allow for the Qualcomm Technologies ASoC drivers
to build.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/Kconfig  | 1 +
 sound/soc/Makefile | 1 +
 2 files changed, 2 insertions(+)

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index dcc79aa0236b548bfe5408fe56689241fc597e97..3ba52da18bc69a9bb41c84627cfc7d08f47e3bf0 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
 source "sound/soc/intel/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
+source "sound/soc/qcom/Kconfig"
 source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/sh/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 5b3c8f67c8db7a29ff7199a6103d445428978125..974ba708b4826a03077a58251434a311542d5e3c 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SND_SOC)	+= nuc900/
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
 obj-$(CONFIG_SND_SOC)	+= pxa/
+obj-$(CONFIG_SND_SOC)	+= qcom/
 obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= sh/
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Patch V4 10/10] ARM: dts: Model IPQ LPASS audio hardware
  2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (6 preceding siblings ...)
  2015-02-05 20:53 ` [Patch V4 09/10] ASoC: Allow for building " Kenneth Westfield
@ 2015-02-05 20:53 ` Kenneth Westfield
  7 siblings, 0 replies; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-05 20:53 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, Patrick Lai
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Model the Qualcomm Technologies LPASS hardware for
the ipq806x SOC.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 arch/arm/boot/dts/qcom-ipq8064.dtsi | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 63b2146f563b541e4994697af5ee1bbb41a4abd1..c608575e3d184a5d84d550d47af8c597e022ba4a 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -2,6 +2,7 @@
 
 #include "skeleton.dtsi"
 #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
+#include <dt-bindings/clock/qcom,lcc-ipq806x.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
 
 / {
@@ -118,6 +119,21 @@
 			regulator;
 		};
 
+		lpass-cpu@28100000 {
+			compatible = "qcom,lpass-cpu";
+			status = "disabled";
+			clocks = <&lcc AHBIX_CLK>,
+					<&lcc MI2S_OSR_CLK>,
+					<&lcc MI2S_BIT_CLK>;
+			clock-names = "ahbix-clk",
+					"mi2s-osr-clk",
+					"mi2s-bit-clk";
+			interrupts = <0 85 1>;
+			interrupt-names = "lpass-irq-lpaif";
+			reg = <0x28100000 0x10000>, <0x28400000 0x4000>;
+			reg-names = "lpass-lpaif", "lpass-lpm";
+		};
+
 		gsbi2: gsbi@12480000 {
 			compatible = "qcom,gsbi-v1.0.0";
 			reg = <0x12480000 0x100>;
@@ -279,5 +295,12 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 		};
+
+		lcc: clock-controller@28000000 {
+			compatible = "qcom,lcc-ipq8064";
+			reg = <0x28000000 0x1000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
 	};
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings
  2015-02-05 20:53 ` [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings Kenneth Westfield
@ 2015-02-06 22:12   ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:12 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:38PM -0800, Kenneth Westfield wrote:
> From: Kenneth Westfield <kwestfie@codeaurora.org>
> 
> Add documentation to the sound directory of the
> device-tree bindings for the Maxim MAX98357A audio
> DAC.

Applied, thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 04/10] ASoC: codec: Add MAX98357A codec driver
  2015-02-05 20:53 ` [Patch V4 04/10] ASoC: codec: Add MAX98357A codec driver Kenneth Westfield
@ 2015-02-06 22:13   ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:13 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:40PM -0800, Kenneth Westfield wrote:
> From: Kenneth Westfield <kwestfie@codeaurora.org>
> 
> Add codec driver for the Maxim MAX98357A DAC.

Applied, thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings
  2015-02-05 20:53   ` [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings Kenneth Westfield
@ 2015-02-06 22:18     ` Mark Brown
  2015-02-09  6:38       ` Kenneth Westfield
  0 siblings, 1 reply; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:18 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:39PM -0800, Kenneth Westfield wrote:

> +- qcom,system-clock-shift		: Add this bool property if the default
> +					  frequency of the system clock needs to
> +					  be reduced.
> +- qcom,system-clock-shift-compare	: A numerical value used to right-shift
> +					  the default system clock frequency for
> +					  comparison with the target bit clock
> +					  frequency.
> +- qcom,system-clock-shift-amount	: A numerical value used to right-shift
> +					  the default system clock frequency.
> +- qcom,alternate-sysclk			: Add this bool property if the default
> +					  frequency of the system clock cannot
> +					  divide down to the target bit clock
> +					  frequency.
> +- qcom,alternate-sysclk-bitwidth	: A numerical value representing the
> +					  sample bitwidth which requires use of
> +					  the alternate system clock frequency.
> +- qcom,alternate-sysclk-frequency	: A numerical value representing the new
> +					  system clock frequency to use.

None of these seem like they are appropriate for device tree properties,
they appear to be choosing a specific clocking configuration which is
something that would normally be done as part of the system integration
in the machine driver rather than in the DAI driver.  This binding won't
work in cases where the clocks are being changed at runtime and would
limit systems where that becomes possible in future.

Further, the interface seems too low level - it's specifying individual
dividers and so on which would normally be things that can trivially be
calculated or inferred given the input and target clock rates.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
       [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
                     ` (2 preceding siblings ...)
  2015-02-05 20:53   ` [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver Kenneth Westfield
@ 2015-02-06 22:32   ` Mark Brown
  2015-02-09  6:45     ` Kenneth Westfield
  3 siblings, 1 reply; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:32 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:36PM -0800, Kenneth Westfield wrote:

> This patch series adds support for I2S audio playback on the Qualcomm
> Technologies ipq806x SOC.

> The ipq806x SOC has audio-related hardware blocks in its low-power audio
> subsystem (or LPASS).  One of the relevant blocks in the LPASS is its low-power
> audio interface (or LPAIF).  This contains an MI2S port, which is what these
> drivers are configured to use.  The LPAIF also contains a DMA engine that is
> dedicated to moving audio samples into the transmit FIFO of the MI2S port.  In
> addition, there is also low-power memory (LPM) within the audio subsystem, which
> is used for buffering the audio samples.

This is implementing an AP centric audio system design where the AP
directly programs all the audio hardware.  Given that pretty much all
public Qualcomm systems use a DSP centric model where the AP interacts
only with a DSP which deals with DMA and the physical interfaces it
seems reasonable to suppose that this system also has a DSP which at
some future point people are likely to want to use.

I'd really like to see some discussion as to how this is all supposed to
be handled - how will these direct hardware access drivers and device
trees work when someone does want to use the DSP (without causing
problems), and how will we transition from one to the other.  This is
particularly pressing if there are use cases where people will want to
switch between the two modes at runtime.

What I'm trying to avoid here is being in a situation where we have
existing stable DT bindings which we have to support but which conflict
with the way that people want to use the systems.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 06/10] ASoC: ipq806x: Add LPASS CPU DAI driver
  2015-02-05 20:53 ` [Patch V4 06/10] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
@ 2015-02-06 22:40   ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:40 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:42PM -0800, Kenneth Westfield wrote:

> +	int bitwidth, ret;

> +	bitwidth = snd_pcm_format_width(format);
> +	if (bitwidth < 0) {
> +		dev_err(dai->dev, "%s() invalid bit width given\n", __func__);

Print the error code.

> +	regval = 0;
> +	regval |= LPAIF_I2SCTL_LOOPBACK_DISABLE;
> +	regval |= LPAIF_I2SCTL_WSSRC_INTERNAL;

Why not just write a single assignment statement?

> +	default:
> +		dev_err(dai->dev, "%s() invalid bitwidth given: %u\n",
> +				__func__, bitwidth);

bitwidth is a signed type but you are using an unsigned format specifier
here.

> +	reg = LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S);
> +	mask = LPAIF_I2SCTL_SPKEN_MASK;
> +	val = LPAIF_I2SCTL_SPKEN_ENABLE;
> +	ret = regmap_update_bits(drvdata->lpaif_map, reg, mask, val);

None of these intermediate variables seem to be doing a lot, why not
just specify the constants directly as arguments (that's the more normal
style)?  A similar thing applies in several other places in this file.

> +#ifdef CONFIG_OF
> +static const struct of_device_id lpass_cpu_device_id[] = {
> +	{.compatible = "qcom," DRV_NAME},
> +	{}
> +};
> +#endif

Using DRV_NAME in the compatible like this makes it impossible to grep
for the driver which isn't helpful.  In general I prefer not to use
DRV_NAME at all (exactly how often do we change the driver name?) but in
this case it's actively harmful.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver
  2015-02-05 20:53   ` [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver Kenneth Westfield
@ 2015-02-06 22:55     ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:55 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:43PM -0800, Kenneth Westfield wrote:

> +	irqreturn_t ret = IRQ_NONE;
> +
> +	interrupts = ioread32(drvdata->lpaif + status_offset) & chan_bitmask;

Elsewhere we're using regmap...  why not here and how does this play
with regmap?

> +	if (likely(interrupts & period_bitmask)) {

In general it's better not to use likely() and unlikely() annotations
unless you've got some evidence that they actually improve things (which
should be explained somewhere).  They make the code that bit noisier and
there's some potential for them to cause the compiler to do unhelpful
things.

> +static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream,
> +		struct snd_soc_pcm_runtime *soc_runtime)
> +{
> +	struct snd_dma_buffer *buf = &substream->dma_buffer;
> +	struct lpass_data *drvdata =
> +		snd_soc_platform_get_drvdata(soc_runtime->platform);
> +
> +	if (atomic_cmpxchg(&drvdata->lpm_lock, 0, 1)) {

cmpxchg() and atomics are both among the more error prone
synchronization primitives the kernel has.  In cases where it is
appropriate to use them it is very important that the code be entirely
clear about what is going on so that not only are we clear that the
concurrency handling is safe but we can also modify the code safely in
the future.

This driver has no documentation at all for this variable so we've at
least got a problem with the clarity side here.  Looking at the code
it's not entirely clear to me wat exactly is being protected or why
we're not using a simpler mechanism like variable protected by a mutex.

> +	return devm_snd_soc_register_platform(&pdev->dev,
> +			&lpass_platform_driver);
> +}
> +EXPORT_SYMBOL(asoc_qcom_lpass_platform_register);

ASoC APIs are all exported EXPORT_SYMBOL_GPL, their users should be too.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 05/10] ASoC: ipq806x: add LPASS header files
       [not found]     ` <1423169626-22166-6-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-02-06 22:58       ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 22:58 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:41PM -0800, Kenneth Westfield wrote:

> +#define __LPASS_H__
> +
> +#define LPASS_AHBIX_CLOCK_FREQUENCY		131072
> +
> +/* Both the CPU DAI driver and platform driver will access this data */
> +struct lpass_data {
> +
> +	/* clocks inside the low-power audio subsystem (LPASS) domain */
> +	struct clk *ahbix_clk;

This uses struct clk so it needs at least a forward declaration of it if
not just a straight inclusion of linux/clk.h.  There's several other
types and annotations that are referenced without an include to ensure
the compiler knows about them, the general idea is to avoid implicit
dependencies and thee surprising build breaks they cause.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 08/10] ASoC: qcom: Add ability to build QCOM drivers
       [not found]   ` <1423169626-22166-9-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-02-06 23:00     ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-06 23:00 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Thu, Feb 05, 2015 at 12:53:44PM -0800, Kenneth Westfield wrote:

> +config SND_SOC_IPQ806X
> +	tristate "SoC Audio support for IPQ806x based platforms"
> +	depends on SND_SOC_QCOM || ARCH_QCOM || COMPILE_TEST
> +        select SND_SIMPLE_CARD
> +	select SND_SOC_LPASS_CPU
> +	select SND_SOC_LPASS_PLATFORM
> +        select SND_SOC_MAX98357A

No, we don't have blocks like this selecting simple-card for any other
platforms using simple-card so we shouldn't do that here either.  Just
let all the drivers be individually selectable.

You've also got a mix of tabs and spaces going on.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings
  2015-02-06 22:18     ` Mark Brown
@ 2015-02-09  6:38       ` Kenneth Westfield
       [not found]         ` <20150209063822.GA19870-VfhoOQ2zEbNBVvN7MMdr1KRtKmQZhJ7pQQ4Iyu8u01E@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-09  6:38 UTC (permalink / raw)
  To: Mark Brown
  Cc: Device Tree Mailing List, ALSA Mailing List, Banajit Goswami,
	Takashi Iwai, Greg KH, Patrick Lai, Liam Girdwood,
	Bryan Huntsman, MSM Mailing List, David Brown

On Sat, Feb 07, 2015 at 06:18:23AM +0800, Mark Brown wrote:
> On Thu, Feb 05, 2015 at 12:53:39PM -0800, Kenneth Westfield wrote:
> 
> > +- qcom,system-clock-shift		: Add this bool property if the default
> > +					  frequency of the system clock needs to
> > +					  be reduced.
> > +- qcom,system-clock-shift-compare	: A numerical value used to right-shift
> > +					  the default system clock frequency for
> > +					  comparison with the target bit clock
> > +					  frequency.
> > +- qcom,system-clock-shift-amount	: A numerical value used to right-shift
> > +					  the default system clock frequency.
> > +- qcom,alternate-sysclk			: Add this bool property if the default
> > +					  frequency of the system clock cannot
> > +					  divide down to the target bit clock
> > +					  frequency.
> > +- qcom,alternate-sysclk-bitwidth	: A numerical value representing the
> > +					  sample bitwidth which requires use of
> > +					  the alternate system clock frequency.
> > +- qcom,alternate-sysclk-frequency	: A numerical value representing the new
> > +					  system clock frequency to use.
> 
> None of these seem like they are appropriate for device tree properties,
> they appear to be choosing a specific clocking configuration which is
> something that would normally be done as part of the system integration
> in the machine driver rather than in the DAI driver.  This binding won't
> work in cases where the clocks are being changed at runtime and would
> limit systems where that becomes possible in future.

So I add a machine driver that selects the clocking freq in hw_params
and calls set_sysclk in the DAIs.

The DT node for the machine driver would look something like:
        default_system_clock_frequency = < xxxxxx >;
        alternate_system_clock_frequency = < xxxxxx >;
        cpu_dai = < &cpu >;
        codec_dai = < &codec >;
        pinctrl... ?

Does this sound ok?  Also, would it make sense to move the pinctrl back
to the machine driver?

-- 
Kenneth Westfield
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
  2015-02-06 22:32   ` [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Mark Brown
@ 2015-02-09  6:45     ` Kenneth Westfield
  2015-02-11  2:26       ` Mark Brown
  0 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-09  6:45 UTC (permalink / raw)
  To: Mark Brown
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

On Sat, Feb 07, 2015 at 06:32:29AM +0800, Mark Brown wrote:
> On Thu, Feb 05, 2015 at 12:53:36PM -0800, Kenneth Westfield wrote:
> 
> > This patch series adds support for I2S audio playback on the Qualcomm
> > Technologies ipq806x SOC.
> 
> > The ipq806x SOC has audio-related hardware blocks in its low-power audio
> > subsystem (or LPASS).  One of the relevant blocks in the LPASS is its low-power
> > audio interface (or LPAIF).  This contains an MI2S port, which is what these
> > drivers are configured to use.  The LPAIF also contains a DMA engine that is
> > dedicated to moving audio samples into the transmit FIFO of the MI2S port.  In
> > addition, there is also low-power memory (LPM) within the audio subsystem, which
> > is used for buffering the audio samples.
> 
> This is implementing an AP centric audio system design where the AP
> directly programs all the audio hardware.  Given that pretty much all
> public Qualcomm systems use a DSP centric model where the AP interacts
> only with a DSP which deals with DMA and the physical interfaces it
> seems reasonable to suppose that this system also has a DSP which at
> some future point people are likely to want to use.
> 
> I'd really like to see some discussion as to how this is all supposed to
> be handled - how will these direct hardware access drivers and device
> trees work when someone does want to use the DSP (without causing
> problems), and how will we transition from one to the other.  This is
> particularly pressing if there are use cases where people will want to
> switch between the two modes at runtime.
> 
> What I'm trying to avoid here is being in a situation where we have
> existing stable DT bindings which we have to support but which conflict
> with the way that people want to use the systems.

The ipq806x SOC has no LPASS DSP.  On SOCs with a DSP, these drivers
would not be enabled.

These drivers are prefixed with "lpass" to differentiate themselves from
other drivers that would interact with a DSP, rather than the LPASS
hardware directly.


-- 
Kenneth Westfield
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings
       [not found]         ` <20150209063822.GA19870-VfhoOQ2zEbNBVvN7MMdr1KRtKmQZhJ7pQQ4Iyu8u01E@public.gmane.org>
@ 2015-02-09  8:08           ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-09  8:08 UTC (permalink / raw)
  To: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Sun, Feb 08, 2015 at 10:38:23PM -0800, Kenneth Westfield wrote:

> So I add a machine driver that selects the clocking freq in hw_params
> and calls set_sysclk in the DAIs.

> The DT node for the machine driver would look something like:
>         default_system_clock_frequency = < xxxxxx >;
>         alternate_system_clock_frequency = < xxxxxx >;
>         cpu_dai = < &cpu >;
>         codec_dai = < &codec >;
>         pinctrl... ?

Why are the system clock frequencies being specified in the DT at all -
can't we either figure out the constraints from something else or just
set the rates to something sensible that the driver knows (allowing for
improvements in the driver in the future).

> Does this sound ok?  Also, would it make sense to move the pinctrl back
> to the machine driver?

Why would we want to do that?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
  2015-02-09  6:45     ` Kenneth Westfield
@ 2015-02-11  2:26       ` Mark Brown
  2015-02-12  1:05         ` [alsa-devel] " Kenneth Westfield
  0 siblings, 1 reply; 27+ messages in thread
From: Mark Brown @ 2015-02-11  2:26 UTC (permalink / raw)
  To: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List, srinivas.kandagatla

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

On Sun, Feb 08, 2015 at 10:45:11PM -0800, Kenneth Westfield wrote:
> On Sat, Feb 07, 2015 at 06:32:29AM +0800, Mark Brown wrote:

> > I'd really like to see some discussion as to how this is all supposed to
> > be handled - how will these direct hardware access drivers and device
> > trees work when someone does want to use the DSP (without causing
> > problems), and how will we transition from one to the other.  This is
> > particularly pressing if there are use cases where people will want to
> > switch between the two modes at runtime.

> > What I'm trying to avoid here is being in a situation where we have
> > existing stable DT bindings which we have to support but which conflict
> > with the way that people want to use the systems.

> The ipq806x SOC has no LPASS DSP.  On SOCs with a DSP, these drivers
> would not be enabled.

OK, but I'm guessing that they're using the same IP that is in other
SoCs which do have the DSP so even if you don't care for this device it
might still be an issue.

> These drivers are prefixed with "lpass" to differentiate themselves from
> other drivers that would interact with a DSP, rather than the LPASS
> hardware directly.

Right, it may be that all that's needed here is some indication as to
how to describe a system which *does* have a DSP.  Perhaps require that
the devices be children of the DSP, that way if people want to access
the hardware directly they can load a dummy driver for the DSP that just
passes things through if they don't want to use the DSP?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [alsa-devel] [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
  2015-02-11  2:26       ` Mark Brown
@ 2015-02-12  1:05         ` Kenneth Westfield
  2015-02-12  2:53           ` Mark Brown
  0 siblings, 1 reply; 27+ messages in thread
From: Kenneth Westfield @ 2015-02-12  1:05 UTC (permalink / raw)
  To: Mark Brown
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List, srinivas.kandagatla,
	Kenneth Westfield

On Tue, Feb 10, 2015 at 06:26:34PM -0800, Mark Brown wrote:
> On Sun, Feb 08, 2015 at 10:45:11PM -0800, Kenneth Westfield wrote:
> > On Sat, Feb 07, 2015 at 06:32:29AM +0800, Mark Brown wrote:
> 
> > > I'd really like to see some discussion as to how this is all supposed
> to
> > > be handled - how will these direct hardware access drivers and device
> > > trees work when someone does want to use the DSP (without causing
> > > problems), and how will we transition from one to the other.  This is
> > > particularly pressing if there are use cases where people will want to
> > > switch between the two modes at runtime.
> 
> > > What I'm trying to avoid here is being in a situation where we have
> > > existing stable DT bindings which we have to support but which
> conflict
> > > with the way that people want to use the systems.
> 
> > The ipq806x SOC has no LPASS DSP.  On SOCs with a DSP, these drivers
> > would not be enabled.
> 
> OK, but I'm guessing that they're using the same IP that is in other
> SoCs which do have the DSP so even if you don't care for this device it
> might still be an issue.
> 
> > These drivers are prefixed with "lpass" to differentiate themselves from
> > other drivers that would interact with a DSP, rather than the LPASS
> > hardware directly.
> 
> Right, it may be that all that's needed here is some indication as to
> how to describe a system which *does* have a DSP.  Perhaps require that
> the devices be children of the DSP, that way if people want to access
> the hardware directly they can load a dummy driver for the DSP that just
> passes things through if they don't want to use the DSP?

Replacing DSP-based drivers with LPASS-based drivers would be something that
should be handled by Kconfig selections.  For the DT, the DSP-related
nodes and the LPASS-related nodes shouldn't overlap.  There should be a
DSP-based DT binding and a separate LPASS-based DT binding.  Tying one
or the other to the sound node (but not both), should work.

-- 
Kenneth Westfield
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [alsa-devel] [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
  2015-02-12  1:05         ` [alsa-devel] " Kenneth Westfield
@ 2015-02-12  2:53           ` Mark Brown
       [not found]             ` <20150212025341.GT2593-bheZrs9scGb3/WHNxyQH9YN0K6Il/+VY@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Mark Brown @ 2015-02-12  2:53 UTC (permalink / raw)
  To: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, Patrick Lai, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List, srinivas.kandagatla

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

On Wed, Feb 11, 2015 at 05:05:52PM -0800, Kenneth Westfield wrote:

> Replacing DSP-based drivers with LPASS-based drivers would be something that
> should be handled by Kconfig selections.  For the DT, the DSP-related

No, it shouldn't be.  We should have the ability to build a single
kernel image which will run on many systems, including both your
system with a DSP and other systems without.

> nodes and the LPASS-related nodes shouldn't overlap.  There should be a
> DSP-based DT binding and a separate LPASS-based DT binding.  Tying one
> or the other to the sound node (but not both), should work.

The selection of DSP use sounds like something which isn't part of the
description of the hardware but rather a runtime policy decision (at
least in so far as non-DSP is ever an option).

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [alsa-devel] [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
       [not found]             ` <20150212025341.GT2593-bheZrs9scGb3/WHNxyQH9YN0K6Il/+VY@public.gmane.org>
@ 2015-02-12  7:20               ` Patrick Lai
  2015-02-14  5:25                 ` Mark Brown
  0 siblings, 1 reply; 27+ messages in thread
From: Patrick Lai @ 2015-02-12  7:20 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Greg KH, Banajit Goswami, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List,
	srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A

On 2/11/2015 6:53 PM, Mark Brown wrote:
> On Wed, Feb 11, 2015 at 05:05:52PM -0800, Kenneth Westfield wrote:
>
>> Replacing DSP-based drivers with LPASS-based drivers would be something that
>> should be handled by Kconfig selections.  For the DT, the DSP-related
>
> No, it shouldn't be.  We should have the ability to build a single
> kernel image which will run on many systems, including both your
> system with a DSP and other systems without.
>
Is there expectation that DTB flashed onto the system would define nodes to
bind with both LPASS-based driver and DSP-based driver? I hope not as we want
to keep LPASS-based driver & DSP-based driver mutually exclusive.

>> nodes and the LPASS-related nodes shouldn't overlap.  There should be a
>> DSP-based DT binding and a separate LPASS-based DT binding.  Tying one
>> or the other to the sound node (but not both), should work.
>
> The selection of DSP use sounds like something which isn't part of the
> description of the hardware but rather a runtime policy decision (at
> least in so far as non-DSP is ever an option).
>
Put aside IPQ8064, I would say it is actually more of build time policy
decision for QC SoCs with DSP. XPU is programmed by trust zone to allow certain
LPASS registers to be accessed by the chosen processor. If ADSP and app
processor would have to have access to audio interfaces and DMA, resources
partition(i.e # of DMAs go to ADSP while rest of DMA go to app processor is
decided after analyzing expected concurrency use case. For case of 8016, MDSP
would simply expect it has access to all audio subsystem except digital core of
CODEC.

Thanks
Patrick

-- 
Patrick Lai
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,a 
Linux Foundation Collaborative Project
--
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	[flat|nested] 27+ messages in thread

* Re: [alsa-devel] [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC
  2015-02-12  7:20               ` Patrick Lai
@ 2015-02-14  5:25                 ` Mark Brown
  0 siblings, 0 replies; 27+ messages in thread
From: Mark Brown @ 2015-02-14  5:25 UTC (permalink / raw)
  To: Patrick Lai
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Greg KH, Banajit Goswami, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List, srinivas.kandagatla

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

On Wed, Feb 11, 2015 at 11:20:33PM -0800, Patrick Lai wrote:
> On 2/11/2015 6:53 PM, Mark Brown wrote:
> >On Wed, Feb 11, 2015 at 05:05:52PM -0800, Kenneth Westfield wrote:

> >>Replacing DSP-based drivers with LPASS-based drivers would be something that
> >>should be handled by Kconfig selections.  For the DT, the DSP-related

> >No, it shouldn't be.  We should have the ability to build a single
> >kernel image which will run on many systems, including both your
> >system with a DSP and other systems without.

> Is there expectation that DTB flashed onto the system would define nodes to
> bind with both LPASS-based driver and DSP-based driver? I hope not as we want
> to keep LPASS-based driver & DSP-based driver mutually exclusive.

DTB time selections are a separate thing to Kconfig changes like Kenneth
was proposing.  They're more viable though it'd be a lot better to avoid
needing them, designing out the possibility of doing something is often
a sure fire way of finding a user.

> >The selection of DSP use sounds like something which isn't part of the
> >description of the hardware but rather a runtime policy decision (at
> >least in so far as non-DSP is ever an option).

> Put aside IPQ8064, I would say it is actually more of build time policy
> decision for QC SoCs with DSP. XPU is programmed by trust zone to allow certain
> LPASS registers to be accessed by the chosen processor. If ADSP and app
> processor would have to have access to audio interfaces and DMA, resources
> partition(i.e # of DMAs go to ADSP while rest of DMA go to app processor is
> decided after analyzing expected concurrency use case. For case of 8016, MDSP
> would simply expect it has access to all audio subsystem except digital core of
> CODEC.

But is it possible to configure the TrustZone firmware to leave things
open?  That's the tricky case.

Actually, can we read the configuration TrustZone did?  That might be
the best answer here, the DT can describe the silicon and then we can
check at runtime which bits of it we're actually allowed to talk to.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2015-02-14  5:26 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-05 20:53 [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
2015-02-05 20:53 ` [Patch V4 01/10] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
2015-02-05 20:53 ` [Patch V4 02/10] ASoC: max98357a: Document MAX98357A bindings Kenneth Westfield
2015-02-06 22:12   ` Mark Brown
2015-02-05 20:53 ` [Patch V4 04/10] ASoC: codec: Add MAX98357A codec driver Kenneth Westfield
2015-02-06 22:13   ` Mark Brown
     [not found] ` <1423169626-22166-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-02-05 20:53   ` [Patch V4 03/10] ASoC: qcom: Document LPASS CPU bindings Kenneth Westfield
2015-02-06 22:18     ` Mark Brown
2015-02-09  6:38       ` Kenneth Westfield
     [not found]         ` <20150209063822.GA19870-VfhoOQ2zEbNBVvN7MMdr1KRtKmQZhJ7pQQ4Iyu8u01E@public.gmane.org>
2015-02-09  8:08           ` Mark Brown
2015-02-05 20:53   ` [Patch V4 05/10] ASoC: ipq806x: add LPASS header files Kenneth Westfield
     [not found]     ` <1423169626-22166-6-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-02-06 22:58       ` Mark Brown
2015-02-05 20:53   ` [Patch V4 07/10] ASoC: ipq806x: Add LPASS platform driver Kenneth Westfield
2015-02-06 22:55     ` Mark Brown
2015-02-06 22:32   ` [Patch V4 00/10] ASoC: QCOM: Add support for ipq806x SOC Mark Brown
2015-02-09  6:45     ` Kenneth Westfield
2015-02-11  2:26       ` Mark Brown
2015-02-12  1:05         ` [alsa-devel] " Kenneth Westfield
2015-02-12  2:53           ` Mark Brown
     [not found]             ` <20150212025341.GT2593-bheZrs9scGb3/WHNxyQH9YN0K6Il/+VY@public.gmane.org>
2015-02-12  7:20               ` Patrick Lai
2015-02-14  5:25                 ` Mark Brown
2015-02-05 20:53 ` [Patch V4 06/10] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
2015-02-06 22:40   ` Mark Brown
2015-02-05 20:53 ` [Patch V4 08/10] ASoC: qcom: Add ability to build QCOM drivers Kenneth Westfield
     [not found]   ` <1423169626-22166-9-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-02-06 23:00     ` Mark Brown
2015-02-05 20:53 ` [Patch V4 09/10] ASoC: Allow for building " Kenneth Westfield
2015-02-05 20:53 ` [Patch V4 10/10] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.