devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC
@ 2014-12-08 22:01 Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 01/11] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

This set of patches adds support for audio 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 encapsulates the MI2S port, which is what these drivers are configured to use.  The I2S pins are connected to an external DAC/amp chip.  In addition, a single GPIO is connected to the same DAC/amp, which gives the SOC enable/disable control.

The specific drivers added are:
 - a Codec DAI driver that controls the SOC external pins
 - a CPU DAI driver for controlling the LPASS-LPAIF block
 - a PCM MI2S platform driver
 - a machine driver that ties the three drivers together

Corresponding additions to the device tree for the ipq806x and its documentation has also been added.  Also, as this is a new directory, the MAINTAINERS file has been updated as well.

== Updates from my previous post:

[PATCH 00/9] ASoC: QCOM: Add support for ipq806x SOC
http://thread.gmane.org/gmane.linux.ports.arm.msm/10701

 - 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

== Additional patch series upon which this patch series has device-tree dependencies (lcc)

[PATCH v2 0/8] qcom audio clock control drivers
http://thread.gmane.org/gmane.linux.ports.arm.msm/10793


Kenneth Westfield (11):
  MAINTAINERS: Add QCOM audio ASoC maintainer
  ASoC: qcom: Add device tree binding docs
  ASoC: ipq806x: add LPAIF header file
  ASoC: codec: Add Maxim codec driver
  ASoC: ipq806x: Add LPASS CPU DAI driver
  ASoC: ipq806x: Add I2S PCM platform driver
  ASoC: ipq806x: Add machine driver for IPQ806X SOC
  ASoC: codec: Add ability to build QCOM codec
  ASoC: qcom: Add ability to build QCOM drivers
  ASoC: Allow for building QCOM drivers
  ARM: dts: Model IPQ LPASS audio hardware

 .../bindings/sound/qcom,ipq806x-snd-card.txt       |  25 ++
 .../bindings/sound/qcom,lpass-cpu-dai.txt          |  32 ++
 .../bindings/sound/qcom,lpass-pcm-mi2s.txt         |  12 +
 .../bindings/sound/qcom,max98357a-codec.txt        |  23 ++
 MAINTAINERS                                        |   7 +
 arch/arm/boot/dts/qcom-ipq8064.dtsi                |  33 ++
 sound/soc/Kconfig                                  |   1 +
 sound/soc/Makefile                                 |   1 +
 sound/soc/codecs/Kconfig                           |   4 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/max98357a.c                       | 267 ++++++++++++
 sound/soc/qcom/Kconfig                             |  25 ++
 sound/soc/qcom/Makefile                            |  11 +
 sound/soc/qcom/ipq806x.c                           | 127 ++++++
 sound/soc/qcom/lpass-cpu-mi2s.c                    | 374 +++++++++++++++++
 sound/soc/qcom/lpass-cpu-mi2s.h                    |  48 +++
 sound/soc/qcom/lpass-lpaif.h                       | 154 +++++++
 sound/soc/qcom/lpass-pcm-mi2s.c                    | 452 +++++++++++++++++++++
 18 files changed, 1598 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,ipq806x-snd-card.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu-dai.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-pcm-mi2s.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,max98357a-codec.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/ipq806x.c
 create mode 100644 sound/soc/qcom/lpass-cpu-mi2s.c
 create mode 100644 sound/soc/qcom/lpass-cpu-mi2s.h
 create mode 100644 sound/soc/qcom/lpass-lpaif.h
 create mode 100644 sound/soc/qcom/lpass-pcm-mi2s.c

-- 
1.8.2.1

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

* [Patch v2 01/11] MAINTAINERS: Add QCOM audio ASoC maintainer
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 02/11] ASoC: qcom: Add device tree binding docs Kenneth Westfield
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

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 e6bff3afaeaeb84b0a4fe99fbd941c38596473f4..0d862732ae301e25f2203e684da21249ae9b4094 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5148,6 +5148,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
-- 
1.8.2.1

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

* [Patch v2 02/11] ASoC: qcom: Add device tree binding docs
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 01/11] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 15:37   ` Mark Brown
  2014-12-08 22:01 ` [Patch v2 03/11] ASoC: ipq806x: add LPAIF header file Kenneth Westfield
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  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 IPQ806x audio drivers.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 .../bindings/sound/qcom,ipq806x-snd-card.txt       | 25 +++++++++++++++++
 .../bindings/sound/qcom,lpass-cpu-dai.txt          | 32 ++++++++++++++++++++++
 .../bindings/sound/qcom,lpass-pcm-mi2s.txt         | 12 ++++++++
 .../bindings/sound/qcom,max98357a-codec.txt        | 23 ++++++++++++++++
 4 files changed, 92 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,ipq806x-snd-card.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-cpu-dai.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-pcm-mi2s.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,max98357a-codec.txt

diff --git a/Documentation/devicetree/bindings/sound/qcom,ipq806x-snd-card.txt b/Documentation/devicetree/bindings/sound/qcom,ipq806x-snd-card.txt
new file mode 100644
index 0000000000000000000000000000000000000000..10178737b4bdc6108475f48726bdbf40b6b044b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,ipq806x-snd-card.txt
@@ -0,0 +1,25 @@
+* Qualcomm Technologies IPQ806x SoundCard
+
+This node models the Qualcomm Technologies IPQ806x LPASS Audio SoundCard,
+with a connection between the CPU MI2S DAI and the external DAC.
+
+Required properties:
+- compatible : "qcom,ipq806x-snd-card"
+- qcom,model : The user-visible name of this sound card
+			* <any string is valid>
+- platform   : This is a phandle reference to platform device driver node (for the soundcard dai-link)
+- cpu        : This is a phandle reference to CPU DAI device driver node (for the soundcard dai-link)
+- codec      : This is a phandle reference to codec DAI device driver node (for the soundcard dai-link)
+- codec-dai  : This is a string that names the codec DAI device (for the soundcard dai-link)
+			* max98357a-codec-dai
+
+Example:
+
+sound {
+	compatible = "qcom,ipq806x-snd-card";
+	model = "ipq806x-snd-card";
+	platform = <&lpass_pcm_mi2s>;
+	cpu = <&lpass_cpu_mi2s>;
+	codec = <&max98357a_codec>;
+	codec-dai = "max98357a-codec-dai";
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu-dai.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu-dai.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ee94af49f90aedb0889f1ddf043780a80e585f62
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu-dai.txt
@@ -0,0 +1,32 @@
+* Qualcomm Technologies IPQ806x LPASS DAI
+
+This node models the Qualcomm Technologies IPQ806x LPASS MI2S DAI port.
+
+Required properties:
+- compatible      : "qcom,lpass-cpu-mi2s"
+- reg             : Address space for the LPASS audio interface registers
+- reg-names       : The name of the LPASS audio interface register address space
+			* lpass-lpaif-mem
+- clocks          : A list of clock specifiers for the audio interface
+			* AHBIX bus clock
+			* MI2S OSR clock
+			* MI2S Bit clock
+- clock-names     : A list of audio interface clock names
+			* ahbix_clk
+			* mi2s_osr_clk
+			* mi2s_bit_clk
+- interrupts      : Phandle to the LPASS audio interface interrupt
+- interrupt-names : The name of the LPASS audio interface interrupt
+			* lpass-lpaif-irq
+
+Example:
+
+lpass-cpu-mi2s {
+	compatible = "qcom,lpass-cpu-dai";
+	reg = <0x28100000 0x10000>;
+	reg-names = "lpass-lpaif-mem";
+	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-lpaif-irq";
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-pcm-mi2s.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-pcm-mi2s.txt
new file mode 100644
index 0000000000000000000000000000000000000000..09c04b7f37b51076860f1df10114e0a47b921404
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-pcm-mi2s.txt
@@ -0,0 +1,12 @@
+* Qualcomm Technologies IPQ806x PCM audio interface
+
+This node models the Qualcomm Technologies IPQ806x PCM audio interface.
+
+Required properties:
+- compatible : "qcom,lpass-pcm-mi2s"
+
+Example:
+
+lpass-pcm-mi2s {
+	compatible = "qcom,lpass-pcm-mi2s";
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom,max98357a-codec.txt b/Documentation/devicetree/bindings/sound/qcom,max98357a-codec.txt
new file mode 100644
index 0000000000000000000000000000000000000000..14bc14b1049f4138123db8fd17e8926545cbb218
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,max98357a-codec.txt
@@ -0,0 +1,23 @@
+* Maxim MAX98357A DAC
+
+This node models the Maxim MAX98357A DAC as a codec DAI.
+This is for audio on the Qualcomm IPQ806x SOC.
+
+Required properties:
+- compatible    : "qcom,max98357a-codec"
+- dac-gpios     : Phandle to the GPIO specifier for the GPIO -> DAC SDMODE pin
+- pinctrl-names : A list of names indicating the state of the MI2S pins
+			* mi2s-disabled
+			* mi2s-enabled
+- pinctrl-0     : The disabled state of the MI2S pins
+- pinctrl-1     : The enabled state of the MI2S pins
+
+Example:
+
+max98357a-codec {
+	compatible = "qcom,max98357a-codec";
+	dac-gpios = <&qcom_pinmux 25 0>;
+	pinctrl-names = "mi2s-disabled", "mi2s_enabled";
+	pinctrl-0 = <&mi2s_disabled>;
+	pinctrl-1 = <&mi2s_enabled>;
+};
-- 
1.8.2.1

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

* [Patch v2 03/11] ASoC: ipq806x: add LPAIF header file
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 01/11] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 02/11] ASoC: qcom: Add device tree binding docs Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 04/11] ASoC: codec: Add Maxim codec driver Kenneth Westfield
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add the LPASS LPAIF header file in Qualcomm Technologies
SoCs.  This primarily contains the register definitions.

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

diff --git a/sound/soc/qcom/lpass-lpaif.h b/sound/soc/qcom/lpass-lpaif.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdc81fbe6d0be9d57860b4ba80e0b3549e4cca76
--- /dev/null
+++ b/sound/soc/qcom/lpass-lpaif.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2010-2011,2013-2014 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 DMA Configuration/Control */
+
+#define LPAIF_DMA_BASE			0x6000
+#define LPAIF_DMA_INDEX(ch)		(LPAIF_BANK_OFFSET * (ch))
+#define LPAIF_DMA_ADDR(ch, addr)	(LPAIF_DMA_BASE \
+						+ (LPAIF_DMA_INDEX(ch) \
+						+ (addr)))
+
+#define LPAIF_DMA_CTL(x)		LPAIF_DMA_ADDR((x), 0x00)
+#define LPAIF_DMA_BASEADDR(x)		LPAIF_DMA_ADDR((x), 0x04)
+#define	LPAIF_DMA_BUFFLEN(x)		LPAIF_DMA_ADDR((x), 0x08)
+#define LPAIF_DMA_CURRADDR(x)		LPAIF_DMA_ADDR((x), 0x0c)
+#define	LPAIF_DMA_PERLEN(x)		LPAIF_DMA_ADDR((x), 0x10)
+#define	LPAIF_DMA_PERCNT(x)		LPAIF_DMA_ADDR((x), 0x14)
+#define	LPAIF_DMA_FRM(x)		LPAIF_DMA_ADDR((x), 0x18)
+#define LPAIF_DMA_FRMCLR(x)		LPAIF_DMA_ADDR((x), 0x1c)
+#define LPAIF_DMA_SETBUFFCNT(x)		LPAIF_DMA_ADDR((x), 0x20)
+#define	LPAIF_DMA_SETPERCNT(x)		LPAIF_DMA_ADDR((x), 0x24)
+
+#define LPAIF_DMACTL_BURST_EN_SHIFT	11
+#define LPAIF_DMACTL_BURST_EN		(1 << LPAIF_DMACTL_BURST_EN_SHIFT)
+
+#define LPAIF_DMACTL_WPSCNT_MASK	0x700
+#define LPAIF_DMACTL_WPSCNT_SHIFT	8
+#define LPAIF_DMACTL_WPSCNT_SINGLE	(0 << LPAIF_DMACTL_WPSCNT_SHIFT)
+#define LPAIF_DMACTL_WPSCNT_DOUBLE	(1 << LPAIF_DMACTL_WPSCNT_SHIFT)
+#define LPAIF_DMACTL_WPSCNT_TRIPLE	(2 << LPAIF_DMACTL_WPSCNT_SHIFT)
+#define LPAIF_DMACTL_WPSCNT_QUAD	(3 << LPAIF_DMACTL_WPSCNT_SHIFT)
+#define LPAIF_DMACTL_WPSCNT_SIXPACK	(5 << LPAIF_DMACTL_WPSCNT_SHIFT)
+#define LPAIF_DMACTL_WPSCNT_OCTAL	(7 << LPAIF_DMACTL_WPSCNT_SHIFT)
+
+#define LPAIF_DMACTL_AUDIO_INTF_MASK	0x0F0
+#define LPAIF_DMACTL_AUDIO_INTF_SHIFT	4
+#define LPAIF_DMACTL_AUDIO_INTF_NONE	(0 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_CODEC	(1 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_PCM	(2 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_SEC_I2S	(3 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_MI2S	(4 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_HDMI	(5 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_MIXOUT	(6 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_LB1	(7 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+#define LPAIF_DMACTL_AUDIO_INTF_LB2	(8 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
+
+#define LPAIF_DMACTL_FIFO_WM_MASK	0x00E
+#define LPAIF_DMACTL_FIFO_WM_SHIFT	1
+#define LPAIF_DMACTL_FIFO_WM_1		(0 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_2		(1 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_3		(2 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_4		(3 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_5		(4 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_6		(5 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_7		(6 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+#define LPAIF_DMACTL_FIFO_WM_8		(7 << LPAIF_DMACTL_FIFO_WM_SHIFT)
+
+#define LPAIF_DMACTL_ENABLE_SHIFT	0
+#define LPAIF_DMACTL_ENABLE		(1 << LPAIF_DMACTL_ENABLE_SHIFT)
+
+/* LPAIF DMA Interrupt Control */
+
+#define LPAIF_DMAIRQ_BASE		0x3000
+#define LPAIF_DMAIRQ_INDEX(x)		(LPAIF_BANK_OFFSET * (x))
+#define LPAIF_DMAIRQ_ADDR(irq, addr)	(LPAIF_DMAIRQ_BASE  \
+						+ LPAIF_DMAIRQ_INDEX(irq) \
+						+ (addr))
+
+#define LPAIF_DMAIRQ_EN(x)		LPAIF_DMAIRQ_ADDR((x), 0x00)
+#define LPAIF_DMAIRQ_STAT(x)		LPAIF_DMAIRQ_ADDR((x), 0x04)
+#define LPAIF_DMAIRQ_RAW_STAT(x)	LPAIF_DMAIRQ_ADDR((x), 0x08)
+#define LPAIF_DMAIRQ_CLEAR(x)		LPAIF_DMAIRQ_ADDR((x), 0x0c)
+#define LPAIF_DMAIRQ_FORCE(x)		LPAIF_DMAIRQ_ADDR((x), 0x10)
+
+#define LPAIF_DMAIRQ_SHIFT		3
+#define LPAIF_DMAIRQ_PER(x)		(1 << (LPAIF_DMAIRQ_SHIFT * (x)))
+#define LPAIF_DMAIRQ_XRUN(x)		(2 << (LPAIF_DMAIRQ_SHIFT * (x)))
+#define LPAIF_DMAIRQ_ERR(x)		(4 << (LPAIF_DMAIRQ_SHIFT * (x)))
+#define LPAIF_DMAIRQ_ALL(x)		(7 << (LPAIF_DMAIRQ_SHIFT * (x)))
+
+/* LPAIF I2S Configuration/Control */
+
+#define LPAIF_MI2S_CTL_OFFSET(x)	(0x0010 + 0x4 * (x))
+
+#define LPAIF_MI2SCTL_LB_SHIFT		15
+#define LPAIF_MI2SCTL_LB		(1 << LPAIF_MI2SCTL_LB_SHIFT)
+
+#define LPAIF_MI2SCTL_SPKEN_SHIFT	14
+#define LPAIF_MI2SCTL_SPKEN		(1 << LPAIF_MI2SCTL_SPKEN_SHIFT)
+
+#define LPAIF_MI2SCTL_SPKMODE_MASK	0x3C00
+#define LPAIF_MI2SCTL_SPKMODE_SHIFT	10
+#define LPAIF_MI2SCTL_SPKMODE_NONE	(0 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_SD0	(1 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_SD1	(2 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_SD2	(3 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_SD3	(4 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_QUAD01	(5 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_QUAD23	(6 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_6CH	(7 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+#define LPAIF_MI2SCTL_SPKMODE_8CH	(8 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
+
+#define LPAIF_MI2SCTL_SPKMONO_MASK	0x0200
+#define LPAIF_MI2SCTL_SPKMONO_SHIFT	9
+#define LPAIF_MI2SCTL_SPKMONO_STEREO	(0 << LPAIF_MI2SCTL_SPKMONO_SHIFT)
+#define LPAIF_MI2SCTL_SPKMONO_MONO	(1 << LPAIF_MI2SCTL_SPKMONO_SHIFT)
+
+#define LPAIF_MI2SCTL_WS_SHIFT		2
+#define LPAIF_MI2SCTL_WS		(1 << LPAIF_MI2SCTL_WS_SHIFT)
+
+#define LPAIF_MI2SCTL_BITRATE_MASK	0x3
+#define LPAIF_MI2SCTL_BITRATE_SHIFT	0
+#define LPAIF_MI2SCTL_BITRATE_16	(0 << LPAIF_MI2SCTL_BITRATE_SHIFT)
+#define LPAIF_MI2SCTL_BITRATE_24	(1 << LPAIF_MI2SCTL_BITRATE_SHIFT)
+#define LPAIF_MI2SCTL_BITRATE_32	(2 << LPAIF_MI2SCTL_BITRATE_SHIFT)
+
+enum lpaif_dma_interface_channels {
+	LPAIF_DMA_RD_CH_MI2S = 0,
+	LPAIF_DMA_RD_CH_PCM0 = 1,
+	LPAIF_DMA_RD_CH_PCM1 = 2,
+	LPAIF_DMA_WR_CH_PCM0 = 5,
+	LPAIF_DMA_WR_CH_PCM1 = 6,
+	LPAIF_DMA_WR_CH_MI2S = 6,
+};
+
+enum lpaif_i2s_interface_ports {
+	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,
+};
+
+enum lpaif_irq_receivers {
+	LPAIF_IRQ_RECV_HOST = 0,
+	LPAIF_IRQ_RECV_ADSP = 1,
+};
+
+#endif /* _LPASS_LPAIF_H */
-- 
1.8.2.1

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

* [Patch v2 04/11] ASoC: codec: Add Maxim codec driver
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (2 preceding siblings ...)
  2014-12-08 22:01 ` [Patch v2 03/11] ASoC: ipq806x: add LPAIF header file Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 15:53   ` Mark Brown
  2014-12-08 22:01 ` [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add codec driver for the MAX98357A DAC.

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

diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
new file mode 100644
index 0000000000000000000000000000000000000000..16def09e98c2318a73e136d92f0c53c81313f10f
--- /dev/null
+++ b/sound/soc/codecs/max98357a.c
@@ -0,0 +1,267 @@
+/* Copyright (c) 2010-2011,2013-2014 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/gpio.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "max98357a-codec"
+
+enum pinctrl_pin_state {
+	STATE_DISABLED = 0,
+	STATE_ENABLED = 1
+};
+static const char * const pin_states[] = {"Disabled", "Enabled"};
+
+struct max98357a_codec_pinctrl {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *disabled;
+	struct pinctrl_state *enabled;
+	enum pinctrl_pin_state curr_state;
+};
+
+struct max98357a_codec_data {
+	struct gpio_desc *dac;
+	struct max98357a_codec_pinctrl mi2s;
+};
+
+static int max98357a_codec_set_pinctrl(struct max98357a_codec_pinctrl *mi2s)
+{
+	int ret;
+
+	pr_debug("%s: curr_state = %s\n", __func__,
+			pin_states[mi2s->curr_state]);
+
+	switch (mi2s->curr_state) {
+	case STATE_DISABLED:
+		ret = pinctrl_select_state(mi2s->pinctrl, mi2s->enabled);
+		if (ret) {
+			pr_err("%s: pinctrl_select_state failed with %d\n",
+					__func__, ret);
+			return -EIO;
+		}
+		mi2s->curr_state = STATE_ENABLED;
+		break;
+	case STATE_ENABLED:
+		pr_err("%s: MI2S pins already enabled\n", __func__);
+		break;
+	default:
+		pr_err("%s: MI2S pin state is invalid: %d\n", __func__,
+				mi2s->curr_state);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int max98357a_codec_reset_pinctrl(struct max98357a_codec_pinctrl *mi2s)
+{
+	int ret;
+
+	pr_debug("%s: curr_state = %s\n", __func__,
+			pin_states[mi2s->curr_state]);
+
+	switch (mi2s->curr_state) {
+	case STATE_ENABLED:
+		ret = pinctrl_select_state(mi2s->pinctrl, mi2s->disabled);
+		if (ret) {
+			pr_err("%s: pinctrl_select_state failed with %d\n",
+					__func__, ret);
+			return -EIO;
+		}
+		mi2s->curr_state = STATE_DISABLED;
+		break;
+	case STATE_DISABLED:
+		pr_err("%s: MI2S pins already disabled\n", __func__);
+		break;
+	default:
+		pr_err("%s: MI2S pin state is invalid: %d\n", __func__,
+				mi2s->curr_state);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int max98357a_codec_get_pinctrl(struct snd_soc_dai *dai)
+{
+	int ret;
+	struct max98357a_codec_data *prtd = snd_soc_dai_get_drvdata(dai);
+	struct max98357a_codec_pinctrl *mi2s = &prtd->mi2s;
+	struct pinctrl *pinctrl;
+
+	pinctrl = devm_pinctrl_get(dai->dev);
+	if (IS_ERR_OR_NULL(pinctrl)) {
+		dev_err(dai->dev, "%s: Unable to get pinctrl handle: %d\n",
+				__func__, PTR_ERR_OR_ZERO(pinctrl));
+		return -EINVAL;
+	}
+	mi2s->pinctrl = pinctrl;
+
+	/* get all the states handles from Device Tree */
+	mi2s->disabled = pinctrl_lookup_state(pinctrl, "mi2s-disabled");
+	if (IS_ERR(mi2s->disabled)) {
+		dev_err(dai->dev, "%s: could not get disabled pinstate: %d\n",
+				__func__, PTR_ERR_OR_ZERO(mi2s->disabled));
+		return -EINVAL;
+	}
+
+	mi2s->enabled = pinctrl_lookup_state(pinctrl, "mi2s-enabled");
+	if (IS_ERR(mi2s->enabled)) {
+		dev_err(dai->dev, "%s: could not get enabled pinstate: %d\n",
+				__func__, PTR_ERR_OR_ZERO(mi2s->enabled));
+		return -EINVAL;
+	}
+
+	/* Reset the MI2S pins to the disabled state */
+	ret = pinctrl_select_state(mi2s->pinctrl, mi2s->disabled);
+	if (ret) {
+		dev_err(dai->dev, "%s: Disable MI2S pins failed with %d\n",
+				__func__, ret);
+		return -EIO;
+	}
+	mi2s->curr_state = STATE_DISABLED;
+
+	return 0;
+}
+
+static int max98357a_codec_daiops_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	int ret;
+	struct max98357a_codec_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	ret = max98357a_codec_set_pinctrl(&prtd->mi2s);
+	if (ret) {
+		dev_err(dai->dev, "%s: MI2S pinctrl set failed with %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	gpiod_set_value(prtd->dac, 1);
+
+	return 0;
+}
+
+static void max98357a_codec_daiops_shutdown(
+		struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+	int ret;
+	struct max98357a_codec_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	gpiod_set_value(prtd->dac, 0);
+
+	ret = max98357a_codec_reset_pinctrl(&prtd->mi2s);
+	if (ret)
+		dev_err(dai->dev, "%s: MI2S pinctrl set failed with %d\n",
+				__func__, ret);
+}
+
+static struct snd_soc_dai_ops max98357a_codec_dai_ops = {
+	.startup	= max98357a_codec_daiops_startup,
+	.shutdown	= max98357a_codec_daiops_shutdown,
+};
+
+static int max98357a_codec_dai_probe(struct snd_soc_dai *dai)
+{
+	int ret;
+	struct max98357a_codec_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	prtd->dac = devm_gpiod_get(dai->dev, "dac");
+	if (IS_ERR(prtd->dac)) {
+		dev_err(dai->dev, "unable to get DAC GPIO\n");
+		return PTR_ERR(prtd->dac);
+	}
+	gpiod_direction_output(prtd->dac, 0);
+
+	ret = max98357a_codec_get_pinctrl(dai);
+	if (ret) {
+		dev_err(dai->dev, "%s: Parsing MI2S pinctrl failed: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver max98357a_codec_dai_driver = {
+	.name = "max98357a-codec-dai",
+	.playback = {
+		.stream_name	= "max98357a-codec-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,
+	},
+	.probe = &max98357a_codec_dai_probe,
+	.ops = &max98357a_codec_dai_ops,
+};
+
+static int max98357a_codec_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct max98357a_codec_data *prtd;
+	struct snd_soc_codec_driver *codec_driver;
+
+	prtd = devm_kzalloc(&pdev->dev, sizeof(struct max98357a_codec_data),
+			GFP_KERNEL);
+	if (!prtd)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, prtd);
+
+	codec_driver = devm_kzalloc(&pdev->dev,
+			sizeof(struct snd_soc_codec_driver), GFP_KERNEL);
+	if (!codec_driver)
+		return -ENOMEM;
+
+	ret = snd_soc_register_codec(&pdev->dev, codec_driver,
+			&max98357a_codec_dai_driver, 1);
+	if (ret)
+		dev_err(&pdev->dev, "%s: error registering codec dais\n",
+				__func__);
+
+	return ret;
+}
+
+static int max98357a_codec_platform_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id max98357a_codec_dt_match[] = {
+	{ .compatible = "qcom,max98357a-codec", },
+	{}
+};
+
+static struct platform_driver max98357a_codec_platform_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = max98357a_codec_dt_match,
+	},
+	.probe	= max98357a_codec_platform_probe,
+	.remove = max98357a_codec_platform_remove,
+};
+module_platform_driver(max98357a_codec_platform_driver);
+
+MODULE_DESCRIPTION("QCOM MAX98357A CODEC DRIVER");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, max98357a_codec_dt_match);
-- 
1.8.2.1

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

* [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (3 preceding siblings ...)
  2014-12-08 22:01 ` [Patch v2 04/11] ASoC: codec: Add Maxim codec driver Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 16:01   ` Mark Brown
  2014-12-08 22:01 ` [Patch v2 06/11] ASoC: ipq806x: Add I2S PCM platform driver Kenneth Westfield
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  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 QCOM LPASS SOC.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/qcom/lpass-cpu-mi2s.c | 374 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/qcom/lpass-cpu-mi2s.h |  48 ++++++
 2 files changed, 422 insertions(+)
 create mode 100644 sound/soc/qcom/lpass-cpu-mi2s.c
 create mode 100644 sound/soc/qcom/lpass-cpu-mi2s.h

diff --git a/sound/soc/qcom/lpass-cpu-mi2s.c b/sound/soc/qcom/lpass-cpu-mi2s.c
new file mode 100644
index 0000000000000000000000000000000000000000..b506064b4e7c3807170e1bff1daaef016221e5f4
--- /dev/null
+++ b/sound/soc/qcom/lpass-cpu-mi2s.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2010-2011,2013-2014 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 <linux/dma-mapping.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "lpass-lpaif.h"
+#include "lpass-cpu-mi2s.h"
+
+#define DRV_NAME			"lpass-cpu-mi2s"
+
+#define LPASS_OSR_TO_BIT_DIVIDER	4
+
+static void lpass_lpaif_mi2s_playback(struct lpass_cpu_mi2s_data *pdata,
+		int enable)
+{
+	u32 cfg;
+
+	cfg = readl(pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+
+	if (enable)
+		cfg |= LPAIF_MI2SCTL_SPKEN;
+	else
+		cfg &= ~LPAIF_MI2SCTL_SPKEN;
+
+	cfg &= ~LPAIF_MI2SCTL_WS;
+
+	writel(cfg, pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+}
+
+static int lpass_lpaif_mi2s_bitwidth(struct lpass_cpu_mi2s_data *pdata,
+		u32 bitwidth)
+{
+	u32 cfg;
+
+	cfg = readl(pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+
+	cfg &= ~LPAIF_MI2SCTL_BITRATE_MASK;
+
+	switch (bitwidth) {
+	case SNDRV_PCM_FORMAT_S16:
+		cfg |= LPAIF_MI2SCTL_BITRATE_16;
+		break;
+	case SNDRV_PCM_FORMAT_S24:
+		cfg |= LPAIF_MI2SCTL_BITRATE_24;
+		break;
+	case SNDRV_PCM_FORMAT_S32:
+		cfg |= LPAIF_MI2SCTL_BITRATE_32;
+		break;
+	default:
+		pr_err("%s: invalid bitwidth given: %u\n", __func__, bitwidth);
+		return -EINVAL;
+	}
+
+	writel(cfg, pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+
+	return 0;
+}
+
+static int lpass_lpaif_mi2s_channels(struct lpass_cpu_mi2s_data *pdata,
+		u32 channels, u32 bitwidth)
+{
+	u32 cfg;
+
+	cfg = readl(pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+
+	cfg &= ~LPAIF_MI2SCTL_SPKMODE_MASK;
+	cfg &= ~LPAIF_MI2SCTL_SPKMONO_MASK;
+
+	switch (channels) {
+	case 1:
+		cfg |= LPAIF_MI2SCTL_SPKMODE_SD0;
+		cfg |= LPAIF_MI2SCTL_SPKMONO_MONO;
+		break;
+	case 2:
+		cfg |= LPAIF_MI2SCTL_SPKMODE_SD0;
+		cfg |= LPAIF_MI2SCTL_SPKMONO_STEREO;
+		break;
+	case 4:
+		cfg |= LPAIF_MI2SCTL_SPKMODE_QUAD01;
+		cfg |= LPAIF_MI2SCTL_SPKMONO_STEREO;
+		break;
+	case 6:
+		cfg |= LPAIF_MI2SCTL_SPKMODE_6CH;
+		cfg |= LPAIF_MI2SCTL_SPKMONO_STEREO;
+		break;
+	case 8:
+		cfg |= LPAIF_MI2SCTL_SPKMODE_8CH;
+		cfg |= LPAIF_MI2SCTL_SPKMONO_STEREO;
+		break;
+	default:
+		pr_err("%s: invalid channels given: %u\n", __func__, channels);
+		return -EINVAL;
+	}
+
+	writel(cfg, pdata->base + LPAIF_MI2S_CTL_OFFSET(LPAIF_I2S_PORT_MI2S));
+
+	return 0;
+}
+
+
+static int lpass_cpu_mi2s_daiops_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	u32 ret;
+	u32 bit_act;
+	u32 bitwidth = params_format(params);
+	u32 channels = params_channels(params);
+	u32 rate = params_rate(params);
+	struct lpass_cpu_mi2s_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	bit_act = snd_pcm_format_width(bitwidth);
+	if (bit_act < 0) {
+		dev_err(dai->dev, "%s: Invalid bit width given\n", __func__);
+		return bit_act;
+	}
+
+	ret = lpass_lpaif_mi2s_channels(prtd, channels, bit_act);
+	if (ret) {
+		dev_err(dai->dev, "%s: Channel setting unsuccessful\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	ret = lpass_lpaif_mi2s_bitwidth(prtd, bitwidth);
+	if (ret) {
+		dev_err(dai->dev, "%s: Could not set bit width in HW\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	ret = clk_set_rate(prtd->mi2s_osr_clk,
+		(rate * bit_act * channels * LPASS_OSR_TO_BIT_DIVIDER));
+	if (ret) {
+		dev_err(dai->dev, "%s: error in setting mi2s osr clk: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(prtd->mi2s_osr_clk);
+	if (ret) {
+		dev_err(dai->dev, "%s: error in enabling mi2s osr clk: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = clk_set_rate(prtd->mi2s_bit_clk, rate * bit_act * channels);
+	if (ret) {
+		dev_err(dai->dev, "%s: error in setting mi2s bit clk: %d\n",
+				__func__, ret);
+		goto err;
+	}
+
+	ret = clk_prepare_enable(prtd->mi2s_bit_clk);
+	if (ret) {
+		dev_err(dai->dev, "%s: error in enabling mi2s bit clk: %d\n",
+				__func__, ret);
+		goto err;
+	}
+
+	prtd->mi2s_clocks_enabled = 1;
+
+	return 0;
+
+err:
+	clk_disable_unprepare(prtd->mi2s_osr_clk);
+
+	return ret;
+}
+
+static int lpass_cpu_mi2s_daiops_hw_free(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct lpass_cpu_mi2s_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	if (prtd->mi2s_clocks_enabled) {
+		clk_disable_unprepare(prtd->mi2s_osr_clk);
+		clk_disable_unprepare(prtd->mi2s_bit_clk);
+	}
+	prtd->mi2s_clocks_enabled = 0;
+
+	return 0;
+}
+
+static int lpass_cpu_mi2s_daiops_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *dai)
+{
+	int ret = 0;
+	struct lpass_cpu_mi2s_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		lpass_lpaif_mi2s_playback(prtd, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		lpass_lpaif_mi2s_playback(prtd, 0);
+		break;
+	default:
+		dev_err(dai->dev, "%s: Invalid trigger command given\n",
+				__func__);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+static struct snd_soc_dai_ops lpass_cpu_mi2s_ops = {
+	.hw_params	= lpass_cpu_mi2s_daiops_hw_params,
+	.hw_free	= lpass_cpu_mi2s_daiops_hw_free,
+	.trigger	= lpass_cpu_mi2s_daiops_trigger,
+};
+
+static int lpass_cpu_mi2s_dai_probe(struct snd_soc_dai *dai)
+{
+	struct lpass_cpu_mi2s_data *prtd = snd_soc_dai_get_drvdata(dai);
+
+	prtd->mi2s_osr_clk = devm_clk_get(dai->dev, "mi2s_osr_clk");
+	if (IS_ERR(prtd->mi2s_osr_clk)) {
+		dev_err(dai->dev, "%s: Error in getting mi2s_osr_clk\n",
+				__func__);
+		return PTR_ERR(prtd->mi2s_osr_clk);
+	}
+
+	prtd->mi2s_bit_clk = devm_clk_get(dai->dev, "mi2s_bit_clk");
+	if (IS_ERR(prtd->mi2s_bit_clk)) {
+		dev_err(dai->dev, "%s: Error in getting mi2s_bit_clk\n",
+				__func__);
+		return PTR_ERR(prtd->mi2s_bit_clk);
+	}
+
+	prtd->mi2s_clocks_enabled = 0;
+
+	/* disable MI2S port */
+	lpass_lpaif_mi2s_playback(prtd, 0);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver lpass_cpu_mi2s_dai_driver = {
+	.name = "lpass-cpu-mi2s-dai",
+	.playback = {
+		.stream_name	= "lpass-cpu-mi2s-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_mi2s_dai_probe,
+	.ops    = &lpass_cpu_mi2s_ops,
+};
+
+static const struct snd_soc_component_driver lpass_cpu_mi2s_comp_driver = {
+	.name = DRV_NAME,
+};
+
+static int lpass_cpu_mi2s_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *lpass_res;
+	struct lpass_cpu_mi2s_data *prtd;
+
+	prtd = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cpu_mi2s_data),
+			GFP_KERNEL);
+	if (!prtd)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, prtd);
+
+	prtd->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix_clk");
+	if (IS_ERR(prtd->ahbix_clk)) {
+		dev_err(&pdev->dev, "%s: Error in getting ahbix_clk\n",
+				__func__);
+		return PTR_ERR(prtd->ahbix_clk);
+	}
+
+	clk_set_rate(prtd->ahbix_clk, 131072);
+	ret = clk_prepare_enable(prtd->ahbix_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Error in enabling ahbix_clk\n",
+				__func__);
+		return ret;
+	}
+
+	lpass_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"lpass-lpaif-mem");
+	if (!lpass_res) {
+		dev_err(&pdev->dev, "%s: error getting resource\n", __func__);
+		ret = -ENODEV;
+		goto err_clk;
+	}
+
+	prtd->base = devm_ioremap_resource(&pdev->dev, lpass_res);
+	if (IS_ERR(prtd->base)) {
+		dev_err(&pdev->dev, "%s: error remapping resource\n",
+				__func__);
+		ret = PTR_ERR(prtd->base);
+		goto err_clk;
+	}
+
+	prtd->irqnum = platform_get_irq_byname(pdev, "lpass-lpaif-irq");
+	if (prtd->irqnum < 0) {
+		dev_err(&pdev->dev, "%s: failed get irq res\n", __func__);
+		return -ENODEV;
+	}
+
+	prtd->irq_acquired = 0;
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+			&lpass_cpu_mi2s_comp_driver,
+			&lpass_cpu_mi2s_dai_driver, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: error registering soc dai\n",
+				__func__);
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	clk_disable_unprepare(prtd->ahbix_clk);
+	return ret;
+}
+
+static int lpass_cpu_mi2s_platform_remove(struct platform_device *pdev)
+{
+	struct lpass_cpu_mi2s_data *prtd = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(prtd->ahbix_clk);
+
+	return 0;
+}
+
+static const struct of_device_id lpass_cpu_mi2s_dt_match[] = {
+	{.compatible = "qcom,lpass-cpu-mi2s"},
+	{}
+};
+
+static struct platform_driver lpass_cpu_mi2s_platform_driver = {
+	.driver	= {
+		.name	= DRV_NAME,
+		.of_match_table = lpass_cpu_mi2s_dt_match,
+	},
+	.probe	= lpass_cpu_mi2s_platform_probe,
+	.remove	= lpass_cpu_mi2s_platform_remove,
+};
+module_platform_driver(lpass_cpu_mi2s_platform_driver);
+
+MODULE_DESCRIPTION("QCOM LPASS MI2S CPU DRIVER");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, lpass_cpu_mi2s_dt_match);
diff --git a/sound/soc/qcom/lpass-cpu-mi2s.h b/sound/soc/qcom/lpass-cpu-mi2s.h
new file mode 100644
index 0000000000000000000000000000000000000000..4227a3661d2a90214e3e8bd43d21d3d3345da531
--- /dev/null
+++ b/sound/soc/qcom/lpass-cpu-mi2s.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2011,2013-2014 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_CPU_MI2S_H
+#define _LPASS_CPU_MI2S_H
+
+enum pinctrl_pin_state {
+	STATE_DISABLED = 0,
+	STATE_ENABLED = 1
+};
+static const char *const pin_states[] = {"Disabled", "Enabled"};
+
+struct mi2s_pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *disabled;
+	struct pinctrl_state *enabled;
+	enum pinctrl_pin_state curr_state;
+};
+
+/*
+ * Device data for the multi-channel I2S port in the low-power audio
+ * interface (LPAIF) within the low-power audio subsystem (LPASS).
+ * Both the CPU DAI driver and platform driver will access this.
+ */
+struct lpass_cpu_mi2s_data {
+	void __iomem *base;
+	struct clk *ahbix_clk;
+	struct clk *mi2s_bit_clk;
+	struct clk *mi2s_osr_clk;
+	int mi2s_clocks_enabled;
+	struct mi2s_pinctrl_info mi2s_pinfo;
+	int irqnum;
+	int irq_acquired;
+	uint8_t prepare_start;
+	uint32_t period_index;
+};
+
+#endif /* _LPASS_CPU_MI2S_H */
-- 
1.8.2.1

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

* [Patch v2 06/11] ASoC: ipq806x: Add I2S PCM platform driver
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (4 preceding siblings ...)
  2014-12-08 22:01 ` [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 16:04   ` Mark Brown
       [not found] ` <1418076073-12623-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Add PCM platform driver for the LPASS I2S port.

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

diff --git a/sound/soc/qcom/lpass-pcm-mi2s.c b/sound/soc/qcom/lpass-pcm-mi2s.c
new file mode 100644
index 0000000000000000000000000000000000000000..75ae2bc7d038a48845d502169d87ed55a1c0783d
--- /dev/null
+++ b/sound/soc/qcom/lpass-pcm-mi2s.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2010-2011,2013-2014 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/dma-mapping.h>
+#include <sound/soc.h>
+#include "lpass-lpaif.h"
+#include "lpass-cpu-mi2s.h"
+
+#define DRV_NAME			"lpass-pcm-mi2s"
+
+/* MI2S HW params */
+#define LPASS_MI2S_PERIOD_SIZE		(8064)
+#define LPASS_MI2S_PERIODS_MIN		(2)
+#define LPASS_MI2S_PERIODS_MAX		(4)
+#define LPASS_MI2S_BUFF_SIZE_MIN	(LPASS_MI2S_PERIOD_SIZE * \
+						LPASS_MI2S_PERIODS_MIN)
+#define LPASS_MI2S_BUFF_SIZE_MAX	(LPASS_MI2S_PERIOD_SIZE * \
+						LPASS_MI2S_PERIODS_MAX)
+
+static struct snd_pcm_hardware lpass_pcm_mi2s_hardware_playback = {
+	.info			=	SNDRV_PCM_INFO_MMAP |
+					SNDRV_PCM_INFO_BLOCK_TRANSFER |
+					SNDRV_PCM_INFO_MMAP_VALID |
+					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		=	8000,
+	.rate_max		=	192000,
+	.channels_min		=	1,
+	.channels_max		=	8,
+	.buffer_bytes_max	=	LPASS_MI2S_BUFF_SIZE_MAX,
+	.period_bytes_max	=	LPASS_MI2S_PERIOD_SIZE,
+	.period_bytes_min	=	LPASS_MI2S_PERIOD_SIZE,
+	.periods_min		=	LPASS_MI2S_PERIODS_MIN,
+	.periods_max		=	LPASS_MI2S_PERIODS_MAX,
+	.fifo_size		=	0,
+};
+
+static int lpass_lpaif_int_enable(struct lpass_cpu_mi2s_data *prtd)
+{
+	u32 intr_val;
+
+	/* clear status before enabling interrupt */
+	writel(LPAIF_DMAIRQ_ALL(LPAIF_DMA_RD_CH_MI2S),
+			prtd->base + LPAIF_DMAIRQ_CLEAR(LPAIF_IRQ_RECV_HOST));
+
+	intr_val = readl(prtd->base + LPAIF_DMAIRQ_EN(LPAIF_IRQ_RECV_HOST));
+	intr_val |= LPAIF_DMAIRQ_ALL(LPAIF_DMA_RD_CH_MI2S);
+	writel(intr_val, prtd->base + LPAIF_DMAIRQ_EN(LPAIF_IRQ_RECV_HOST));
+
+	return 0;
+}
+
+static int lpass_lpaif_int_disable(struct lpass_cpu_mi2s_data *prtd)
+{
+	u32 intr_val;
+
+	intr_val = readl(prtd->base + LPAIF_DMAIRQ_EN(LPAIF_IRQ_RECV_HOST));
+	intr_val &= ~LPAIF_DMAIRQ_ALL(LPAIF_DMA_RD_CH_MI2S);
+	writel(intr_val, prtd->base + LPAIF_DMAIRQ_EN(LPAIF_IRQ_RECV_HOST));
+
+	return 0;
+}
+
+static int lpass_lpaif_cfg_dma(struct lpass_cpu_mi2s_data *prtd,
+		dma_addr_t src_start, int buffer_size, int period_size,
+		int channels, int bitwidth)
+{
+	int ret = 0;
+	u32 cfg;
+
+	lpass_lpaif_int_enable(prtd);
+
+	writel(src_start, prtd->base +
+			LPAIF_DMA_BASEADDR(LPAIF_DMA_RD_CH_MI2S));
+	writel((buffer_size >> 2) - 1, prtd->base +
+			LPAIF_DMA_BUFFLEN(LPAIF_DMA_RD_CH_MI2S));
+	writel((period_size >> 2) - 1, prtd->base +
+			LPAIF_DMA_PERLEN(LPAIF_DMA_RD_CH_MI2S));
+
+	cfg = 0;
+	cfg |= LPAIF_DMACTL_BURST_EN;
+	cfg |= LPAIF_DMACTL_AUDIO_INTF_MI2S;
+	cfg |= LPAIF_DMACTL_FIFO_WM_8;
+	cfg |= LPAIF_DMACTL_ENABLE;
+
+	switch (bitwidth) {
+	case 16:
+		switch (channels) {
+		case 1:
+		case 2:
+			cfg |= LPAIF_DMACTL_WPSCNT_SINGLE;
+			break;
+		case 4:
+			cfg |= LPAIF_DMACTL_WPSCNT_DOUBLE;
+			break;
+		case 6:
+			cfg |= LPAIF_DMACTL_WPSCNT_TRIPLE;
+			break;
+		case 8:
+			cfg |= LPAIF_DMACTL_WPSCNT_QUAD;
+			break;
+		default:
+			pr_err("%s: invalid PCM config given: bw=%u, ch=%u\n",
+					__func__, bitwidth, channels);
+			ret = -EINVAL;
+		}
+		break;
+	case 24:
+	case 32:
+		switch (channels) {
+		case 1:
+			cfg |= LPAIF_DMACTL_WPSCNT_SINGLE;
+			break;
+		case 2:
+			cfg |= LPAIF_DMACTL_WPSCNT_DOUBLE;
+			break;
+		case 4:
+			cfg |= LPAIF_DMACTL_WPSCNT_QUAD;
+			break;
+		case 6:
+			cfg |= LPAIF_DMACTL_WPSCNT_SIXPACK;
+			break;
+		case 8:
+			cfg |= LPAIF_DMACTL_WPSCNT_OCTAL;
+			break;
+		default:
+			pr_err("%s: invalid PCM config given: bw=%u, ch=%u\n",
+					__func__, bitwidth, channels);
+			ret = -EINVAL;
+		}
+		break;
+	default:
+		pr_err("%s: invalid PCM config given: bw=%u, ch=%u\n",
+				__func__, bitwidth, channels);
+		ret = -EINVAL;
+	}
+
+	if (!ret)
+		writel(cfg, prtd->base + LPAIF_DMA_CTL(LPAIF_DMA_RD_CH_MI2S));
+
+	return ret;
+}
+
+static void lpass_lpaif_dma_stop_clear(struct lpass_cpu_mi2s_data *prtd)
+{
+	writel(0x0, prtd->base + LPAIF_DMA_CTL(LPAIF_DMA_RD_CH_MI2S));
+}
+
+static void lpass_lpaif_dma_stop(struct lpass_cpu_mi2s_data *prtd)
+{
+	u32 cfg;
+
+	cfg = readl(prtd->base + LPAIF_DMA_CTL(LPAIF_DMA_RD_CH_MI2S));
+	cfg &= ~LPAIF_DMACTL_ENABLE;
+	writel(cfg, prtd->base + LPAIF_DMA_CTL(LPAIF_DMA_RD_CH_MI2S));
+}
+
+static int lpass_pcm_mi2s_alloc_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size;
+
+	size = lpass_pcm_mi2s_hardware_playback.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_coherent(pcm->card->dev, size,
+			&buf->addr, GFP_KERNEL);
+	if (!buf->area) {
+		dev_err(prtd->dev, "%s: Could not allocate DMA buffer\n",
+				__func__);
+		return -ENOMEM;
+	}
+	buf->bytes = size;
+
+	return 0;
+}
+
+static void lpass_pcm_mi2s_free_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+
+	substream = pcm->streams[stream].substream;
+	buf = &substream->dma_buffer;
+	if (buf->area) {
+		dma_free_coherent(pcm->card->dev, buf->bytes, buf->area,
+				buf->addr);
+	}
+	buf->area = NULL;
+}
+
+static irqreturn_t lpass_pcm_mi2s_irq(int irq, void *data)
+{
+	irqreturn_t ret = IRQ_NONE;
+	u32 intrsrc;
+	u32 has_xrun, pending;
+	struct snd_pcm_substream *substream = data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	intrsrc = readl(prtd->base + LPAIF_DMAIRQ_STAT(LPAIF_IRQ_RECV_HOST));
+	intrsrc &= LPAIF_DMAIRQ_ALL(LPAIF_DMA_RD_CH_MI2S);
+	writel(intrsrc, prtd->base + LPAIF_DMAIRQ_CLEAR(LPAIF_IRQ_RECV_HOST));
+
+	pending = intrsrc & LPAIF_DMAIRQ_ALL(LPAIF_DMA_RD_CH_MI2S);
+	has_xrun = pending & LPAIF_DMAIRQ_XRUN(LPAIF_DMA_RD_CH_MI2S);
+
+	if (unlikely(has_xrun) && snd_pcm_running(substream)) {
+		dev_warn(soc_prtd->dev, "%s: xrun warning\n", __func__);
+		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		pending &= ~LPAIF_DMAIRQ_XRUN(LPAIF_DMA_RD_CH_MI2S);
+		ret = IRQ_HANDLED;
+	}
+
+	if (pending & LPAIF_DMAIRQ_PER(LPAIF_DMA_RD_CH_MI2S)) {
+		if (++prtd->period_index >= runtime->periods)
+			prtd->period_index = 0;
+		snd_pcm_period_elapsed(substream);
+		pending &= ~LPAIF_DMAIRQ_PER(LPAIF_DMA_RD_CH_MI2S);
+		ret = IRQ_HANDLED;
+	}
+
+	if (pending & LPAIF_DMAIRQ_XRUN(LPAIF_DMA_RD_CH_MI2S)) {
+		snd_pcm_period_elapsed(substream);
+		dev_warn(soc_prtd->dev, "%s: xrun warning\n", __func__);
+		ret = IRQ_HANDLED;
+	}
+
+	if (pending & LPAIF_DMAIRQ_ERR(LPAIF_DMA_RD_CH_MI2S)) {
+		dev_err(soc_prtd->dev, "%s: Bus access error\n", __func__);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int lpass_pcm_mi2s_open(struct snd_pcm_substream *substream)
+{
+	int ret;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	prtd->prepare_start = 0;
+	prtd->period_index = 0;
+
+	runtime->dma_bytes = lpass_pcm_mi2s_hardware_playback.buffer_bytes_max;
+	snd_soc_set_runtime_hwparams(substream,
+			&lpass_pcm_mi2s_hardware_playback);
+
+	ret = snd_pcm_hw_constraint_integer(runtime,
+			SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0) {
+		dev_err(soc_prtd->dev,
+				"%s: snd_pcm_hw_constraint_integer failed\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+	return 0;
+}
+
+static int lpass_pcm_mi2s_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	lpass_lpaif_dma_stop_clear(prtd);
+	lpass_lpaif_int_disable(prtd);
+
+	return 0;
+}
+
+static int lpass_pcm_mi2s_prepare(struct snd_pcm_substream *substream)
+{
+	int ret;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	/* xrun recovery */
+	if (prtd->prepare_start)
+		return 0;
+
+	lpass_lpaif_dma_stop(prtd);
+	prtd->prepare_start = 1;
+
+	ret = lpass_lpaif_cfg_dma(prtd, runtime->dma_addr,
+			snd_pcm_lib_buffer_bytes(substream),
+			snd_pcm_lib_period_bytes(substream), runtime->channels,
+			runtime->sample_bits);
+	if (ret) {
+		dev_err(soc_prtd->dev, "%s: Error in configuring DMA\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int lpass_pcm_mi2s_mmap(struct snd_pcm_substream *substream,
+		struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	return dma_mmap_coherent(substream->pcm->card->dev, vma,
+		runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+}
+
+static snd_pcm_uframes_t lpass_pcm_mi2s_pointer(
+		struct snd_pcm_substream *substream)
+{
+	snd_pcm_uframes_t offset;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	offset = prtd->period_index * runtime->period_size;
+
+	return offset >= (runtime->buffer_size) ? 0 : offset;
+}
+
+static struct snd_pcm_ops lpass_pcm_mi2s_soc_ops = {
+	.open		= lpass_pcm_mi2s_open,
+	.close		= lpass_pcm_mi2s_close,
+	.prepare	= lpass_pcm_mi2s_prepare,
+	.mmap		= lpass_pcm_mi2s_mmap,
+	.pointer	= lpass_pcm_mi2s_pointer,
+	.ioctl		= snd_pcm_lib_ioctl,
+};
+
+static int lpass_pcm_mi2s_soc_new(struct snd_soc_pcm_runtime *soc_prtd)
+{
+	int ret;
+	struct snd_card *card = soc_prtd->card->snd_card;
+	struct snd_pcm *pcm = soc_prtd->pcm;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+	struct snd_pcm_substream *substream =
+		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &card->dev->coherent_dma_mask;
+
+	ret = lpass_pcm_mi2s_alloc_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
+	if (ret)
+		return ret;
+
+	ret = request_irq(prtd->irqnum, lpass_pcm_mi2s_irq,
+			IRQF_TRIGGER_RISING, "lpass-lpaif-intr", substream);
+	if (ret) {
+		dev_err(soc_prtd->dev, "%s: irq resource request failed\n",
+				__func__);
+		goto err;
+	}
+	prtd->irq_acquired = 1;
+
+	return 0;
+
+err:
+	lpass_pcm_mi2s_free_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
+	return ret;
+}
+
+static void lpass_pcm_mi2s_soc_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream =
+		pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+	struct lpass_cpu_mi2s_data *prtd =
+		snd_soc_dai_get_drvdata(soc_prtd->cpu_dai);
+
+	lpass_pcm_mi2s_free_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
+
+	disable_irq(prtd->irqnum);
+	if (prtd->irq_acquired)
+		free_irq(prtd->irqnum, NULL);
+	prtd->irq_acquired = 0;
+}
+
+static struct snd_soc_platform_driver lpass_pcm_mi2s_soc_driver = {
+	.pcm_new	= lpass_pcm_mi2s_soc_new,
+	.pcm_free	= lpass_pcm_mi2s_soc_free,
+	.ops		= &lpass_pcm_mi2s_soc_ops,
+};
+
+static int lpass_pcm_mi2s_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = devm_snd_soc_register_platform(&pdev->dev,
+			&lpass_pcm_mi2s_soc_driver);
+	if (ret)
+		dev_err(&pdev->dev, "%s: Failed to register pcm device: %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static const struct of_device_id lpass_pcm_mi2s_dt_match[] = {
+	{ .compatible = "qcom,lpass-pcm-mi2s", },
+	{}
+};
+
+static struct platform_driver lpass_pcm_mi2s_platform_driver = {
+	.driver	= {
+		.name	= DRV_NAME,
+		.of_match_table = lpass_pcm_mi2s_dt_match,
+	},
+	.probe	= lpass_pcm_mi2s_platform_probe,
+};
+module_platform_driver(lpass_pcm_mi2s_platform_driver);
+
+MODULE_DESCRIPTION("QCOM LPASS MI2S PLATFORM DRIVER");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, lpass_pcm_mi2s_dt_match);
-- 
1.8.2.1

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

* [Patch v2 07/11] ASoC: ipq806x: Add machine driver for IPQ806X SOC
       [not found] ` <1418076073-12623-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2014-12-08 22:01   ` Kenneth Westfield
  2014-12-09 16:05     ` Mark Brown
  2014-12-08 22:01   ` [Patch v2 08/11] ASoC: codec: Add ability to build QCOM codec Kenneth Westfield
  1 sibling, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

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

Add machine driver for the IPQ806X LPASS SOC.

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

diff --git a/sound/soc/qcom/ipq806x.c b/sound/soc/qcom/ipq806x.c
new file mode 100644
index 0000000000000000000000000000000000000000..58bc64105ce6176cbe9408e5a75e4a7d7be437a1
--- /dev/null
+++ b/sound/soc/qcom/ipq806x.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2010-2011,2013-2014 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 <sound/soc.h>
+
+#define DRV_NAME	"ipq806x-machine"
+
+static struct snd_soc_dai_link ipq806x_machine_dai_link = {
+	.name		= "IPQ806x Media1",
+	.stream_name	= "MultiMedia1",
+};
+
+static int ipq806x_populate_dai_link_of_nodes(struct snd_soc_card *card)
+{
+	int ret;
+	struct device *cdev = card->dev;
+	struct snd_soc_dai_link *dai_link = card->dai_link;
+	struct device_node *np;
+
+	np = of_parse_phandle(cdev->of_node, "platform", 0);
+	if (!np) {
+		dev_err(cdev, "%s: no phandle for platform driver\n",
+				__func__);
+		return -ENODEV;
+	}
+	dai_link->platform_of_node = np;
+
+	np = of_parse_phandle(cdev->of_node, "cpu", 0);
+	if (!np) {
+		dev_err(cdev, "%s: no phandle for cpu-dai driver\n", __func__);
+		return -ENODEV;
+	}
+	dai_link->cpu_of_node = np;
+
+	np = of_parse_phandle(cdev->of_node, "codec", 0);
+	if (!np) {
+		dev_err(cdev, "%s: no phandle for codec driver\n", __func__);
+		return -ENODEV;
+	}
+	dai_link->codec_of_node = np;
+
+	ret = of_property_read_string(cdev->of_node, "codec-dai",
+			&dai_link->codec_dai_name);
+	if (ret) {
+		dev_err(cdev, "%s: no name for codec dai\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_card ipq806x_machine_soc_card = {
+	.name	= DRV_NAME,
+	.dev	= NULL,
+};
+
+static int ipq806x_machine_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct snd_soc_card *card = &ipq806x_machine_soc_card;
+
+	if (card->dev) {
+		dev_err(&pdev->dev, "soundcard instance already created\n");
+		return -ENODEV;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret) {
+		dev_err(&pdev->dev, "parse card name failed, err:%d\n", ret);
+		return ret;
+	}
+
+	card->dai_link	= &ipq806x_machine_dai_link;
+	card->num_links	= 1;
+
+	ret = ipq806x_populate_dai_link_of_nodes(card);
+	if (ret) {
+		dev_err(&pdev->dev, "could not resolve dai links, err:%d\n",
+				ret);
+		return ret;
+	}
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret == -EPROBE_DEFER) {
+		card->dev = NULL;
+		return ret;
+	} else if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id ipq806x_machine_dt_match[]  = {
+	{ .compatible = "qcom,ipq806x-snd-card", },
+	{},
+};
+
+static struct platform_driver ipq806x_machine_platform_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = ipq806x_machine_dt_match,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = ipq806x_machine_platform_probe,
+};
+module_platform_driver(ipq806x_machine_platform_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806X MACHINE DRIVER");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, ipq806x_asoc_machine_of_match);
-- 
1.8.2.1

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

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

* [Patch v2 08/11] ASoC: codec: Add ability to build QCOM codec
       [not found] ` <1418076073-12623-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  2014-12-08 22:01   ` [Patch v2 07/11] ASoC: ipq806x: Add machine driver for IPQ806X SOC Kenneth Westfield
@ 2014-12-08 22:01   ` Kenneth Westfield
  2014-12-09 16:06     ` Mark Brown
  1 sibling, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

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

Now that all codec drivers are in place, allow
them to build.

Signed-off-by: Kenneth Westfield <kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Acked-by: Banajit Goswami <bgoswami-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 sound/soc/codecs/Kconfig  | 4 ++++
 sound/soc/codecs/Makefile | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 883c5778b309322797a9b49b38b2ff117eec079b..499351a3537e56caf308825fec9612d366131ced 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 if SND_SOC_QCOM
 	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9768 if I2C
 	select SND_SOC_MAX9877 if I2C
@@ -827,6 +828,9 @@ config SND_SOC_LM4857
 config SND_SOC_MAX9768
 	tristate
 
+config SND_SOC_MAX98357A
+	tristate
+
 config SND_SOC_MAX9877
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bbdfd1e1c182f9ee102f532f391f522e77a8922b..1a5840859c13c0cfd8039c8bf5a40521c60dcf9c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -173,6 +173,7 @@ snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
 
 # Amp
+snd-soc-max98357a-objs := max98357a.o
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-tas2552-objs := tas2552.o
@@ -351,5 +352,6 @@ obj-$(CONFIG_SND_SOC_WM_ADSP)	+= snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
 
 # Amp
+obj-$(CONFIG_SND_SOC_MAX98357A)	+= snd-soc-max98357a.o
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
-- 
1.8.2.1

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

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

* [Patch v2 09/11] ASoC: qcom: Add ability to build QCOM drivers
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (6 preceding siblings ...)
       [not found] ` <1418076073-12623-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 16:07   ` Mark Brown
  2014-12-08 22:01 ` [Patch v2 10/11] ASoC: Allow for building " Kenneth Westfield
  2014-12-08 22:01 ` [Patch v2 11/11] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Now all drivers are in place, allow them to build.

Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
Acked-by: Banajit Goswami <bgoswami@codeaurora.org>
---
 sound/soc/qcom/Kconfig  | 25 +++++++++++++++++++++++++
 sound/soc/qcom/Makefile | 11 +++++++++++
 2 files changed, 36 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..cd4d88bc079c02d3a665b163aefca798fa8a08dc
--- /dev/null
+++ b/sound/soc/qcom/Kconfig
@@ -0,0 +1,25 @@
+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_CPU_MI2S
+	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
+	select SND_SOC_PCM_MI2S
+	select SND_SOC_CPU_MI2S
+        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_PCM_MI2S
+	tristate
+	depends on SND_SOC_QCOM
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0c5779a72c8ef95e3d6da12c76303997d91d11a6
--- /dev/null
+++ b/sound/soc/qcom/Makefile
@@ -0,0 +1,11 @@
+# Platform
+snd-soc-lpass-pcm-mi2s-objs := lpass-pcm-mi2s.o
+snd-soc-lpass-cpu-mi2s-objs := lpass-cpu-mi2s.o
+
+obj-$(CONFIG_SND_SOC_PCM_MI2S) += snd-soc-lpass-pcm-mi2s.o
+obj-$(CONFIG_SND_SOC_CPU_MI2S) += snd-soc-lpass-cpu-mi2s.o
+
+# Machine
+snd-soc-ipq806x-objs := ipq806x.o
+
+obj-$(CONFIG_SND_SOC_IPQ806X) += snd-soc-ipq806x.o
-- 
1.8.2.1

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

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

From: Kenneth Westfield <kwestfie@codeaurora.org>

Allow for the QCOM LPASS 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 7d5d6444a83737ffa3c01acbe1925de619e0390a..b98eebf0e30bba19ec24acc7f0e6ab155e5e602b 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 865e090c80616024a552da5e33d2796b9be1dbbd..3d78a8d874dc98dd6219b33e3f2c100ef0334bfc 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/
-- 
1.8.2.1

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

* [Patch v2 11/11] ARM: dts: Model IPQ LPASS audio hardware
  2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
                   ` (8 preceding siblings ...)
  2014-12-08 22:01 ` [Patch v2 10/11] ASoC: Allow for building " Kenneth Westfield
@ 2014-12-08 22:01 ` Kenneth Westfield
  2014-12-09 16:08   ` Mark Brown
  9 siblings, 1 reply; 20+ messages in thread
From: Kenneth Westfield @ 2014-12-08 22:01 UTC (permalink / raw)
  To: Mark Brown, Takashi Iwai, Liam Girdwood, David Brown,
	Bryan Huntsman, Rob Herring, Greg KH, Patrick Lai,
	Banajit Goswami
  Cc: ALSA Mailing List, Device Tree Mailing List, MSM Mailing List,
	Kenneth Westfield

From: Kenneth Westfield <kwestfie@codeaurora.org>

Model the LPASS audio hardware for the IPQ806X.

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

diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 63b2146f563b541e4994697af5ee1bbb41a4abd1..fb1d6f6e290b9c645eb82fc4403d0fba48305f81 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>
 
 / {
@@ -66,6 +67,31 @@
 		ranges;
 		compatible = "simple-bus";
 
+		lpass_pcm_mi2s: lpass-pcm-mi2s {
+			compatible = "qcom,lpass-pcm-mi2s";
+			status = "disabled";
+		};
+
+		lpass_cpu_mi2s: lpass-cpu-mi2s {
+			compatible = "qcom,lpass-cpu-mi2s";
+			status = "disabled";
+			reg = <0x28100000 0x10000>;
+			reg-names = "lpass-lpaif-mem";
+			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-lpaif-irq";
+		};
+
+		max98357a_codec: max98357a-codec {
+			compatible = "qcom,max98357a-codec";
+			status = "disabled";
+		};
+
 		qcom_pinmux: pinmux@800000 {
 			compatible = "qcom,ipq8064-pinctrl";
 			reg = <0x800000 0x4000>;
@@ -234,6 +260,13 @@
 			};
 		};
 
+		lcc: clock-controller@28000000 {
+			compatible = "qcom,lcc-ipq8064";
+			reg = <0x28000000 0x1000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		sata_phy: sata-phy@1b400000 {
 			compatible = "qcom,ipq806x-sata-phy";
 			reg = <0x1b400000 0x200>;
-- 
1.8.2.1

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

* Re: [Patch v2 02/11] ASoC: qcom: Add device tree binding docs
  2014-12-08 22:01 ` [Patch v2 02/11] ASoC: qcom: Add device tree binding docs Kenneth Westfield
@ 2014-12-09 15:37   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 15:37 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Rob Herring, Greg KH, Patrick Lai, Banajit Goswami,
	ALSA Mailing List, Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:04PM -0800, Kenneth Westfield wrote:
> From: Kenneth Westfield <kwestfie@codeaurora.org>
> 
> Add documentation to the sound directory of the
> device-tree bindings for IPQ806x audio drivers.

Please don't send multiple separate changes in a single patch.  One
change per patch.

>  .../bindings/sound/qcom,max98357a-codec.txt        | 23 ++++++++++++++++

You are reporting the vendor for this Maxim device as Qualcomm which
isn't right, please review the meaning of the vendor information in the
device tree binding strings.

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

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

* Re: [Patch v2 04/11] ASoC: codec: Add Maxim codec driver
  2014-12-08 22:01 ` [Patch v2 04/11] ASoC: codec: Add Maxim codec driver Kenneth Westfield
@ 2014-12-09 15:53   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 15:53 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Rob Herring, Greg KH, Patrick Lai, Banajit Goswami,
	ALSA Mailing List, Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:06PM -0800, Kenneth Westfield wrote:

> +enum pinctrl_pin_state {
> +	STATE_DISABLED = 0,
> +	STATE_ENABLED = 1
> +};
> +static const char * const pin_states[] = {"Disabled", "Enabled"};

This looks like you are trying to reimplement some of the generic
support provided by the pinctrl framework - please don't do that.  It
looks like you should be using the standard idle and default states.

However I'm also questioning why this device is using pinctrl at all.
As far as I can see from the code it's a dumb external device with just
an enable control and hence no pin control support so it's not a device
I'd expect to have any pinmux to control.  Why is it doing this?  There
are also substantial problems throughout the relevant code but probably
the best thing is just to remove it all.

> +static int max98357a_codec_set_pinctrl(struct max98357a_codec_pinctrl *mi2s)
> +{
> +	int ret;
> +
> +	pr_debug("%s: curr_state = %s\n", __func__,
> +			pin_states[mi2s->curr_state]);

To repeat my previous review comments: use dev_ prints.

> +static struct snd_soc_dai_driver max98357a_codec_dai_driver = {
> +	.name = "max98357a-codec-dai",
> +	.playback = {
> +		.stream_name	= "max98357a-codec-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,
> +	},
> +	.probe = &max98357a_codec_dai_probe,
> +	.ops = &max98357a_codec_dai_ops,
> +};

This CODEC driver has no DAPM support.  I'm surprised this works at all,
it's certainly not OK for upstream - you need to implement at least stub
DAPM support.

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

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

* Re: [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver
  2014-12-08 22:01 ` [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
@ 2014-12-09 16:01   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:01 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman, Greg KH,
	Patrick Lai, Banajit Goswami, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:07PM -0800, Kenneth Westfield wrote:

Please stop CCing Rob Herring's Calxeda address, it bounces.

> +	default:
> +		pr_err("%s: invalid bitwidth given: %u\n", __func__, bitwidth);
> +		return -EINVAL;
> +	}

Repeating again: dev_err().

> +	ret = lpass_lpaif_mi2s_channels(prtd, channels, bit_act);

> +	ret = lpass_lpaif_mi2s_bitwidth(prtd, bitwidth);

Just inline these helper functions, they're basically just abstracting a
single switch statement each which adds little if anything.

> +static int lpass_cpu_mi2s_daiops_hw_free(struct snd_pcm_substream *substream,
> +		struct snd_soc_dai *dai)
> +{
> +	struct lpass_cpu_mi2s_data *prtd = snd_soc_dai_get_drvdata(dai);
> +
> +	if (prtd->mi2s_clocks_enabled) {
> +		clk_disable_unprepare(prtd->mi2s_osr_clk);
> +		clk_disable_unprepare(prtd->mi2s_bit_clk);
> +	}

This seems problematic, why is the clock being disabled here rather than
in a place matching that where it was enabled so we don't need to do
this checking.  I suspect you should be using a DAPM widget to manage
the clocks.

> +	prtd->irq_acquired = 0;

What is this supposed to do?  It looks write only.

> +#ifndef _LPASS_CPU_MI2S_H
> +#define _LPASS_CPU_MI2S_H
> +
> +enum pinctrl_pin_state {
> +	STATE_DISABLED = 0,
> +	STATE_ENABLED = 1
> +};
> +static const char *const pin_states[] = {"Disabled", "Enabled"};

This apppears to be the same pinctrl stuff you had in the Maxim CODEC
driver.  Similar issues with reproducing core pinctrl functionality
apply here too, and the fact that the code has been cut'n'pasted between
different drivers isn't a good sign.

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

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

* Re: [Patch v2 06/11] ASoC: ipq806x: Add I2S PCM platform driver
  2014-12-08 22:01 ` [Patch v2 06/11] ASoC: ipq806x: Add I2S PCM platform driver Kenneth Westfield
@ 2014-12-09 16:04   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:04 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Rob Herring, Greg KH, Patrick Lai, Banajit Goswami,
	ALSA Mailing List, Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:08PM -0800, Kenneth Westfield wrote:

> +static int lpass_pcm_mi2s_platform_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +
> +	ret = devm_snd_soc_register_platform(&pdev->dev,
> +			&lpass_pcm_mi2s_soc_driver);
> +	if (ret)
> +		dev_err(&pdev->dev, "%s: Failed to register pcm device: %d\n",
> +				__func__, ret);
> +
> +	return ret;
> +}

> +static const struct of_device_id lpass_pcm_mi2s_dt_match[] = {
> +	{ .compatible = "qcom,lpass-pcm-mi2s", },
> +	{}
> +};

This device which is intended to appear in the device tree and accesses
hardware acquires no resources on probe.  That indicates that there's
something wrong with the way you're modelling things in device tree; my
best guess would be that it's part of the I2S controller and should be
being instantiated from the I2S DAI driver code not the DT - many other
drivers use this model, it's very standard.

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

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

* Re: [Patch v2 07/11] ASoC: ipq806x: Add machine driver for IPQ806X SOC
  2014-12-08 22:01   ` [Patch v2 07/11] ASoC: ipq806x: Add machine driver for IPQ806X SOC Kenneth Westfield
@ 2014-12-09 16:05     ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:05 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Rob Herring, Greg KH, Patrick Lai, Banajit Goswami,
	ALSA Mailing List, Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:09PM -0800, Kenneth Westfield wrote:
> From: Kenneth Westfield <kwestfie@codeaurora.org>
> 
> Add machine driver for the IPQ806X LPASS SOC.

This looks like it should be able to use simple-card - is there
something I'm missing here?

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

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

* Re: [Patch v2 08/11] ASoC: codec: Add ability to build QCOM codec
  2014-12-08 22:01   ` [Patch v2 08/11] ASoC: codec: Add ability to build QCOM codec Kenneth Westfield
@ 2014-12-09 16:06     ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:06 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman, Greg KH,
	Patrick Lai, Banajit Goswami, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:10PM -0800, Kenneth Westfield wrote:
> From: Kenneth Westfield <kwestfie@codeaurora.org>
> 
> Now that all codec drivers are in place, allow
> them to build.

This isn't a Qualcomm CODEC and this should be part of the patch adding
the driver.

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

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

* Re: [Patch v2 09/11] ASoC: qcom: Add ability to build QCOM drivers
  2014-12-08 22:01 ` [Patch v2 09/11] ASoC: qcom: Add ability to build QCOM drivers Kenneth Westfield
@ 2014-12-09 16:07   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:07 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman, Greg KH,
	Patrick Lai, Banajit Goswami, ALSA Mailing List,
	Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:11PM -0800, Kenneth Westfield wrote:

> +config SND_SOC_CPU_MI2S
> +	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
> +	select SND_SOC_PCM_MI2S
> +	select SND_SOC_CPU_MI2S
> +        select SND_SOC_MAX98357A

Any reason for these not to have an || COMPILE_TEST dependency?

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

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

* Re: [Patch v2 11/11] ARM: dts: Model IPQ LPASS audio hardware
  2014-12-08 22:01 ` [Patch v2 11/11] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield
@ 2014-12-09 16:08   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2014-12-09 16:08 UTC (permalink / raw)
  To: Kenneth Westfield
  Cc: Takashi Iwai, Liam Girdwood, David Brown, Bryan Huntsman,
	Rob Herring, Greg KH, Patrick Lai, Banajit Goswami,
	ALSA Mailing List, Device Tree Mailing List, MSM Mailing List

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

On Mon, Dec 08, 2014 at 02:01:13PM -0800, Kenneth Westfield wrote:

> +		max98357a_codec: max98357a-codec {
> +			compatible = "qcom,max98357a-codec";
> +			status = "disabled";
> +		};
> +
>  		qcom_pinmux: pinmux@800000 {

This appears to be adding an off-SoC CODEC driver to the .dtsi for the
SoC.  Don't do that, just let the relevant boards register the devices
on them.

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

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

end of thread, other threads:[~2014-12-09 16:08 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-08 22:01 [Patch v2 00/11] ASoC: QCOM: Add support for ipq806x SOC Kenneth Westfield
2014-12-08 22:01 ` [Patch v2 01/11] MAINTAINERS: Add QCOM audio ASoC maintainer Kenneth Westfield
2014-12-08 22:01 ` [Patch v2 02/11] ASoC: qcom: Add device tree binding docs Kenneth Westfield
2014-12-09 15:37   ` Mark Brown
2014-12-08 22:01 ` [Patch v2 03/11] ASoC: ipq806x: add LPAIF header file Kenneth Westfield
2014-12-08 22:01 ` [Patch v2 04/11] ASoC: codec: Add Maxim codec driver Kenneth Westfield
2014-12-09 15:53   ` Mark Brown
2014-12-08 22:01 ` [Patch v2 05/11] ASoC: ipq806x: Add LPASS CPU DAI driver Kenneth Westfield
2014-12-09 16:01   ` Mark Brown
2014-12-08 22:01 ` [Patch v2 06/11] ASoC: ipq806x: Add I2S PCM platform driver Kenneth Westfield
2014-12-09 16:04   ` Mark Brown
     [not found] ` <1418076073-12623-1-git-send-email-kwestfie-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2014-12-08 22:01   ` [Patch v2 07/11] ASoC: ipq806x: Add machine driver for IPQ806X SOC Kenneth Westfield
2014-12-09 16:05     ` Mark Brown
2014-12-08 22:01   ` [Patch v2 08/11] ASoC: codec: Add ability to build QCOM codec Kenneth Westfield
2014-12-09 16:06     ` Mark Brown
2014-12-08 22:01 ` [Patch v2 09/11] ASoC: qcom: Add ability to build QCOM drivers Kenneth Westfield
2014-12-09 16:07   ` Mark Brown
2014-12-08 22:01 ` [Patch v2 10/11] ASoC: Allow for building " Kenneth Westfield
2014-12-08 22:01 ` [Patch v2 11/11] ARM: dts: Model IPQ LPASS audio hardware Kenneth Westfield
2014-12-09 16:08   ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).