Re: [PATCH] xhci: use iopoll for xhci_handshake

2019-02-28 Thread Daniel Kurtz
On Thu, Feb 28, 2019 at 12:09 AM Greg Kroah-Hartman
 wrote:
>
> On Wed, Feb 27, 2019 at 03:19:17PM -0700, Daniel Kurtz wrote:
> > In cases such as xhci_abort_cmd_ring(), xhci_handshake() is called with
> > a spin lock held (and local interrupts disabled) with a huge 5 second
> > timeout.  This can translates to 5 million calls to udelay(1).  By its
> > very nature, udelay() is not meant to be precise, it only guarantees to
> > delay a minimum of 1 microsecond. Therefore the actual delay of
> > xhci_handshake() can be significantly longer.  If the average udelay(1)
> > is greater than 2.2 us, the total time in xhci_handshake() - with
> > interrupts disabled can be > 11 seconds triggering the kernel's soft lockup
> > detector.
> >
> > To avoid this, let's replace the open coded io polling loop with one from
> > iopoll.h that uses a loop timed with the more presumably reliable ktime
> > infrastructure.
> >
> > Signed-off-by: Daniel Kurtz 
>
> Looks sane to me, nice fixup.
>
> Reviewed-by: Greg Kroah-Hartman 
>
> Is this causing problems on older kernels/devices today such that we
> should backport this?

We detected that xhci_handshake timing out can lead to softlockup
while debugging a USB issue on a new product.  The xhci_handshake
timeout itself is a symptom of another underlying problem causing some
commands to be aborted.  I don't know if any such underlying problems
exist on other older devices, but the potential is there so a backport
is reasonable.  Although, it may just shift the symptom of an
underlying problem from a softlockup/oops to some other symptom, like
USB just being dead.

-Dan

>
> thanks,
>
> greg k-h


[PATCH] xhci: use iopoll for xhci_handshake

2019-02-27 Thread Daniel Kurtz
In cases such as xhci_abort_cmd_ring(), xhci_handshake() is called with
a spin lock held (and local interrupts disabled) with a huge 5 second
timeout.  This can translates to 5 million calls to udelay(1).  By its
very nature, udelay() is not meant to be precise, it only guarantees to
delay a minimum of 1 microsecond. Therefore the actual delay of
xhci_handshake() can be significantly longer.  If the average udelay(1)
is greater than 2.2 us, the total time in xhci_handshake() - with
interrupts disabled can be > 11 seconds triggering the kernel's soft lockup
detector.

To avoid this, let's replace the open coded io polling loop with one from
iopoll.h that uses a loop timed with the more presumably reliable ktime
infrastructure.

Signed-off-by: Daniel Kurtz 
---
 drivers/usb/host/xhci.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 005e65922608e..fde5ff84ba69b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "xhci.h"
 #include "xhci-trace.h"
@@ -69,18 +70,18 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring 
*ring)
 int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
 {
u32 result;
+   int ret;
 
-   do {
-   result = readl(ptr);
-   if (result == ~(u32)0)  /* card removed */
-   return -ENODEV;
-   result &= mask;
-   if (result == done)
-   return 0;
-   udelay(1);
-   usec--;
-   } while (usec > 0);
-   return -ETIMEDOUT;
+   ret = readl_poll_timeout_atomic(ptr, result,
+   ((result & mask) == done || (result == ~(u32)0)),
+   1, usec);
+   if (ret)
+   return ret;
+
+   if (result == ~(u32)0)  /* card removed */
+   return -ENODEV;
+
+   return 0;
 }
 
 /*
-- 
2.21.0.rc2.261.ga7da99ff1b-goog



Re: [PATCH 2/2] ASoC: DA7219: Implement error check on reg read and write

2018-12-05 Thread Daniel Kurtz
On Wed, Dec 5, 2018 at 4:28 AM Mark Brown  wrote:
>
> On Wed, Dec 05, 2018 at 10:21:04AM +, Adam Thomson wrote:
>
> > If the previous I2C access failed, how can we be sure that the write back 
> > to HW
> > of 0xFF even succeeds? More importantly these error returns won't 
> > necessarily
> > stop subsequent calls to controls within the Codec I believe, so you could 
> > still
> > see unwanted writes to HW via I2C, if I2C is sporadically operational. 
> > Again I
> > don't see this update resolving that. The key thing is to resolve why even 
> > just
> > one I2C transaction fails.
>
> Right, it's just not clear what we can constructively do if the I2C bus
> falls to bits other than log things and the I2C controllers will
> generally do that themselves.  There's no guarantee what made it
> through to the device or what will in future make it through to the
> device.

I agree, there is no guarantee here once things have gone wrong, and
the concerns above are reasonable.  However, in the real world, I2C
transactions do sometimes fail for various reasons.  The I2C (and
other bus) APIs have ways of reporting up their errors so callers can
take appropriate action.  This codec driver can run on all kinds of
hardware that can experience transient I2C errors, thus it sounds like
a reasonable idea to have the driver do some error checking on the
APIs it calls and take whatever action it can.  Just ignoring the
errors and proceeding like nothing is wrong is one option, but we can
probably do a little better by at least checking for errors, abort the
current operation, and pass up errors to higher layers when an i2c
transaction failure is detected.  If nothing else, this would enable
higher policy layers to take appropriate corrective action - for
example, if there is an i2c error when configuring a codec, it seems
advisable to report this up so that a machine driver would know to
abort and not turn on downstream amplifiers [I am assuming here that
something like this would happen, I don't know if the sound stack
really works this way].

Once the default "check, abort and report" error checking is in place,
we could perhaps think about actions that the driver could take to
recover from various failures, such as resetting the device or
unwinding previous transactions before aborting, or retrying  but
those are all policy, and this patch is more mechanism that enables
policy.

As for this patch itself, I would recommend using
snd_soc_component_read rather than snd_soc_component_read32() which is
fundamentally broken and afaict should be removed, since there is no
way to distinguish between its error return "(u32)-1" and the valid
register value 0x.  (Edit: I notice that you did this in v2,
so please ignore, but still replying here since this seems to be where
the active discussion is).

-Dan


Re: [PATCH 2/2] ASoC: DA7219: Implement error check on reg read and write

2018-12-05 Thread Daniel Kurtz
On Wed, Dec 5, 2018 at 4:28 AM Mark Brown  wrote:
>
> On Wed, Dec 05, 2018 at 10:21:04AM +, Adam Thomson wrote:
>
> > If the previous I2C access failed, how can we be sure that the write back 
> > to HW
> > of 0xFF even succeeds? More importantly these error returns won't 
> > necessarily
> > stop subsequent calls to controls within the Codec I believe, so you could 
> > still
> > see unwanted writes to HW via I2C, if I2C is sporadically operational. 
> > Again I
> > don't see this update resolving that. The key thing is to resolve why even 
> > just
> > one I2C transaction fails.
>
> Right, it's just not clear what we can constructively do if the I2C bus
> falls to bits other than log things and the I2C controllers will
> generally do that themselves.  There's no guarantee what made it
> through to the device or what will in future make it through to the
> device.

I agree, there is no guarantee here once things have gone wrong, and
the concerns above are reasonable.  However, in the real world, I2C
transactions do sometimes fail for various reasons.  The I2C (and
other bus) APIs have ways of reporting up their errors so callers can
take appropriate action.  This codec driver can run on all kinds of
hardware that can experience transient I2C errors, thus it sounds like
a reasonable idea to have the driver do some error checking on the
APIs it calls and take whatever action it can.  Just ignoring the
errors and proceeding like nothing is wrong is one option, but we can
probably do a little better by at least checking for errors, abort the
current operation, and pass up errors to higher layers when an i2c
transaction failure is detected.  If nothing else, this would enable
higher policy layers to take appropriate corrective action - for
example, if there is an i2c error when configuring a codec, it seems
advisable to report this up so that a machine driver would know to
abort and not turn on downstream amplifiers [I am assuming here that
something like this would happen, I don't know if the sound stack
really works this way].

Once the default "check, abort and report" error checking is in place,
we could perhaps think about actions that the driver could take to
recover from various failures, such as resetting the device or
unwinding previous transactions before aborting, or retrying  but
those are all policy, and this patch is more mechanism that enables
policy.

As for this patch itself, I would recommend using
snd_soc_component_read rather than snd_soc_component_read32() which is
fundamentally broken and afaict should be removed, since there is no
way to distinguish between its error return "(u32)-1" and the valid
register value 0x.  (Edit: I notice that you did this in v2,
so please ignore, but still replying here since this seems to be where
the active discussion is).

-Dan


Re: [PATCH] ASoC: AMD: Fix race condition between register access

2018-10-29 Thread Daniel Kurtz
Hi Akshu,


On Mon, Oct 29, 2018 at 1:39 AM Agrawal, Akshu  wrote:
>
> During simultaneous running of playback and capture, we
> got hit by incorrect value write on common register. This was due
> to race condition between 2 streams.
> Fixing this by locking the common register access.

Nice catch!  It looks looks like one of the operations you are trying
to make atomic is that two step Addr + Data register update.
If so, then I recommend refactoring a bit, and just doing that locked
2-step-access in its own helper function, like this:

  static void acp_reg_write_srbm_targ(void __iomem *acp_mmio, u32
addr, u32 data)
  {
unsigned long flags;

spin_lock_irqsave(, flags);
acp_reg_write(addr, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
acp_reg_write(data, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
spin_unlock_irqrestore(, flags);
  }

And similarly, you can add 2 more locking helpers, one for modifying
the imr/ch and another for mmACP_I2S_16BIT_RESOLUTION_EN.

>
> Signed-off-by: Akshu Agrawal 
> ---
>  sound/soc/amd/acp-pcm-dma.c | 29 +
>  1 file changed, 29 insertions(+)
>
> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 0ac4b5b..993a7db 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -121,6 +121,9 @@
> .periods_max = CAPTURE_MAX_NUM_PERIODS,
>  };
>
> +/* Lock to protect access to registers */
> +static DEFINE_SPINLOCK(lock);
> +
>  static u32 acp_reg_read(void __iomem *acp_mmio, u32 reg)
>  {
> return readl(acp_mmio + (reg * 4));
> @@ -168,9 +171,12 @@ static void config_dma_descriptor_in_sram(void __iomem 
> *acp_mmio,
>   acp_dma_dscr_transfer_t *descr_info)
>  {
> u32 sram_offset;
> +   unsigned long flags;
>
> sram_offset = (descr_idx * sizeof(acp_dma_dscr_transfer_t));
>
> +   spin_lock_irqsave(, flags);
> +
> /* program the source base address. */
> acp_reg_write(sram_offset, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
> acp_reg_write(descr_info->src,  acp_mmio, mmACP_SRBM_Targ_Idx_Data);
> @@ -181,6 +187,8 @@ static void config_dma_descriptor_in_sram(void __iomem 
> *acp_mmio,
> /* program the number of bytes to be transferred for this descriptor. 
> */
> acp_reg_write(sram_offset + 8,  acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
> acp_reg_write(descr_info->xfer_val, acp_mmio, 
> mmACP_SRBM_Targ_Idx_Data);
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
> @@ -309,8 +317,12 @@ static void acp_pte_config(void __iomem *acp_mmio, 
> struct page *pg,
> u32 low;
> u32 high;
> u32 offset;
> +   unsigned long flags;
>
> offset  = ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET + (pte_offset * 8);
> +
> +   spin_lock_irqsave(, flags);
> +
> for (page_idx = 0; page_idx < (num_of_pages); page_idx++) {
> /* Load the low address of page int ACP SRAM through SRBM */
> acp_reg_write((offset + (page_idx * 8)),
> @@ -333,6 +345,8 @@ static void acp_pte_config(void __iomem *acp_mmio, struct 
> page *pg,
> /* Move to next physically contiguos page */
> pg++;
> }
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void config_acp_dma(void __iomem *acp_mmio,
> @@ -367,6 +381,7 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
>u16 cap_channel)
>  {
> u32 val, ch_reg, imr_reg, res_reg;
> +   unsigned long flags;
>
> switch (cap_channel) {
> case CAP_CHANNEL1:
> @@ -381,6 +396,8 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
> imr_reg = mmACP_I2SMICSP_IMR0;
> break;
> }
> +   spin_lock_irqsave(, flags);
> +
> val = acp_reg_read(acp_mmio,
>mmACP_I2S_16BIT_RESOLUTION_EN);
> if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) {
> @@ -393,12 +410,15 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
> val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
> acp_reg_write(val, acp_mmio, imr_reg);
> acp_reg_write(0x1, acp_mmio, ch_reg);
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void acp_dma_cap_channel_disable(void __iomem *acp_mmio,
> u16 cap_channel)
>  {
> u32 val, ch_reg, imr_reg;
> +   unsigned long flags;
>
> switch (cap_channel) {
> case CAP_CHANNEL1:
> @@ -411,11 +431,15 @@ static void acp_dma_cap_channel_disable(void __iomem 
> *acp_mmio,
> ch_reg = mmACP_I2SMICSP_RER0;
> break;
> }
> +   spin_lock_irqsave(, flags);
> +
> val = acp_reg_read(acp_mmio, imr_reg);
> val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
> val |= 

Re: [PATCH] ASoC: AMD: Fix race condition between register access

2018-10-29 Thread Daniel Kurtz
Hi Akshu,


On Mon, Oct 29, 2018 at 1:39 AM Agrawal, Akshu  wrote:
>
> During simultaneous running of playback and capture, we
> got hit by incorrect value write on common register. This was due
> to race condition between 2 streams.
> Fixing this by locking the common register access.

Nice catch!  It looks looks like one of the operations you are trying
to make atomic is that two step Addr + Data register update.
If so, then I recommend refactoring a bit, and just doing that locked
2-step-access in its own helper function, like this:

  static void acp_reg_write_srbm_targ(void __iomem *acp_mmio, u32
addr, u32 data)
  {
unsigned long flags;

spin_lock_irqsave(, flags);
acp_reg_write(addr, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
acp_reg_write(data, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
spin_unlock_irqrestore(, flags);
  }

And similarly, you can add 2 more locking helpers, one for modifying
the imr/ch and another for mmACP_I2S_16BIT_RESOLUTION_EN.

>
> Signed-off-by: Akshu Agrawal 
> ---
>  sound/soc/amd/acp-pcm-dma.c | 29 +
>  1 file changed, 29 insertions(+)
>
> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 0ac4b5b..993a7db 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -121,6 +121,9 @@
> .periods_max = CAPTURE_MAX_NUM_PERIODS,
>  };
>
> +/* Lock to protect access to registers */
> +static DEFINE_SPINLOCK(lock);
> +
>  static u32 acp_reg_read(void __iomem *acp_mmio, u32 reg)
>  {
> return readl(acp_mmio + (reg * 4));
> @@ -168,9 +171,12 @@ static void config_dma_descriptor_in_sram(void __iomem 
> *acp_mmio,
>   acp_dma_dscr_transfer_t *descr_info)
>  {
> u32 sram_offset;
> +   unsigned long flags;
>
> sram_offset = (descr_idx * sizeof(acp_dma_dscr_transfer_t));
>
> +   spin_lock_irqsave(, flags);
> +
> /* program the source base address. */
> acp_reg_write(sram_offset, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
> acp_reg_write(descr_info->src,  acp_mmio, mmACP_SRBM_Targ_Idx_Data);
> @@ -181,6 +187,8 @@ static void config_dma_descriptor_in_sram(void __iomem 
> *acp_mmio,
> /* program the number of bytes to be transferred for this descriptor. 
> */
> acp_reg_write(sram_offset + 8,  acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
> acp_reg_write(descr_info->xfer_val, acp_mmio, 
> mmACP_SRBM_Targ_Idx_Data);
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
> @@ -309,8 +317,12 @@ static void acp_pte_config(void __iomem *acp_mmio, 
> struct page *pg,
> u32 low;
> u32 high;
> u32 offset;
> +   unsigned long flags;
>
> offset  = ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET + (pte_offset * 8);
> +
> +   spin_lock_irqsave(, flags);
> +
> for (page_idx = 0; page_idx < (num_of_pages); page_idx++) {
> /* Load the low address of page int ACP SRAM through SRBM */
> acp_reg_write((offset + (page_idx * 8)),
> @@ -333,6 +345,8 @@ static void acp_pte_config(void __iomem *acp_mmio, struct 
> page *pg,
> /* Move to next physically contiguos page */
> pg++;
> }
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void config_acp_dma(void __iomem *acp_mmio,
> @@ -367,6 +381,7 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
>u16 cap_channel)
>  {
> u32 val, ch_reg, imr_reg, res_reg;
> +   unsigned long flags;
>
> switch (cap_channel) {
> case CAP_CHANNEL1:
> @@ -381,6 +396,8 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
> imr_reg = mmACP_I2SMICSP_IMR0;
> break;
> }
> +   spin_lock_irqsave(, flags);
> +
> val = acp_reg_read(acp_mmio,
>mmACP_I2S_16BIT_RESOLUTION_EN);
> if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) {
> @@ -393,12 +410,15 @@ static void acp_dma_cap_channel_enable(void __iomem 
> *acp_mmio,
> val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
> acp_reg_write(val, acp_mmio, imr_reg);
> acp_reg_write(0x1, acp_mmio, ch_reg);
> +
> +   spin_unlock_irqrestore(, flags);
>  }
>
>  static void acp_dma_cap_channel_disable(void __iomem *acp_mmio,
> u16 cap_channel)
>  {
> u32 val, ch_reg, imr_reg;
> +   unsigned long flags;
>
> switch (cap_channel) {
> case CAP_CHANNEL1:
> @@ -411,11 +431,15 @@ static void acp_dma_cap_channel_disable(void __iomem 
> *acp_mmio,
> ch_reg = mmACP_I2SMICSP_RER0;
> break;
> }
> +   spin_lock_irqsave(, flags);
> +
> val = acp_reg_read(acp_mmio, imr_reg);
> val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
> val |= 

[PATCH] pinctrl/amd: poll InterruptEnable bits in amd_gpio_irq_set_type

2018-09-22 Thread Daniel Kurtz
>From the AMD BKDG, if WAKE_INT_MASTER_REG.MaskStsEn is set, a software
write to the debounce registers of *any* gpio will block wake/interrupt
status generation for *all* gpios for a length of time that depends on
WAKE_INT_MASTER_REG.MaskStsLength[11:0].  During this period the Interrupt
Delivery bit (INTERRUPT_ENABLE) will read as 0.

In commit 4c1de0414a1340 ("pinctrl/amd: poll InterruptEnable bits in
enable_irq") we tried to fix this same "gpio Interrupts are blocked
immediately after writing debounce registers" problem, but incorrectly
assumed it only affected the gpio whose debounce was being configured
and not ALL gpios.

To solve this for all gpios, we move the polling loop from
amd_gpio_irq_enable() to amd_gpio_irq_set_type(), while holding the gpio
spinlock.  This ensures that another gpio operation (e.g.
amd_gpio_irq_unmask()) can read a temporarily disabled IRQ and
incorrectly disable it while trying to modify some other register bits.

Fixes: 4c1de0414a1340 pinctrl/amd: poll InterruptEnable bits in enable_irq

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index b7788140641ee2..67718b0f978d34 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
unsigned long flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-   u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
 
raw_spin_lock_irqsave(_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-   /*
-* When debounce logic is enabled it takes ~900 us before interrupts
-* can be enabled.  During this "debounce warm up" period the
-* "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
-* reads back as 1, signaling that interrupts are now enabled.
-*/
-   while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
-   continue;
raw_spin_unlock_irqrestore(_dev->lock, flags);
 }
 
@@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
 static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
int ret = 0;
-   u32 pin_reg;
+   u32 pin_reg, pin_reg_irq_en, mask;
unsigned long flags, irq_flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
@@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, 
unsigned int type)
}
 
pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
+   /*
+* If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the
+* debounce registers of any GPIO will block wake/interrupt status
+* generation for *all* GPIOs for a lenght of time that depends on
+* WAKE_INT_MASTER_REG.MaskStsLength[11:0].  During this period the
+* INTERRUPT_ENABLE bit will read as 0.
+*
+* We temporarily enable irq for the GPIO whose configuration is
+* changing, and then wait for it to read back as 1 to know when
+* debounce has settled and then disable the irq again.
+* We do this polling with the spinlock held to ensure other GPIO
+* access routines do not read an incorrect value for the irq enable
+* bit of other GPIOs.  We keep the GPIO masked while polling to avoid
+* spurious irqs, and disable the irq again after polling.
+*/
+   mask = BIT(INTERRUPT_ENABLE_OFF);
+   pin_reg_irq_en = pin_reg;
+   pin_reg_irq_en |= mask;
+   pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
+   writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
+   while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
+   continue;
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
raw_spin_unlock_irqrestore(_dev->lock, flags);
 
-- 
2.19.0.444.g18242da7ef-goog



[PATCH] pinctrl/amd: poll InterruptEnable bits in amd_gpio_irq_set_type

2018-09-22 Thread Daniel Kurtz
>From the AMD BKDG, if WAKE_INT_MASTER_REG.MaskStsEn is set, a software
write to the debounce registers of *any* gpio will block wake/interrupt
status generation for *all* gpios for a length of time that depends on
WAKE_INT_MASTER_REG.MaskStsLength[11:0].  During this period the Interrupt
Delivery bit (INTERRUPT_ENABLE) will read as 0.

In commit 4c1de0414a1340 ("pinctrl/amd: poll InterruptEnable bits in
enable_irq") we tried to fix this same "gpio Interrupts are blocked
immediately after writing debounce registers" problem, but incorrectly
assumed it only affected the gpio whose debounce was being configured
and not ALL gpios.

To solve this for all gpios, we move the polling loop from
amd_gpio_irq_enable() to amd_gpio_irq_set_type(), while holding the gpio
spinlock.  This ensures that another gpio operation (e.g.
amd_gpio_irq_unmask()) can read a temporarily disabled IRQ and
incorrectly disable it while trying to modify some other register bits.

Fixes: 4c1de0414a1340 pinctrl/amd: poll InterruptEnable bits in enable_irq

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 33 +++--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index b7788140641ee2..67718b0f978d34 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
unsigned long flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-   u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
 
raw_spin_lock_irqsave(_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-   /*
-* When debounce logic is enabled it takes ~900 us before interrupts
-* can be enabled.  During this "debounce warm up" period the
-* "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
-* reads back as 1, signaling that interrupts are now enabled.
-*/
-   while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
-   continue;
raw_spin_unlock_irqrestore(_dev->lock, flags);
 }
 
@@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
 static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
int ret = 0;
-   u32 pin_reg;
+   u32 pin_reg, pin_reg_irq_en, mask;
unsigned long flags, irq_flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
@@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, 
unsigned int type)
}
 
pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
+   /*
+* If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the
+* debounce registers of any GPIO will block wake/interrupt status
+* generation for *all* GPIOs for a lenght of time that depends on
+* WAKE_INT_MASTER_REG.MaskStsLength[11:0].  During this period the
+* INTERRUPT_ENABLE bit will read as 0.
+*
+* We temporarily enable irq for the GPIO whose configuration is
+* changing, and then wait for it to read back as 1 to know when
+* debounce has settled and then disable the irq again.
+* We do this polling with the spinlock held to ensure other GPIO
+* access routines do not read an incorrect value for the irq enable
+* bit of other GPIOs.  We keep the GPIO masked while polling to avoid
+* spurious irqs, and disable the irq again after polling.
+*/
+   mask = BIT(INTERRUPT_ENABLE_OFF);
+   pin_reg_irq_en = pin_reg;
+   pin_reg_irq_en |= mask;
+   pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
+   writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
+   while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
+   continue;
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
raw_spin_unlock_irqrestore(_dev->lock, flags);
 
-- 
2.19.0.444.g18242da7ef-goog



Re: [PATCH] ASoC: AMD: Change MCLK to 48Mhz

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 1:00 AM Akshu Agrawal  wrote:
>
> 25Mhz MCLK which was earlier used was of spread type.
> Thus, we were not getting accurate rate. The 48Mhz system
> clk is of non-spread type and we are changing to it to get
> accurate rate.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  sound/soc/amd/acp-da7219-max98357a.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
> b/sound/soc/amd/acp-da7219-max98357a.c
> index cf2f648..55d7f61 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -42,7 +42,7 @@
>  #include "../codecs/da7219.h"
>  #include "../codecs/da7219-aad.h"
>
> -#define CZ_PLAT_CLK 2500
> +#define CZ_PLAT_CLK 4800
>  #define DUAL_CHANNEL   2
>
>  static struct snd_soc_jack cz_jack;
> --
> 1.9.1
>


Re: [PATCH] ASoC: AMD: Change MCLK to 48Mhz

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 1:00 AM Akshu Agrawal  wrote:
>
> 25Mhz MCLK which was earlier used was of spread type.
> Thus, we were not getting accurate rate. The 48Mhz system
> clk is of non-spread type and we are changing to it to get
> accurate rate.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  sound/soc/amd/acp-da7219-max98357a.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
> b/sound/soc/amd/acp-da7219-max98357a.c
> index cf2f648..55d7f61 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -42,7 +42,7 @@
>  #include "../codecs/da7219.h"
>  #include "../codecs/da7219-aad.h"
>
> -#define CZ_PLAT_CLK 2500
> +#define CZ_PLAT_CLK 4800
>  #define DUAL_CHANNEL   2
>
>  static struct snd_soc_jack cz_jack;
> --
> 1.9.1
>


Re: [PATCH] ASoC: AMD: Set constraints for DMIC and MAX98357a codec

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 12:55 AM Akshu Agrawal  wrote:
>
> We support dual channel, 48Khz. This constraint was set only for
> da7219. It is being extended to DMIC and MAX98357a.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  sound/soc/amd/acp-da7219-max98357a.c | 33 +
>  1 file changed, 33 insertions(+)
>
> diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
> b/sound/soc/amd/acp-da7219-max98357a.c
> index 066d5489..cf2f648 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -162,10 +162,21 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
> *substream)
>
>  static int cz_max_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_BT_INSTANCE;
> return da7219_clk_enable(substream);
>  }
> @@ -177,20 +188,42 @@ static void cz_max_shutdown(struct snd_pcm_substream 
> *substream)
>
>  static int cz_dmic0_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_BT_INSTANCE;
> return da7219_clk_enable(substream);
>  }
>
>  static int cz_dmic1_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_SP_INSTANCE;
> machine->capture_channel = CAP_CHANNEL0;
> return da7219_clk_enable(substream);
> --
> 1.9.1
>


Re: [PATCH] clk: x86: Set default parent to 48Mhz

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 12:53 AM Akshu Agrawal  wrote:
>
> System clk provided in ST soc can be set to:
> 48Mhz, non-spread
> 25Mhz, spread
> To get accurate rate, we need it to set it at non-spread
> option which is 48Mhz.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  drivers/clk/x86/clk-st.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
> index fb62f39..3a0996f 100644
> --- a/drivers/clk/x86/clk-st.c
> +++ b/drivers/clk/x86/clk-st.c
> @@ -46,7 +46,7 @@ static int st_clk_probe(struct platform_device *pdev)
> clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
> 0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
>
> -   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
> +   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
>
> hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", 
> "oscout1_mux",
> 0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
> --
> 1.9.1
>


Re: [PATCH] ASoC: AMD: Set constraints for DMIC and MAX98357a codec

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 12:55 AM Akshu Agrawal  wrote:
>
> We support dual channel, 48Khz. This constraint was set only for
> da7219. It is being extended to DMIC and MAX98357a.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  sound/soc/amd/acp-da7219-max98357a.c | 33 +
>  1 file changed, 33 insertions(+)
>
> diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
> b/sound/soc/amd/acp-da7219-max98357a.c
> index 066d5489..cf2f648 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -162,10 +162,21 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
> *substream)
>
>  static int cz_max_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_BT_INSTANCE;
> return da7219_clk_enable(substream);
>  }
> @@ -177,20 +188,42 @@ static void cz_max_shutdown(struct snd_pcm_substream 
> *substream)
>
>  static int cz_dmic0_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_BT_INSTANCE;
> return da7219_clk_enable(substream);
>  }
>
>  static int cz_dmic1_startup(struct snd_pcm_substream *substream)
>  {
> +   struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_soc_pcm_runtime *rtd = substream->private_data;
> struct snd_soc_card *card = rtd->card;
> struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
>
> +   /*
> +* On this platform for PCM device we support stereo
> +*/
> +
> +   runtime->hw.channels_max = DUAL_CHANNEL;
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +  _channels);
> +   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +  _rates);
> +
> machine->i2s_instance = I2S_SP_INSTANCE;
> machine->capture_channel = CAP_CHANNEL0;
> return da7219_clk_enable(substream);
> --
> 1.9.1
>


Re: [PATCH] clk: x86: Set default parent to 48Mhz

2018-08-27 Thread Daniel Kurtz
On Tue, Aug 21, 2018 at 12:53 AM Akshu Agrawal  wrote:
>
> System clk provided in ST soc can be set to:
> 48Mhz, non-spread
> 25Mhz, spread
> To get accurate rate, we need it to set it at non-spread
> option which is 48Mhz.
>
> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
>  drivers/clk/x86/clk-st.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
> index fb62f39..3a0996f 100644
> --- a/drivers/clk/x86/clk-st.c
> +++ b/drivers/clk/x86/clk-st.c
> @@ -46,7 +46,7 @@ static int st_clk_probe(struct platform_device *pdev)
> clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
> 0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
>
> -   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
> +   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
>
> hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", 
> "oscout1_mux",
> 0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
> --
> 1.9.1
>


[PATCH v2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-08-22 Thread Daniel Kurtz
Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
changed to the clearing of interrupt status bits to a RMW in a critical
section.  This works, but is a bit overkill.

The relevant interrupt/wake status bits are in the Most Significant Byte
of a 32-bit word.  These two are the only write-able bits in this byte.

Therefore, it should be safe to just write these bits back as a byte
access without any additional locking.

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 41ccc759b8b886..7698bd9f6b687c 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -558,15 +558,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
 
-   /* Clear interrupt.
-* We must read the pin register again, in case the
+   /*
+* Write 1 to clear the irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.  This
+* avoids modifying the lower 24-bits, in case their
 * value was changed while executing
 * generic_handle_irq() above.
 */
-   raw_spin_lock_irqsave(_dev->lock, flags);
-   regval = readl(regs + i);
-   writel(regval, regs + i);
-   raw_spin_unlock_irqrestore(_dev->lock, flags);
+   writeb((regval >> 24), (u8 *)(regs + i) + 3);
ret = IRQ_HANDLED;
}
}
-- 
2.18.0.1017.ga543ac7ca45-goog



[PATCH v2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-08-22 Thread Daniel Kurtz
Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
changed to the clearing of interrupt status bits to a RMW in a critical
section.  This works, but is a bit overkill.

The relevant interrupt/wake status bits are in the Most Significant Byte
of a 32-bit word.  These two are the only write-able bits in this byte.

Therefore, it should be safe to just write these bits back as a byte
access without any additional locking.

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 41ccc759b8b886..7698bd9f6b687c 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -558,15 +558,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
 
-   /* Clear interrupt.
-* We must read the pin register again, in case the
+   /*
+* Write 1 to clear the irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.  This
+* avoids modifying the lower 24-bits, in case their
 * value was changed while executing
 * generic_handle_irq() above.
 */
-   raw_spin_lock_irqsave(_dev->lock, flags);
-   regval = readl(regs + i);
-   writel(regval, regs + i);
-   raw_spin_unlock_irqrestore(_dev->lock, flags);
+   writeb((regval >> 24), (u8 *)(regs + i) + 3);
ret = IRQ_HANDLED;
}
}
-- 
2.18.0.1017.ga543ac7ca45-goog



[PATCH v2] ASoC: da7219: Allow pdata to specify a VDDIO

2018-07-22 Thread Daniel Kurtz
Some systems do not have software controllable regulators driving the
DA7219's supplies, nor can they use device tree to create "always-on fixed
regulators" to easily pretend like they do.

On these systems the call to devm_regulator_bulk_get() just creates
a set of dummy registers.  Calling regulator_get_voltage() on a dummy
regulator just returns -EINVAL, in which case the DA7219 is always set up
to use the default VDDIO voltage range of 2.5-3.6V.

Provide a new device property to let such systems specify a different
VDDIO if needed (e.g., 1.8V).

Signed-off-by: Daniel Kurtz 
---
Changes for v2:
 - fix to use device_property_read_u32()

 include/sound/da7219.h|  2 ++
 sound/soc/codecs/da7219.c | 19 +--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 1bfcb16f2d10ab..16ab125ad4adbf 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -38,6 +38,8 @@ struct da7219_pdata {
 
const char *dai_clks_name;
 
+   u32 vddio;
+
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 980a6a8bf56d38..9893920b26f41f 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1634,6 +1634,9 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct 
snd_soc_component *compone
else
pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF;
 
+   if (device_property_read_u32(dev, "dlg,vddio", _val32) >= 0)
+   pdata->vddio = of_val32;
+
return pdata;
 }
 
@@ -1717,8 +1720,12 @@ static int da7219_handle_supplies(struct 
snd_soc_component *component)
/* Determine VDDIO voltage provided */
vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer;
ret = regulator_get_voltage(vddio);
+   /* If regulator_get_voltage() fails, try to use vddio from pdata. */
+   if (ret < 0 && da7219->pdata)
+   ret = da7219->pdata->vddio;
if (ret < 120)
-   dev_warn(component->dev, "Invalid VDDIO voltage\n");
+   dev_warn(component->dev, "Invalid VDDIO voltage: %d mV\n",
+ret);
else if (ret < 280)
io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V;
 
@@ -1872,6 +1879,11 @@ static int da7219_probe(struct snd_soc_component 
*component)
mutex_init(>ctrl_lock);
mutex_init(>pll_lock);
 
+   /* Handle DT/ACPI/Platform data */
+   da7219->pdata = dev_get_platdata(component->dev);
+   if (!da7219->pdata)
+   da7219->pdata = da7219_fw_to_pdata(component);
+
/* Regulator configuration */
ret = da7219_handle_supplies(component);
if (ret)
@@ -1897,11 +1909,6 @@ static int da7219_probe(struct snd_soc_component 
*component)
break;
}
 
-   /* Handle DT/ACPI/Platform data */
-   da7219->pdata = dev_get_platdata(component->dev);
-   if (!da7219->pdata)
-   da7219->pdata = da7219_fw_to_pdata(component);
-
da7219_handle_pdata(component);
 
/* Check if MCLK provided */
-- 
2.18.0.233.g985f88cf7e-goog



[PATCH v2] ASoC: da7219: Allow pdata to specify a VDDIO

2018-07-22 Thread Daniel Kurtz
Some systems do not have software controllable regulators driving the
DA7219's supplies, nor can they use device tree to create "always-on fixed
regulators" to easily pretend like they do.

On these systems the call to devm_regulator_bulk_get() just creates
a set of dummy registers.  Calling regulator_get_voltage() on a dummy
regulator just returns -EINVAL, in which case the DA7219 is always set up
to use the default VDDIO voltage range of 2.5-3.6V.

Provide a new device property to let such systems specify a different
VDDIO if needed (e.g., 1.8V).

Signed-off-by: Daniel Kurtz 
---
Changes for v2:
 - fix to use device_property_read_u32()

 include/sound/da7219.h|  2 ++
 sound/soc/codecs/da7219.c | 19 +--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 1bfcb16f2d10ab..16ab125ad4adbf 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -38,6 +38,8 @@ struct da7219_pdata {
 
const char *dai_clks_name;
 
+   u32 vddio;
+
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 980a6a8bf56d38..9893920b26f41f 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1634,6 +1634,9 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct 
snd_soc_component *compone
else
pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF;
 
+   if (device_property_read_u32(dev, "dlg,vddio", _val32) >= 0)
+   pdata->vddio = of_val32;
+
return pdata;
 }
 
@@ -1717,8 +1720,12 @@ static int da7219_handle_supplies(struct 
snd_soc_component *component)
/* Determine VDDIO voltage provided */
vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer;
ret = regulator_get_voltage(vddio);
+   /* If regulator_get_voltage() fails, try to use vddio from pdata. */
+   if (ret < 0 && da7219->pdata)
+   ret = da7219->pdata->vddio;
if (ret < 120)
-   dev_warn(component->dev, "Invalid VDDIO voltage\n");
+   dev_warn(component->dev, "Invalid VDDIO voltage: %d mV\n",
+ret);
else if (ret < 280)
io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V;
 
@@ -1872,6 +1879,11 @@ static int da7219_probe(struct snd_soc_component 
*component)
mutex_init(>ctrl_lock);
mutex_init(>pll_lock);
 
+   /* Handle DT/ACPI/Platform data */
+   da7219->pdata = dev_get_platdata(component->dev);
+   if (!da7219->pdata)
+   da7219->pdata = da7219_fw_to_pdata(component);
+
/* Regulator configuration */
ret = da7219_handle_supplies(component);
if (ret)
@@ -1897,11 +1909,6 @@ static int da7219_probe(struct snd_soc_component 
*component)
break;
}
 
-   /* Handle DT/ACPI/Platform data */
-   da7219->pdata = dev_get_platdata(component->dev);
-   if (!da7219->pdata)
-   da7219->pdata = da7219_fw_to_pdata(component);
-
da7219_handle_pdata(component);
 
/* Check if MCLK provided */
-- 
2.18.0.233.g985f88cf7e-goog



[PATCH] ASoC: da7219: Allow pdata to specify a VDDIO

2018-07-20 Thread Daniel Kurtz
Some systems do not have software controllable regulators driving the
DA7219's supplies, nor can they use device tree to create "always-on fixed
regulators" to easily pretend like they do.

On these systems the call to devm_regulator_bulk_get() just creates
a set of dummy registers.  Calling regulator_get_voltage() on a dummy
regulator just returns -EINVAL, in which case the DA7219 is always set up
to use the default VDDIO voltage range of 2.5-3.6V.

Provide a new device property to let such systems specify a different
VDDIO if needed (e.g., 1.8V).

Signed-off-by: Daniel Kurtz 
---

This patch tries to solve the same problem as in the following patches,
but does so in a way that doesn't require registering fixed regulators in
the audio machine-driver:
  https://patchwork.kernel.org/patch/10531097 & 10531099
  https://patchwork.kernel.org/patch/10536023/

 include/sound/da7219.h|  2 ++
 sound/soc/codecs/da7219.c | 19 +--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 1bfcb16f2d10ab..16ab125ad4adbf 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -38,6 +38,8 @@ struct da7219_pdata {
 
const char *dai_clks_name;
 
+   u32 vddio;
+
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 980a6a8bf56d38..d8f202c57f958d 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1634,6 +1634,9 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct 
snd_soc_component *compone
else
pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF;
 
+   if (!device_property_read_string(dev, "dlg,vddio", _val32))
+   pdata->vddio = of_val32;
+
return pdata;
 }
 
@@ -1717,8 +1720,12 @@ static int da7219_handle_supplies(struct 
snd_soc_component *component)
/* Determine VDDIO voltage provided */
vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer;
ret = regulator_get_voltage(vddio);
+   /* If regulator_get_voltage() fails, try to use vddio from pdata. */
+   if (ret < 0 && da7219->pdata)
+   ret = da7219->pdata->vddio;
if (ret < 120)
-   dev_warn(component->dev, "Invalid VDDIO voltage\n");
+   dev_warn(component->dev, "Invalid VDDIO voltage: %d mV\n",
+ret);
else if (ret < 280)
io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V;
 
@@ -1872,6 +1879,11 @@ static int da7219_probe(struct snd_soc_component 
*component)
mutex_init(>ctrl_lock);
mutex_init(>pll_lock);
 
+   /* Handle DT/ACPI/Platform data */
+   da7219->pdata = dev_get_platdata(component->dev);
+   if (!da7219->pdata)
+   da7219->pdata = da7219_fw_to_pdata(component);
+
/* Regulator configuration */
ret = da7219_handle_supplies(component);
if (ret)
@@ -1897,11 +1909,6 @@ static int da7219_probe(struct snd_soc_component 
*component)
break;
}
 
-   /* Handle DT/ACPI/Platform data */
-   da7219->pdata = dev_get_platdata(component->dev);
-   if (!da7219->pdata)
-   da7219->pdata = da7219_fw_to_pdata(component);
-
da7219_handle_pdata(component);
 
/* Check if MCLK provided */
-- 
2.18.0.233.g985f88cf7e-goog



[PATCH] ASoC: da7219: Allow pdata to specify a VDDIO

2018-07-20 Thread Daniel Kurtz
Some systems do not have software controllable regulators driving the
DA7219's supplies, nor can they use device tree to create "always-on fixed
regulators" to easily pretend like they do.

On these systems the call to devm_regulator_bulk_get() just creates
a set of dummy registers.  Calling regulator_get_voltage() on a dummy
regulator just returns -EINVAL, in which case the DA7219 is always set up
to use the default VDDIO voltage range of 2.5-3.6V.

Provide a new device property to let such systems specify a different
VDDIO if needed (e.g., 1.8V).

Signed-off-by: Daniel Kurtz 
---

This patch tries to solve the same problem as in the following patches,
but does so in a way that doesn't require registering fixed regulators in
the audio machine-driver:
  https://patchwork.kernel.org/patch/10531097 & 10531099
  https://patchwork.kernel.org/patch/10536023/

 include/sound/da7219.h|  2 ++
 sound/soc/codecs/da7219.c | 19 +--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 1bfcb16f2d10ab..16ab125ad4adbf 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -38,6 +38,8 @@ struct da7219_pdata {
 
const char *dai_clks_name;
 
+   u32 vddio;
+
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index 980a6a8bf56d38..d8f202c57f958d 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1634,6 +1634,9 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct 
snd_soc_component *compone
else
pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF;
 
+   if (!device_property_read_string(dev, "dlg,vddio", _val32))
+   pdata->vddio = of_val32;
+
return pdata;
 }
 
@@ -1717,8 +1720,12 @@ static int da7219_handle_supplies(struct 
snd_soc_component *component)
/* Determine VDDIO voltage provided */
vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer;
ret = regulator_get_voltage(vddio);
+   /* If regulator_get_voltage() fails, try to use vddio from pdata. */
+   if (ret < 0 && da7219->pdata)
+   ret = da7219->pdata->vddio;
if (ret < 120)
-   dev_warn(component->dev, "Invalid VDDIO voltage\n");
+   dev_warn(component->dev, "Invalid VDDIO voltage: %d mV\n",
+ret);
else if (ret < 280)
io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V;
 
@@ -1872,6 +1879,11 @@ static int da7219_probe(struct snd_soc_component 
*component)
mutex_init(>ctrl_lock);
mutex_init(>pll_lock);
 
+   /* Handle DT/ACPI/Platform data */
+   da7219->pdata = dev_get_platdata(component->dev);
+   if (!da7219->pdata)
+   da7219->pdata = da7219_fw_to_pdata(component);
+
/* Regulator configuration */
ret = da7219_handle_supplies(component);
if (ret)
@@ -1897,11 +1909,6 @@ static int da7219_probe(struct snd_soc_component 
*component)
break;
}
 
-   /* Handle DT/ACPI/Platform data */
-   da7219->pdata = dev_get_platdata(component->dev);
-   if (!da7219->pdata)
-   da7219->pdata = da7219_fw_to_pdata(component);
-
da7219_handle_pdata(component);
 
/* Check if MCLK provided */
-- 
2.18.0.233.g985f88cf7e-goog



Re: [PATCH 2/2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-07-20 Thread Daniel Kurtz
Hi Daniel,

On Tue, Jul 17, 2018 at 6:30 AM Daniel Drake  wrote:
>
> On Mon, Jul 16, 2018 at 7:57 PM, Daniel Kurtz  wrote:
> > Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
> > changed to the clearing of interrupt status bits to a RMW in a critical
> > section.  This works, but is a bit overkill.
> >
> > The relevant interrupt/wake status bits are in the Most Significant Byte
> > of a 32-bit word.  These two are the only write-able bits in this byte.
>
> I don't have the hardware to test this any more, and I also don't have
> any docs to double if those are really the only writable bits, but
> looking at the existing driver code it does seem to be the case.
>
> I think you should retain the comment noting that the value of the
> register may have changed since it was read just a few lines above
> (and hence explaining more precisely why we make the special effort
> just to modify the MSB), just in case there is further rework of this
> code in future and we end up walking into the same trap. It was one of
> those issues that took a frustratingly long time to figure out...

Sounds reasonable.  How about:

-   /* Clear interrupt.
-* We must read the pin register again, in case the
-* value was changed while executing
-* generic_handle_irq() above.
+   /*
+* Write-1-to-clear irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.
+* This avoids modifying the lower 24-bits
because they may have
+*  changed while executing generic_handle_irq() above.
 */


>
> Thanks
> Daniel


Re: [PATCH 2/2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-07-20 Thread Daniel Kurtz
Hi Daniel,

On Tue, Jul 17, 2018 at 6:30 AM Daniel Drake  wrote:
>
> On Mon, Jul 16, 2018 at 7:57 PM, Daniel Kurtz  wrote:
> > Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
> > changed to the clearing of interrupt status bits to a RMW in a critical
> > section.  This works, but is a bit overkill.
> >
> > The relevant interrupt/wake status bits are in the Most Significant Byte
> > of a 32-bit word.  These two are the only write-able bits in this byte.
>
> I don't have the hardware to test this any more, and I also don't have
> any docs to double if those are really the only writable bits, but
> looking at the existing driver code it does seem to be the case.
>
> I think you should retain the comment noting that the value of the
> register may have changed since it was read just a few lines above
> (and hence explaining more precisely why we make the special effort
> just to modify the MSB), just in case there is further rework of this
> code in future and we end up walking into the same trap. It was one of
> those issues that took a frustratingly long time to figure out...

Sounds reasonable.  How about:

-   /* Clear interrupt.
-* We must read the pin register again, in case the
-* value was changed while executing
-* generic_handle_irq() above.
+   /*
+* Write-1-to-clear irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.
+* This avoids modifying the lower 24-bits
because they may have
+*  changed while executing generic_handle_irq() above.
 */


>
> Thanks
> Daniel


[PATCH 2/2] ASoC: AMD: Add an always on fixed 1.8V regulator for da7219 VDDIO

2018-07-17 Thread Daniel Kurtz
From: Akshu Agrawal 

DA7219's VDDIO for our platform need to be configured for 1.8V.
Hence we register a fixed 1.8V voltage regulator in the machine driver.

Change-Id: I65fd93e1dd37c3e0d38265b4b1492ea53b93afd4
Signed-off-by: Akshu Agrawal 
Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/Kconfig|  1 +
 sound/soc/amd/acp-da7219-max98357a.c | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf4d1a4c2..58c1dcb4d2550f 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index ccddc6650b9c79..6ea0f42f5b7692 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -32,6 +32,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -278,11 +280,23 @@ static struct snd_soc_card cz_card = {
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00")
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   struct platform_device *reg;
+
+   reg = regulator_register_always_on(0, "fixed-1.8V",
+  acp_da7219_supplies,
+  ARRAY_SIZE(acp_da7219_supplies),
+  180);
+   if (!reg)
+   return -ENOMEM;
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 2/2] ASoC: AMD: Add an always on fixed 1.8V regulator for da7219 VDDIO

2018-07-17 Thread Daniel Kurtz
From: Akshu Agrawal 

DA7219's VDDIO for our platform need to be configured for 1.8V.
Hence we register a fixed 1.8V voltage regulator in the machine driver.

Change-Id: I65fd93e1dd37c3e0d38265b4b1492ea53b93afd4
Signed-off-by: Akshu Agrawal 
Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/Kconfig|  1 +
 sound/soc/amd/acp-da7219-max98357a.c | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf4d1a4c2..58c1dcb4d2550f 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index ccddc6650b9c79..6ea0f42f5b7692 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -32,6 +32,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -278,11 +280,23 @@ static struct snd_soc_card cz_card = {
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00")
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   struct platform_device *reg;
+
+   reg = regulator_register_always_on(0, "fixed-1.8V",
+  acp_da7219_supplies,
+  ARRAY_SIZE(acp_da7219_supplies),
+  180);
+   if (!reg)
+   return -ENOMEM;
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 1/2] regulator: allow drivers in modules to register fixed regulators

2018-07-17 Thread Daniel Kurtz
Sound machine drivers tend to live in modules. Sometimes such a machine
driver needs to register a fixed regulator to provide to a codec.

Export regulator_register_always_on() such that this is possible.

Change-Id: I2906f96df278b5fa65d40d3a777bf6d3d91841d2
Signed-off-by: Daniel Kurtz 
---
 drivers/regulator/fixed-helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
index 777fac6fb4cb0a..f53fbda043f525 100644
--- a/drivers/regulator/fixed-helper.c
+++ b/drivers/regulator/fixed-helper.c
@@ -60,3 +60,4 @@ struct platform_device *regulator_register_always_on(int id, 
const char *name,
 
return >pdev;
 }
+EXPORT_SYMBOL_GPL(regulator_register_always_on);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 1/2] regulator: allow drivers in modules to register fixed regulators

2018-07-17 Thread Daniel Kurtz
Sound machine drivers tend to live in modules. Sometimes such a machine
driver needs to register a fixed regulator to provide to a codec.

Export regulator_register_always_on() such that this is possible.

Change-Id: I2906f96df278b5fa65d40d3a777bf6d3d91841d2
Signed-off-by: Daniel Kurtz 
---
 drivers/regulator/fixed-helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
index 777fac6fb4cb0a..f53fbda043f525 100644
--- a/drivers/regulator/fixed-helper.c
+++ b/drivers/regulator/fixed-helper.c
@@ -60,3 +60,4 @@ struct platform_device *regulator_register_always_on(int id, 
const char *name,
 
return >pdev;
 }
+EXPORT_SYMBOL_GPL(regulator_register_always_on);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH] pinctrl/amd: fix gpio irq level in debugfs

2018-07-16 Thread Daniel Kurtz
According to the AMD BKDG, the GPIO ActiveLevel bits (10:9) map to:
 00 Active High
 01 Active Low
 10 Active on both edges iff LevelTrig (bit 8) == 0
 11 Reserved

The current code has a bug where it interprets 00 => Active Low, and
01 => Active High.

Fix the bug, restrict "Active on both" to just the edge trigger case, and
refactor a bit to make the logic more readable.

Change-Id: Id7775ae4cb61d193fa7fbb83967a8c5a7cdd0de6
Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 14 +++---
 drivers/pinctrl/pinctrl-amd.h |  4 
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 04ae139671c8a8..5df5e8d64c57e7 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -247,16 +247,16 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct 
gpio_chip *gc)
raw_spin_unlock_irqrestore(_dev->lock, flags);
 
if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) {
+   u8 level = (pin_reg >> ACTIVE_LEVEL_OFF) &
+   ACTIVE_LEVEL_MASK;
interrupt_enable = "interrupt is enabled|";
 
-   if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
-   !(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
-   active_level = "Active low|";
-   else if (pin_reg & BIT(ACTIVE_LEVEL_OFF) &&
-!(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
+   if (level == ACTIVE_LEVEL_HIGH)
active_level = "Active high|";
-   else if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
-pin_reg & BIT(ACTIVE_LEVEL_OFF + 1))
+   else if (level == ACTIVE_LEVEL_LOW)
+   active_level = "Active low|";
+   else if (!(pin_reg & BIT(LEVEL_TRIG_OFF)) &&
+level == ACTIVE_LEVEL_BOTH)
active_level = "Active on both|";
else
active_level = "Unknown Active level|";
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index 8fa453a59da5e6..22af7edfdb38e8 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -54,6 +54,10 @@
 #define ACTIVE_LEVEL_MASK  0x3UL
 #define DRV_STRENGTH_SEL_MASK  0x3UL
 
+#define ACTIVE_LEVEL_HIGH  0x0UL
+#define ACTIVE_LEVEL_LOW   0x1UL
+#define ACTIVE_LEVEL_BOTH  0x2UL
+
 #define DB_TYPE_NO_DEBOUNCE   0x0UL
 #define DB_TYPE_PRESERVE_LOW_GLITCH   0x1UL
 #define DB_TYPE_PRESERVE_HIGH_GLITCH  0x2UL
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH] pinctrl/amd: fix gpio irq level in debugfs

2018-07-16 Thread Daniel Kurtz
According to the AMD BKDG, the GPIO ActiveLevel bits (10:9) map to:
 00 Active High
 01 Active Low
 10 Active on both edges iff LevelTrig (bit 8) == 0
 11 Reserved

The current code has a bug where it interprets 00 => Active Low, and
01 => Active High.

Fix the bug, restrict "Active on both" to just the edge trigger case, and
refactor a bit to make the logic more readable.

Change-Id: Id7775ae4cb61d193fa7fbb83967a8c5a7cdd0de6
Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 14 +++---
 drivers/pinctrl/pinctrl-amd.h |  4 
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 04ae139671c8a8..5df5e8d64c57e7 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -247,16 +247,16 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct 
gpio_chip *gc)
raw_spin_unlock_irqrestore(_dev->lock, flags);
 
if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) {
+   u8 level = (pin_reg >> ACTIVE_LEVEL_OFF) &
+   ACTIVE_LEVEL_MASK;
interrupt_enable = "interrupt is enabled|";
 
-   if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
-   !(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
-   active_level = "Active low|";
-   else if (pin_reg & BIT(ACTIVE_LEVEL_OFF) &&
-!(pin_reg & BIT(ACTIVE_LEVEL_OFF + 1)))
+   if (level == ACTIVE_LEVEL_HIGH)
active_level = "Active high|";
-   else if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF)) &&
-pin_reg & BIT(ACTIVE_LEVEL_OFF + 1))
+   else if (level == ACTIVE_LEVEL_LOW)
+   active_level = "Active low|";
+   else if (!(pin_reg & BIT(LEVEL_TRIG_OFF)) &&
+level == ACTIVE_LEVEL_BOTH)
active_level = "Active on both|";
else
active_level = "Unknown Active level|";
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index 8fa453a59da5e6..22af7edfdb38e8 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -54,6 +54,10 @@
 #define ACTIVE_LEVEL_MASK  0x3UL
 #define DRV_STRENGTH_SEL_MASK  0x3UL
 
+#define ACTIVE_LEVEL_HIGH  0x0UL
+#define ACTIVE_LEVEL_LOW   0x1UL
+#define ACTIVE_LEVEL_BOTH  0x2UL
+
 #define DB_TYPE_NO_DEBOUNCE   0x0UL
 #define DB_TYPE_PRESERVE_LOW_GLITCH   0x1UL
 #define DB_TYPE_PRESERVE_HIGH_GLITCH  0x2UL
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 1/2] pinctrl/amd: only handle irq if it is pending and unmasked

2018-07-16 Thread Daniel Kurtz
The AMD pinctrl driver demultiplexes GPIO interrupts and fires off their
individual handlers.

If one of these GPIO irqs is configured as a level interrupt, and its
downstream handler is a threaded ONESHOT interrupt, the GPIO interrupt
source is masked by handle_level_irq() until the eventual return of the
threaded irq handler.  During this time the level GPIO interrupt status
will still report as high until the actual gpio source is cleared - both
in the individual GPIO interrupt status bit (INTERRUPT_STS_OFF) and in
its corresponding "WAKE_INT_STATUS_REG" bit.

Thus, if another GPIO interrupt occurs during this time,
amd_gpio_irq_handler() will see that the (masked-and-not-yet-cleared)
level irq is still pending and incorrectly call its handler again.

To fix this, have amd_gpio_irq_handler() check for both interrupts status
and mask before calling generic_handle_irq().

Note: Is it possible that this bug was the source of the interrupt storm
on Ryzen when using chained interrupts before commit ba714a9c1dea85
("pinctrl/amd: Use regular interrupt instead of chained")?

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 04ae139671c8a8..b91db89eb9247c 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -552,7 +552,8 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
/* Each status bit covers four pins */
for (i = 0; i < 4; i++) {
regval = readl(regs + i);
-   if (!(regval & PIN_IRQ_PENDING))
+   if (!(regval & PIN_IRQ_PENDING) ||
+   !(regval & BIT(INTERRUPT_MASK_OFF)))
continue;
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 2/2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-07-16 Thread Daniel Kurtz
Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
changed to the clearing of interrupt status bits to a RMW in a critical
section.  This works, but is a bit overkill.

The relevant interrupt/wake status bits are in the Most Significant Byte
of a 32-bit word.  These two are the only write-able bits in this byte.

Therefore, it should be safe to just write these bits back as a byte
access without any additional locking.

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index b91db89eb9247c..52efe77ffb9991 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -558,15 +558,11 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
 
-   /* Clear interrupt.
-* We must read the pin register again, in case the
-* value was changed while executing
-* generic_handle_irq() above.
+   /*
+* Write-1-to-clear irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.
 */
-   raw_spin_lock_irqsave(_dev->lock, flags);
-   regval = readl(regs + i);
-   writel(regval, regs + i);
-   raw_spin_unlock_irqrestore(_dev->lock, flags);
+   writeb((regval >> 24), (u8 *)(regs + i) + 3);
ret = IRQ_HANDLED;
}
}
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 2/2] pinctrl/amd: use byte access to clear irq/wake status bits

2018-07-16 Thread Daniel Kurtz
Commit 6afb10267c1692 ("pinctrl/amd: fix masking of GPIO interrupts")
changed to the clearing of interrupt status bits to a RMW in a critical
section.  This works, but is a bit overkill.

The relevant interrupt/wake status bits are in the Most Significant Byte
of a 32-bit word.  These two are the only write-able bits in this byte.

Therefore, it should be safe to just write these bits back as a byte
access without any additional locking.

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index b91db89eb9247c..52efe77ffb9991 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -558,15 +558,11 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
 
-   /* Clear interrupt.
-* We must read the pin register again, in case the
-* value was changed while executing
-* generic_handle_irq() above.
+   /*
+* Write-1-to-clear irq/wake status bits in MSByte.
+* All other bits in this byte are read-only.
 */
-   raw_spin_lock_irqsave(_dev->lock, flags);
-   regval = readl(regs + i);
-   writel(regval, regs + i);
-   raw_spin_unlock_irqrestore(_dev->lock, flags);
+   writeb((regval >> 24), (u8 *)(regs + i) + 3);
ret = IRQ_HANDLED;
}
}
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 1/2] pinctrl/amd: only handle irq if it is pending and unmasked

2018-07-16 Thread Daniel Kurtz
The AMD pinctrl driver demultiplexes GPIO interrupts and fires off their
individual handlers.

If one of these GPIO irqs is configured as a level interrupt, and its
downstream handler is a threaded ONESHOT interrupt, the GPIO interrupt
source is masked by handle_level_irq() until the eventual return of the
threaded irq handler.  During this time the level GPIO interrupt status
will still report as high until the actual gpio source is cleared - both
in the individual GPIO interrupt status bit (INTERRUPT_STS_OFF) and in
its corresponding "WAKE_INT_STATUS_REG" bit.

Thus, if another GPIO interrupt occurs during this time,
amd_gpio_irq_handler() will see that the (masked-and-not-yet-cleared)
level irq is still pending and incorrectly call its handler again.

To fix this, have amd_gpio_irq_handler() check for both interrupts status
and mask before calling generic_handle_irq().

Note: Is it possible that this bug was the source of the interrupt storm
on Ryzen when using chained interrupts before commit ba714a9c1dea85
("pinctrl/amd: Use regular interrupt instead of chained")?

Signed-off-by: Daniel Kurtz 
---
 drivers/pinctrl/pinctrl-amd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 04ae139671c8a8..b91db89eb9247c 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -552,7 +552,8 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void 
*dev_id)
/* Each status bit covers four pins */
for (i = 0; i < 4; i++) {
regval = readl(regs + i);
-   if (!(regval & PIN_IRQ_PENDING))
+   if (!(regval & PIN_IRQ_PENDING) ||
+   !(regval & BIT(INTERRUPT_MASK_OFF)))
continue;
irq = irq_find_mapping(gc->irq.domain, irqnr + i);
generic_handle_irq(irq);
-- 
2.18.0.203.gfac676dfb9-goog



[PATCH 3/6] ASoC: AMD: Always subtract bytescount

2018-07-02 Thread Daniel Kurtz
It is always correct to subtract out the starting bytescount value.  Even
in the case of 2^64 byte rollover (292 Million Years in the future
@ 48000 Hz) the math still works out.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index e6f85f2e5ac2a..224383fef0c3a 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -995,8 +995,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
 
-   if (bytescount > rtd->bytescount)
-   bytescount -= rtd->bytescount;
+   bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
return bytes_to_frames(runtime, pos);
 }
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 3/6] ASoC: AMD: Always subtract bytescount

2018-07-02 Thread Daniel Kurtz
It is always correct to subtract out the starting bytescount value.  Even
in the case of 2^64 byte rollover (292 Million Years in the future
@ 48000 Hz) the math still works out.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index e6f85f2e5ac2a..224383fef0c3a 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -995,8 +995,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
 
-   if (bytescount > rtd->bytescount)
-   bytescount -= rtd->bytescount;
+   bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
return bytes_to_frames(runtime, pos);
 }
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 5/6] ASoC: AMD: Do not generate interrups for every captured sample

2018-07-02 Thread Daniel Kurtz
On capture, audio data is first copied from I2S to ACP memory, and then
from ACP to SYSRAM.  The I2S_TO_ACP_DMA interrupt fires on every sample
transferred from I2S to ACP memory.  That is it fires ~48000 times per
second when capturing @ 48 kHz.  Since we don't do anything on this
interrupt anyway, disable it to save quite a few unnecessary interrupts.
The real "work" (calling snd_pcm_period_elapsed()) is done when transfer
from ACP to SYSRAM is complete.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 15 ---
 1 file changed, 15 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 2a6a6e65e27c3..ab60129f4f266 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -412,10 +412,8 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
switch (ch_num) {
case ACP_TO_I2S_DMA_CH_NUM:
case ACP_TO_SYSRAM_CH_NUM:
-   case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
-   case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
default:
@@ -704,12 +702,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
-   valid_irq = true;
-   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
- acp_mmio, mmACP_EXTERNAL_INTR_STAT);
-   }
-
if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
@@ -718,13 +710,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
-   valid_irq = true;
-   acp_reg_write((intr_flag &
- BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
- acp_mmio, mmACP_EXTERNAL_INTR_STAT);
-   }
-
if (valid_irq)
return IRQ_HANDLED;
else
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 5/6] ASoC: AMD: Do not generate interrups for every captured sample

2018-07-02 Thread Daniel Kurtz
On capture, audio data is first copied from I2S to ACP memory, and then
from ACP to SYSRAM.  The I2S_TO_ACP_DMA interrupt fires on every sample
transferred from I2S to ACP memory.  That is it fires ~48000 times per
second when capturing @ 48 kHz.  Since we don't do anything on this
interrupt anyway, disable it to save quite a few unnecessary interrupts.
The real "work" (calling snd_pcm_period_elapsed()) is done when transfer
from ACP to SYSRAM is complete.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 15 ---
 1 file changed, 15 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 2a6a6e65e27c3..ab60129f4f266 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -412,10 +412,8 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
switch (ch_num) {
case ACP_TO_I2S_DMA_CH_NUM:
case ACP_TO_SYSRAM_CH_NUM:
-   case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
-   case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
default:
@@ -704,12 +702,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
-   valid_irq = true;
-   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
- acp_mmio, mmACP_EXTERNAL_INTR_STAT);
-   }
-
if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
@@ -718,13 +710,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
-   valid_irq = true;
-   acp_reg_write((intr_flag &
- BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
- acp_mmio, mmACP_EXTERNAL_INTR_STAT);
-   }
-
if (valid_irq)
return IRQ_HANDLED;
else
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 1/6] ASoC: AMD: Always stop ch2 first

2018-07-02 Thread Daniel Kurtz
Commit 6b116dfb4633a ("ASoC: AMD: make channel 1 dma as circular") made
both channels circular, so this comment and logic no longer applies.  Always
stop ch2 (the channel closest to the output) before ch1.  This ensures
that the downstream circular DMA channel does not continue to play/capture
repeated samples after the upstream circular DMA channel has already
stopped.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 17 ++---
 1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 3c3d398d0d0b1..4665ae12e74e4 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1067,21 +1067,8 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
-   /* For playback, non circular dma should be stopped first
-* i.e Sysram to acp dma transfer channel(rtd->ch1) should be
-* stopped before stopping cirular dma which is acp sram to i2s
-* fifo dma transfer channel(rtd->ch2). Where as in Capture
-* scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped
-* first before stopping acp sram to sysram which is circular
-* dma(rtd->ch1).
-*/
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   ret =  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
-   } else {
-   acp_dma_stop(rtd->acp_mmio, rtd->ch2);
-   ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   }
+   acp_dma_stop(rtd->acp_mmio, rtd->ch2);
+   ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
rtd->bytescount = 0;
break;
default:
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 1/6] ASoC: AMD: Always stop ch2 first

2018-07-02 Thread Daniel Kurtz
Commit 6b116dfb4633a ("ASoC: AMD: make channel 1 dma as circular") made
both channels circular, so this comment and logic no longer applies.  Always
stop ch2 (the channel closest to the output) before ch1.  This ensures
that the downstream circular DMA channel does not continue to play/capture
repeated samples after the upstream circular DMA channel has already
stopped.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 17 ++---
 1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 3c3d398d0d0b1..4665ae12e74e4 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1067,21 +1067,8 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
-   /* For playback, non circular dma should be stopped first
-* i.e Sysram to acp dma transfer channel(rtd->ch1) should be
-* stopped before stopping cirular dma which is acp sram to i2s
-* fifo dma transfer channel(rtd->ch2). Where as in Capture
-* scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped
-* first before stopping acp sram to sysram which is circular
-* dma(rtd->ch1).
-*/
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   ret =  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
-   } else {
-   acp_dma_stop(rtd->acp_mmio, rtd->ch2);
-   ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   }
+   acp_dma_stop(rtd->acp_mmio, rtd->ch2);
+   ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
rtd->bytescount = 0;
break;
default:
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 2/6] ASoC: AMD: Reset bytescount when starting transaction

2018-07-02 Thread Daniel Kurtz
The pointer() callback gets its value by reading the I2S BYTE_COUNT
register.  This is a 64-bit runnning transaction counter. If a
transaction was aborted in the middle of a sample buffer, the counter will
stop counting on a number divisible by the buffer size.  Since we actually
use it as a pointer into an aligned buffer, however, we do want to ensure
that it always starts at a number divisible by the buffer size when
starting a transaction, hence we reset it whenever starting a transaction.

To accomplish this, it wasn't necessary to zero bytescount at the
termination of each transaction, so remove this unnecessary code.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 4665ae12e74e4..e6f85f2e5ac2a 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1029,7 +1029,6 @@ static int acp_dma_prepare(struct snd_pcm_substream 
*substream)
 static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 {
int ret;
-   u64 bytescount = 0;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1040,9 +1039,7 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
-   bytescount = acp_get_byte_count(rtd);
-   if (rtd->bytescount == 0)
-   rtd->bytescount = bytescount;
+   rtd->bytescount = acp_get_byte_count(rtd);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
acp_dma_start(rtd->acp_mmio, rtd->ch1);
acp_dma_start(rtd->acp_mmio, rtd->ch2);
@@ -1069,7 +1066,6 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_SUSPEND:
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   rtd->bytescount = 0;
break;
default:
ret = -EINVAL;
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 2/6] ASoC: AMD: Reset bytescount when starting transaction

2018-07-02 Thread Daniel Kurtz
The pointer() callback gets its value by reading the I2S BYTE_COUNT
register.  This is a 64-bit runnning transaction counter. If a
transaction was aborted in the middle of a sample buffer, the counter will
stop counting on a number divisible by the buffer size.  Since we actually
use it as a pointer into an aligned buffer, however, we do want to ensure
that it always starts at a number divisible by the buffer size when
starting a transaction, hence we reset it whenever starting a transaction.

To accomplish this, it wasn't necessary to zero bytescount at the
termination of each transaction, so remove this unnecessary code.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 4665ae12e74e4..e6f85f2e5ac2a 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1029,7 +1029,6 @@ static int acp_dma_prepare(struct snd_pcm_substream 
*substream)
 static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 {
int ret;
-   u64 bytescount = 0;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1040,9 +1039,7 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
-   bytescount = acp_get_byte_count(rtd);
-   if (rtd->bytescount == 0)
-   rtd->bytescount = bytescount;
+   rtd->bytescount = acp_get_byte_count(rtd);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
acp_dma_start(rtd->acp_mmio, rtd->ch1);
acp_dma_start(rtd->acp_mmio, rtd->ch2);
@@ -1069,7 +1066,6 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_SUSPEND:
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
-   rtd->bytescount = 0;
break;
default:
ret = -EINVAL;
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 4/6] ASoC: AMD: Fix Capture DMA channel names

2018-07-02 Thread Daniel Kurtz
On capture, audio data is first copied from I2S to ACP memory, and then
to SYSRAM.  For each step the channel number increases, so the names in
the driver were wrong.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 24 
 sound/soc/amd/acp.h |  8 
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 224383fef0c3a..2a6a6e65e27c3 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -697,31 +697,31 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
-   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
- BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
acp_reg_write((intr_flag &
- BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
@@ -899,8 +899,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
switch (rtd->i2s_instance) {
case I2S_BT_INSTANCE:
rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET;
-   rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
-   rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
+   rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
+   rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS;
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
@@ -914,8 +914,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
case I2S_SP_INSTANCE:
default:
rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
-   rtd->ch1 = ACP_TO_SYSRAM_CH_NUM;
-   rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM;
+   rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM;
+   rtd->ch2 = ACP_TO_SYSRAM_CH_NUM;
switch (adata->asic_type) {
case CHIP_STONEY:
rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 3190fdce63074..0a2240bff62e1 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -74,16 +74,16 @@
 #define ACP_TO_I2S_DMA_CH_NUM 13
 
 /* Capture DMA channels */
-#define ACP_TO_SYSRAM_CH_NUM 14
-#define I2S_TO_ACP_DMA_CH_NUM 15
+#define I2S_TO_ACP_DMA_CH_NUM 14
+#define ACP_TO_SYSRAM_CH_NUM 15
 
 /* Playback DMA Channels for I2S BT instance */
 #define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM  8
 #define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9
 
 /* Capture DMA Channels for I2S BT Instance */
-#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10
-#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11
+#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10
+#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11
 
 #define NUM_DSCRS_PER_CHANNEL 2
 
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 6/6] ASoC: AMD: Simplify trigger handler

2018-07-02 Thread Daniel Kurtz
Now that the I2S channel names are fixed, and DMA data flow order is
consistent (ch1 then ch2), we can simplify channel start order:
start the upstream channel and then the downstream channel for both
playback and capture cases.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ab60129f4f266..65c1033bd51cc 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1024,10 +1024,7 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
rtd->bytescount = acp_get_byte_count(rtd);
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
-   } else {
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (rtd->capture_channel == CAP_CHANNEL0) {
acp_dma_cap_channel_disable(rtd->acp_mmio,
CAP_CHANNEL1);
@@ -1040,9 +1037,9 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 4/6] ASoC: AMD: Fix Capture DMA channel names

2018-07-02 Thread Daniel Kurtz
On capture, audio data is first copied from I2S to ACP memory, and then
to SYSRAM.  For each step the channel number increases, so the names in
the driver were wrong.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 24 
 sound/soc/amd/acp.h |  8 
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 224383fef0c3a..2a6a6e65e27c3 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -697,31 +697,31 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
-   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
- BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
acp_reg_write((intr_flag &
- BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
@@ -899,8 +899,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
switch (rtd->i2s_instance) {
case I2S_BT_INSTANCE:
rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET;
-   rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
-   rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
+   rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
+   rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS;
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
@@ -914,8 +914,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
case I2S_SP_INSTANCE:
default:
rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
-   rtd->ch1 = ACP_TO_SYSRAM_CH_NUM;
-   rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM;
+   rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM;
+   rtd->ch2 = ACP_TO_SYSRAM_CH_NUM;
switch (adata->asic_type) {
case CHIP_STONEY:
rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 3190fdce63074..0a2240bff62e1 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -74,16 +74,16 @@
 #define ACP_TO_I2S_DMA_CH_NUM 13
 
 /* Capture DMA channels */
-#define ACP_TO_SYSRAM_CH_NUM 14
-#define I2S_TO_ACP_DMA_CH_NUM 15
+#define I2S_TO_ACP_DMA_CH_NUM 14
+#define ACP_TO_SYSRAM_CH_NUM 15
 
 /* Playback DMA Channels for I2S BT instance */
 #define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM  8
 #define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9
 
 /* Capture DMA Channels for I2S BT Instance */
-#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10
-#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11
+#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10
+#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11
 
 #define NUM_DSCRS_PER_CHANNEL 2
 
-- 
2.18.0.399.gad0ab374a1-goog



[PATCH 6/6] ASoC: AMD: Simplify trigger handler

2018-07-02 Thread Daniel Kurtz
Now that the I2S channel names are fixed, and DMA data flow order is
consistent (ch1 then ch2), we can simplify channel start order:
start the upstream channel and then the downstream channel for both
playback and capture cases.

Signed-off-by: Daniel Kurtz 
---
 sound/soc/amd/acp-pcm-dma.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ab60129f4f266..65c1033bd51cc 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1024,10 +1024,7 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
rtd->bytescount = acp_get_byte_count(rtd);
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
-   } else {
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (rtd->capture_channel == CAP_CHANNEL0) {
acp_dma_cap_channel_disable(rtd->acp_mmio,
CAP_CHANNEL1);
@@ -1040,9 +1037,9 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
2.18.0.399.gad0ab374a1-goog



Re: [PATCH] ASoC: AMD: make channel 1 dma as circular

2018-05-26 Thread Daniel Kurtz
On Fri, May 25, 2018 at 3:23 AM Akshu Agrawal <akshu.agra...@amd.com> wrote:

> channel 1: SYSMEM<->ACP
> channel 2: ACP<->I2S
> Instead of waiting on period interrupt of ch 2 and then starting
> dma on ch1, we make ch1 dma as circular.
> This removes dependency of period granularity on hw pointer.

> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>


Reviewed-by: Daniel Kurtz <djku...@chromium.org>
Tested-by: Daniel Kurtz <djku...@chromium.org>


> ---
>   sound/soc/amd/acp-pcm-dma.c | 72
+++--
>   1 file changed, 10 insertions(+), 62 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index ac32dea..f1d8678 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
>   }

>   /* Start a given DMA channel transfer */
> -static void acp_dma_start(void __iomem *acp_mmio,
> - u16 ch_num, bool is_circular)
> +static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
>   {
>  u32 dma_ctrl;

> @@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
>  break;
>  }

> -   /* enable  for ACP SRAM to/from I2S DMA channel */
> -   if (is_circular == true)
> -   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
> -   else
> -   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
> +   /* circular for both DMA channel */
> +   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;

>  acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
>   }
> @@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
>   /* ACP DMA irq handler routine for playback, capture usecases */
>   static irqreturn_t dma_irq_handler(int irq, void *arg)
>   {
> -   u16 dscr_idx;
>  u32 intr_flag, ext_intr_status;
>  struct audio_drv_data *irq_data;
>  void __iomem *acp_mmio;
> @@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void
*arg)

>  if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
> -   PLAYBACK_START_DMA_DESCR_CH13)
> -   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
> -   else
> -   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM,
dscr_idx,
> -  1, 0);
> -   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
> -
>  snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
> -
>  acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) <<
16,
>acp_mmio, mmACP_EXTERNAL_INTR_STAT);
>  }

>  if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
> -   PLAYBACK_START_DMA_DESCR_CH9)
> -   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
> -   else
> -   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
> -   config_acp_dma_channel(acp_mmio,
> -  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
> -  dscr_idx, 1, 0);
> -   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
> - false);
>  snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
>  acp_reg_write((intr_flag &
>BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) <<
16,
> @@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void
*arg)

>  if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
> -   CAPTURE_START_DMA_DESCR_CH15)
> -   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
> -   else
> -   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM,
dscr_idx,
> -  1, 0);
> -   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
> -
> +   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
>  acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM

Re: [PATCH] ASoC: AMD: make channel 1 dma as circular

2018-05-26 Thread Daniel Kurtz
On Fri, May 25, 2018 at 3:23 AM Akshu Agrawal  wrote:

> channel 1: SYSMEM<->ACP
> channel 2: ACP<->I2S
> Instead of waiting on period interrupt of ch 2 and then starting
> dma on ch1, we make ch1 dma as circular.
> This removes dependency of period granularity on hw pointer.

> Signed-off-by: Akshu Agrawal 


Reviewed-by: Daniel Kurtz 
Tested-by: Daniel Kurtz 


> ---
>   sound/soc/amd/acp-pcm-dma.c | 72
+++--
>   1 file changed, 10 insertions(+), 62 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index ac32dea..f1d8678 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
>   }

>   /* Start a given DMA channel transfer */
> -static void acp_dma_start(void __iomem *acp_mmio,
> - u16 ch_num, bool is_circular)
> +static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
>   {
>  u32 dma_ctrl;

> @@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
>  break;
>  }

> -   /* enable  for ACP SRAM to/from I2S DMA channel */
> -   if (is_circular == true)
> -   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
> -   else
> -   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
> +   /* circular for both DMA channel */
> +   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;

>  acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
>   }
> @@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
>   /* ACP DMA irq handler routine for playback, capture usecases */
>   static irqreturn_t dma_irq_handler(int irq, void *arg)
>   {
> -   u16 dscr_idx;
>  u32 intr_flag, ext_intr_status;
>  struct audio_drv_data *irq_data;
>  void __iomem *acp_mmio;
> @@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void
*arg)

>  if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
> -   PLAYBACK_START_DMA_DESCR_CH13)
> -   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
> -   else
> -   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM,
dscr_idx,
> -  1, 0);
> -   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
> -
>  snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
> -
>  acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) <<
16,
>acp_mmio, mmACP_EXTERNAL_INTR_STAT);
>  }

>  if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
> -   PLAYBACK_START_DMA_DESCR_CH9)
> -   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
> -   else
> -   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
> -   config_acp_dma_channel(acp_mmio,
> -  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
> -  dscr_idx, 1, 0);
> -   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
> - false);
>  snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
>  acp_reg_write((intr_flag &
>BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) <<
16,
> @@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void
*arg)

>  if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
>  valid_irq = true;
> -   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
> -   CAPTURE_START_DMA_DESCR_CH15)
> -   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
> -   else
> -   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM,
dscr_idx,
> -  1, 0);
> -   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
> -
> +   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
>  acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) <<
16,
>acp_mmio, mmACP_EXTERNAL_INTR_STAT);
>

Re: [PATCH v3 2/2] ACPI: APD: Add AMD misc clock handler support

2018-05-09 Thread Daniel Kurtz
On Wed, May 9, 2018 at 4:01 AM Akshu Agrawal <akshu.agra...@amd.com> wrote:

> AMD SoC exposes clock for general purpose use. The clock registration
> is done in clk-st driver. The MMIO mapping are passed on to the
> clock driver for accessing the registers.
> The misc clock handler will create MMIO mappings to access the
> clock registers and enable the clock driver to expose the clock
> for use of drivers which will connect to it.

> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>

Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
> v2: Submitted with dependent patch, removed unneeded kfree for
devm_kzalloc
> v3: used devm_ioremap and fix coccinelle warning
>   drivers/acpi/acpi_apd.c | 47
+++
>   1 file changed, 47 insertions(+)

> diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
> index d553b00..2664452 100644
> --- a/drivers/acpi/acpi_apd.c
> +++ b/drivers/acpi/acpi_apd.c
> @@ -11,6 +11,7 @@
>*/

>   #include 
> +#include 
>   #include 
>   #include 
>   #include 
> @@ -72,6 +73,47 @@ static int acpi_apd_setup(struct apd_private_data
*pdata)
>   }

>   #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
> +
> +static int misc_check_res(struct acpi_resource *ares, void *data)
> +{
> +   struct resource res;
> +
> +   return !acpi_dev_resource_memory(ares, );
> +}
> +
> +static int st_misc_setup(struct apd_private_data *pdata)
> +{
> +   struct acpi_device *adev = pdata->adev;
> +   struct platform_device *clkdev;
> +   struct st_clk_data *clk_data;
> +   struct resource_entry *rentry;
> +   struct list_head resource_list;
> +   int ret;
> +
> +   clk_data = devm_kzalloc(>dev, sizeof(*clk_data),
GFP_KERNEL);
> +   if (!clk_data)
> +   return -ENOMEM;
> +
> +   INIT_LIST_HEAD(_list);
> +   ret = acpi_dev_get_resources(adev, _list, misc_check_res,
> +NULL);
> +   if (ret < 0)
> +   return -ENOENT;
> +
> +   list_for_each_entry(rentry, _list, node) {
> +   clk_data->base = devm_ioremap(>dev,
rentry->res->start,
> + resource_size(rentry->res));
> +   break;
> +   }
> +
> +   acpi_dev_free_resource_list(_list);
> +
> +   clkdev = platform_device_register_data(>dev, "clk-st",
> +  PLATFORM_DEVID_NONE,
clk_data,
> +  sizeof(*clk_data));
> +   return PTR_ERR_OR_ZERO(clkdev);
> +}
> +
>   static const struct apd_device_desc cz_i2c_desc = {
>  .setup = acpi_apd_setup,
>  .fixed_clk_rate = 13300,
> @@ -94,6 +136,10 @@ static int acpi_apd_setup(struct apd_private_data
*pdata)
>  .fixed_clk_rate = 4800,
>  .properties = uart_properties,
>   };
> +
> +static const struct apd_device_desc st_misc_desc = {
> +   .setup = st_misc_setup,
> +};
>   #endif

>   #ifdef CONFIG_ARM64
> @@ -179,6 +225,7 @@ static int acpi_apd_create_device(struct acpi_device
*adev,
>  { "AMD0020", APD_ADDR(cz_uart_desc) },
>  { "AMDI0020", APD_ADDR(cz_uart_desc) },
>  { "AMD0030", },
> +   { "AMD0040", APD_ADDR(st_misc_desc)},
>   #endif
>   #ifdef CONFIG_ARM64
>  { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
> --
> 1.9.1


Re: [PATCH v3 2/2] ACPI: APD: Add AMD misc clock handler support

2018-05-09 Thread Daniel Kurtz
On Wed, May 9, 2018 at 4:01 AM Akshu Agrawal  wrote:

> AMD SoC exposes clock for general purpose use. The clock registration
> is done in clk-st driver. The MMIO mapping are passed on to the
> clock driver for accessing the registers.
> The misc clock handler will create MMIO mappings to access the
> clock registers and enable the clock driver to expose the clock
> for use of drivers which will connect to it.

> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 

> ---
> v2: Submitted with dependent patch, removed unneeded kfree for
devm_kzalloc
> v3: used devm_ioremap and fix coccinelle warning
>   drivers/acpi/acpi_apd.c | 47
+++
>   1 file changed, 47 insertions(+)

> diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
> index d553b00..2664452 100644
> --- a/drivers/acpi/acpi_apd.c
> +++ b/drivers/acpi/acpi_apd.c
> @@ -11,6 +11,7 @@
>*/

>   #include 
> +#include 
>   #include 
>   #include 
>   #include 
> @@ -72,6 +73,47 @@ static int acpi_apd_setup(struct apd_private_data
*pdata)
>   }

>   #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
> +
> +static int misc_check_res(struct acpi_resource *ares, void *data)
> +{
> +   struct resource res;
> +
> +   return !acpi_dev_resource_memory(ares, );
> +}
> +
> +static int st_misc_setup(struct apd_private_data *pdata)
> +{
> +   struct acpi_device *adev = pdata->adev;
> +   struct platform_device *clkdev;
> +   struct st_clk_data *clk_data;
> +   struct resource_entry *rentry;
> +   struct list_head resource_list;
> +   int ret;
> +
> +   clk_data = devm_kzalloc(>dev, sizeof(*clk_data),
GFP_KERNEL);
> +   if (!clk_data)
> +   return -ENOMEM;
> +
> +   INIT_LIST_HEAD(_list);
> +   ret = acpi_dev_get_resources(adev, _list, misc_check_res,
> +NULL);
> +   if (ret < 0)
> +   return -ENOENT;
> +
> +   list_for_each_entry(rentry, _list, node) {
> +   clk_data->base = devm_ioremap(>dev,
rentry->res->start,
> + resource_size(rentry->res));
> +   break;
> +   }
> +
> +   acpi_dev_free_resource_list(_list);
> +
> +   clkdev = platform_device_register_data(>dev, "clk-st",
> +  PLATFORM_DEVID_NONE,
clk_data,
> +  sizeof(*clk_data));
> +   return PTR_ERR_OR_ZERO(clkdev);
> +}
> +
>   static const struct apd_device_desc cz_i2c_desc = {
>  .setup = acpi_apd_setup,
>  .fixed_clk_rate = 13300,
> @@ -94,6 +136,10 @@ static int acpi_apd_setup(struct apd_private_data
*pdata)
>  .fixed_clk_rate = 4800,
>  .properties = uart_properties,
>   };
> +
> +static const struct apd_device_desc st_misc_desc = {
> +   .setup = st_misc_setup,
> +};
>   #endif

>   #ifdef CONFIG_ARM64
> @@ -179,6 +225,7 @@ static int acpi_apd_create_device(struct acpi_device
*adev,
>  { "AMD0020", APD_ADDR(cz_uart_desc) },
>  { "AMDI0020", APD_ADDR(cz_uart_desc) },
>  { "AMD0030", },
> +   { "AMD0040", APD_ADDR(st_misc_desc)},
>   #endif
>   #ifdef CONFIG_ARM64
>  { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
> --
> 1.9.1


Re: [PATCH v5 1/2] clk: x86: Add ST oscout platform clock

2018-05-09 Thread Daniel Kurtz
On Wed, May 9, 2018 at 4:01 AM Akshu Agrawal <akshu.agra...@amd.com> wrote:

> Stoney SoC provides oscout clock. This clock can support 25Mhz and
> 48Mhz of frequency.
> The clock is available for general system use.

> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>

Reviewed-by: Daniel Kurtz <djku...@chromium.org>


> ---
> v2: config change, added SPDX tag and used clk_hw_register_.
> v3: Fix kbuild warning for checking of NULL pointer
> v4: unregister clk_hw in driver remove, add .suppress_bind_attrs
> v5: Fix license, used static array
>   drivers/clk/x86/Makefile |  3 +-
>   drivers/clk/x86/clk-st.c | 77

>   include/linux/platform_data/clk-st.h | 17 
>   3 files changed, 96 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/clk/x86/clk-st.c
>   create mode 100644 include/linux/platform_data/clk-st.h

> diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
> index 1367afb..00303bc 100644
> --- a/drivers/clk/x86/Makefile
> +++ b/drivers/clk/x86/Makefile
> @@ -1,3 +1,4 @@
> +obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
> +obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
>   clk-x86-lpss-objs  := clk-lpt.o
>   obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
> -obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
> diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
> new file mode 100644
> index 000..fb62f39
> --- /dev/null
> +++ b/drivers/clk/x86/clk-st.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * clock framework for AMD Stoney based clocks
> + *
> + * Copyright 2018 Advanced Micro Devices, Inc.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/* Clock Driving Strength 2 register */
> +#define CLKDRVSTR2 0x28
> +/* Clock Control 1 register */
> +#define MISCCLKCNTL1   0x40
> +/* Auxiliary clock1 enable bit */
> +#define OSCCLKENB  2
> +/* 25Mhz auxiliary output clock freq bit */
> +#define OSCOUT1CLK25MHZ16
> +
> +#define ST_CLK_48M 0
> +#define ST_CLK_25M 1
> +#define ST_CLK_MUX 2
> +#define ST_CLK_GATE3
> +#define ST_MAX_CLKS4
> +
> +static const char * const clk_oscout1_parents[] = { "clk48MHz",
"clk25MHz" };
> +static struct clk_hw *hws[ST_MAX_CLKS];
> +
> +static int st_clk_probe(struct platform_device *pdev)
> +{
> +   struct st_clk_data *st_data;
> +
> +   st_data = dev_get_platdata(>dev);
> +   if (!st_data || !st_data->base)
> +   return -EINVAL;
> +
> +   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
NULL, 0,
> +4800);
> +   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
NULL, 0,
> +2500);
> +
> +   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
> +   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
> +   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
NULL);
> +
> +   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
> +
> +   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
"oscout1_mux",
> +   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
> +   CLK_GATE_SET_TO_DISABLE, NULL);
> +
> +   clk_hw_register_clkdev(hws[ST_CLK_GATE], "oscout1", NULL);
> +
> +   return 0;
> +}
> +
> +static int st_clk_remove(struct platform_device *pdev)
> +{
> +   int i;
> +
> +   for (i = 0; i < ST_MAX_CLKS; i++)
> +   clk_hw_unregister(hws[i]);
> +   return 0;
> +}
> +
> +static struct platform_driver st_clk_driver = {
> +   .driver = {
> +   .name = "clk-st",
> +   .suppress_bind_attrs = true,
> +   },
> +   .probe = st_clk_probe,
> +   .remove = st_clk_remove,
> +};
> +builtin_platform_driver(st_clk_driver);
> diff --git a/include/linux/platform_data/clk-st.h
b/include/linux/platform_data/clk-st.h
> new file mode 100644
> index 000..7cdb6a4
> --- /dev/null
> +++ b/include/linux/platform_data/clk-st.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * clock framework for AMD Stoney based clock
> + *
> + * Copyright 2018 Advanced Micro Devices, Inc.
> + */
> +
> +#ifndef __CLK_ST_H
> +#define __CLK_ST_H
> +
> +#include 
> +
> +struct st_clk_data {
> +   void __iomem *base;
> +};
> +
> +#endif /* __CLK_ST_H */
> --
> 1.9.1


Re: [PATCH v5 1/2] clk: x86: Add ST oscout platform clock

2018-05-09 Thread Daniel Kurtz
On Wed, May 9, 2018 at 4:01 AM Akshu Agrawal  wrote:

> Stoney SoC provides oscout clock. This clock can support 25Mhz and
> 48Mhz of frequency.
> The clock is available for general system use.

> Signed-off-by: Akshu Agrawal 

Reviewed-by: Daniel Kurtz 


> ---
> v2: config change, added SPDX tag and used clk_hw_register_.
> v3: Fix kbuild warning for checking of NULL pointer
> v4: unregister clk_hw in driver remove, add .suppress_bind_attrs
> v5: Fix license, used static array
>   drivers/clk/x86/Makefile |  3 +-
>   drivers/clk/x86/clk-st.c | 77

>   include/linux/platform_data/clk-st.h | 17 
>   3 files changed, 96 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/clk/x86/clk-st.c
>   create mode 100644 include/linux/platform_data/clk-st.h

> diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
> index 1367afb..00303bc 100644
> --- a/drivers/clk/x86/Makefile
> +++ b/drivers/clk/x86/Makefile
> @@ -1,3 +1,4 @@
> +obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
> +obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
>   clk-x86-lpss-objs  := clk-lpt.o
>   obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
> -obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
> diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
> new file mode 100644
> index 000..fb62f39
> --- /dev/null
> +++ b/drivers/clk/x86/clk-st.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * clock framework for AMD Stoney based clocks
> + *
> + * Copyright 2018 Advanced Micro Devices, Inc.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/* Clock Driving Strength 2 register */
> +#define CLKDRVSTR2 0x28
> +/* Clock Control 1 register */
> +#define MISCCLKCNTL1   0x40
> +/* Auxiliary clock1 enable bit */
> +#define OSCCLKENB  2
> +/* 25Mhz auxiliary output clock freq bit */
> +#define OSCOUT1CLK25MHZ16
> +
> +#define ST_CLK_48M 0
> +#define ST_CLK_25M 1
> +#define ST_CLK_MUX 2
> +#define ST_CLK_GATE3
> +#define ST_MAX_CLKS4
> +
> +static const char * const clk_oscout1_parents[] = { "clk48MHz",
"clk25MHz" };
> +static struct clk_hw *hws[ST_MAX_CLKS];
> +
> +static int st_clk_probe(struct platform_device *pdev)
> +{
> +   struct st_clk_data *st_data;
> +
> +   st_data = dev_get_platdata(>dev);
> +   if (!st_data || !st_data->base)
> +   return -EINVAL;
> +
> +   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
NULL, 0,
> +4800);
> +   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
NULL, 0,
> +2500);
> +
> +   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
> +   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
> +   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
NULL);
> +
> +   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
> +
> +   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
"oscout1_mux",
> +   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
> +   CLK_GATE_SET_TO_DISABLE, NULL);
> +
> +   clk_hw_register_clkdev(hws[ST_CLK_GATE], "oscout1", NULL);
> +
> +   return 0;
> +}
> +
> +static int st_clk_remove(struct platform_device *pdev)
> +{
> +   int i;
> +
> +   for (i = 0; i < ST_MAX_CLKS; i++)
> +   clk_hw_unregister(hws[i]);
> +   return 0;
> +}
> +
> +static struct platform_driver st_clk_driver = {
> +   .driver = {
> +   .name = "clk-st",
> +   .suppress_bind_attrs = true,
> +   },
> +   .probe = st_clk_probe,
> +   .remove = st_clk_remove,
> +};
> +builtin_platform_driver(st_clk_driver);
> diff --git a/include/linux/platform_data/clk-st.h
b/include/linux/platform_data/clk-st.h
> new file mode 100644
> index 000..7cdb6a4
> --- /dev/null
> +++ b/include/linux/platform_data/clk-st.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * clock framework for AMD Stoney based clock
> + *
> + * Copyright 2018 Advanced Micro Devices, Inc.
> + */
> +
> +#ifndef __CLK_ST_H
> +#define __CLK_ST_H
> +
> +#include 
> +
> +struct st_clk_data {
> +   void __iomem *base;
> +};
> +
> +#endif /* __CLK_ST_H */
> --
> 1.9.1


Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-07 Thread Daniel Kurtz
On Thu, May 3, 2018 at 10:35 PM Agrawal, Akshu <akshu.agra...@amd.com>
wrote:



> On 5/3/2018 10:10 PM, Daniel Kurtz wrote:
> > On Thu, May 3, 2018 at 1:33 AM Mukunda,Vijendar <
vijendar.muku...@amd.com>
> > wrote:
> >
> >
> >
> >> On Thursday 03 May 2018 11:13 AM, Daniel Kurtz wrote:
> >>> Some checkpatch nits below...
> >>>
> >>> On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda <
> > vijendar.muku...@amd.com>
> >>> wrote:
> >>>
> >>>> With in ACP, There are three I2S controllers can be
> >>>> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> >>>> Default enabled I2S controller instance is I2S SP.
> >>>> This patch provides required changes to support I2S BT
> >>>> controller Instance.
> >>>
> >>>> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>
> >>>> ---
> >>>> v1->v2: defined i2s instance macros in acp header file
> >>>> v2->v3: sqaushed previous patch series and spilt changes
> >>>> into multiple patches (acp dma driver code cleanup
> >>>> patches and bt i2s instance specific changes)
> >>>>  sound/soc/amd/acp-da7219-max98357a.c |  23 
> >>>>  sound/soc/amd/acp-pcm-dma.c  | 256
> >>> +++
> >>>>  sound/soc/amd/acp.h  |  40 ++
> >>>>  3 files changed, 262 insertions(+), 57 deletions(-)
> >>>
> >>>> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
> >>> b/sound/soc/amd/acp-da7219-max98357a.c
> >>>> index 133139d..b3184ab 100644
> >>>> --- a/sound/soc/amd/acp-da7219-max98357a.c
> >>>> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> >>>> @@ -36,6 +36,7 @@
> >>>>  #include 
> >>>>  #include 
> >>>
> >>>> +#include "acp.h"
> >>>>  #include "../codecs/da7219.h"
> >>>>  #include "../codecs/da7219-aad.h"
> >>>
> >>>> @@ -44,6 +45,7 @@
> >>>
> >>>>  static struct snd_soc_jack cz_jack;
> >>>>  static struct clk *da7219_dai_clk;
> >>>> +extern int bt_pad_enable;
> >>>
> >>> WARNING: externs should be avoided in .c files
> >
> >> We don't have .h file for machine driver and It can be ignored for
> >> one variable.
> >>>
> >>>
> >>>>  static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
> >>>>  {
> >>>> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
> >>> constraints_channels = {
> >>>>  static int cz_da7219_startup(struct snd_pcm_substream
*substream)
> >>>>  {
> >>>> struct snd_pcm_runtime *runtime = substream->runtime;
> >>>> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> >>>> +   struct snd_soc_card *card = rtd->card;
> >>>> +   struct acp_platform_info *machine =
> >>> snd_soc_card_get_drvdata(card);
> >>>
> >>>> /*
> >>>>  * On this platform for PCM device we support stereo
> >>>> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct
> > snd_pcm_substream
> >>> *substream)
> >>>> snd_pcm_hw_constraint_list(runtime, 0,
> > SNDRV_PCM_HW_PARAM_RATE,
> >>>>_rates);
> >>>
> >>>> +   machine->i2s_instance = I2S_BT_INSTANCE;
> >>>
> >>> I'm not a big fan of this approach, but I don't know any other way to
> > tell
> >>> a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT)
> > to
> >>> use via the pcm_open() callback.
> >>>
> >>> Mark, can you recommend any other way of doing this?
> >
> >> Hi Dan,
> >
> >> There have been couple of approaches worked upon this earlier.
> >> 1) To compare cpu dai name to get the I2S instance value in
> >> acp_dma_open() call.
> >
> >> But, Mark suggested not to implement this approach as we are comparing
> >> dynamically generated cpu dai names.
> >
> >> 2) We added i2s_instance parameter as platform data to dwc driver.
> >> By qu

Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-07 Thread Daniel Kurtz
On Thu, May 3, 2018 at 10:35 PM Agrawal, Akshu 
wrote:



> On 5/3/2018 10:10 PM, Daniel Kurtz wrote:
> > On Thu, May 3, 2018 at 1:33 AM Mukunda,Vijendar <
vijendar.muku...@amd.com>
> > wrote:
> >
> >
> >
> >> On Thursday 03 May 2018 11:13 AM, Daniel Kurtz wrote:
> >>> Some checkpatch nits below...
> >>>
> >>> On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda <
> > vijendar.muku...@amd.com>
> >>> wrote:
> >>>
> >>>> With in ACP, There are three I2S controllers can be
> >>>> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> >>>> Default enabled I2S controller instance is I2S SP.
> >>>> This patch provides required changes to support I2S BT
> >>>> controller Instance.
> >>>
> >>>> Signed-off-by: Vijendar Mukunda 
> >>>> ---
> >>>> v1->v2: defined i2s instance macros in acp header file
> >>>> v2->v3: sqaushed previous patch series and spilt changes
> >>>> into multiple patches (acp dma driver code cleanup
> >>>> patches and bt i2s instance specific changes)
> >>>>  sound/soc/amd/acp-da7219-max98357a.c |  23 
> >>>>  sound/soc/amd/acp-pcm-dma.c  | 256
> >>> +++
> >>>>  sound/soc/amd/acp.h  |  40 ++
> >>>>  3 files changed, 262 insertions(+), 57 deletions(-)
> >>>
> >>>> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
> >>> b/sound/soc/amd/acp-da7219-max98357a.c
> >>>> index 133139d..b3184ab 100644
> >>>> --- a/sound/soc/amd/acp-da7219-max98357a.c
> >>>> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> >>>> @@ -36,6 +36,7 @@
> >>>>  #include 
> >>>>  #include 
> >>>
> >>>> +#include "acp.h"
> >>>>  #include "../codecs/da7219.h"
> >>>>  #include "../codecs/da7219-aad.h"
> >>>
> >>>> @@ -44,6 +45,7 @@
> >>>
> >>>>  static struct snd_soc_jack cz_jack;
> >>>>  static struct clk *da7219_dai_clk;
> >>>> +extern int bt_pad_enable;
> >>>
> >>> WARNING: externs should be avoided in .c files
> >
> >> We don't have .h file for machine driver and It can be ignored for
> >> one variable.
> >>>
> >>>
> >>>>  static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
> >>>>  {
> >>>> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
> >>> constraints_channels = {
> >>>>  static int cz_da7219_startup(struct snd_pcm_substream
*substream)
> >>>>  {
> >>>> struct snd_pcm_runtime *runtime = substream->runtime;
> >>>> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> >>>> +   struct snd_soc_card *card = rtd->card;
> >>>> +   struct acp_platform_info *machine =
> >>> snd_soc_card_get_drvdata(card);
> >>>
> >>>> /*
> >>>>  * On this platform for PCM device we support stereo
> >>>> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct
> > snd_pcm_substream
> >>> *substream)
> >>>> snd_pcm_hw_constraint_list(runtime, 0,
> > SNDRV_PCM_HW_PARAM_RATE,
> >>>>_rates);
> >>>
> >>>> +   machine->i2s_instance = I2S_BT_INSTANCE;
> >>>
> >>> I'm not a big fan of this approach, but I don't know any other way to
> > tell
> >>> a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT)
> > to
> >>> use via the pcm_open() callback.
> >>>
> >>> Mark, can you recommend any other way of doing this?
> >
> >> Hi Dan,
> >
> >> There have been couple of approaches worked upon this earlier.
> >> 1) To compare cpu dai name to get the I2S instance value in
> >> acp_dma_open() call.
> >
> >> But, Mark suggested not to implement this approach as we are comparing
> >> dynamically generated cpu dai names.
> >
> >> 2) We added i2s_instance parameter as platform data to dwc driver.
> >> By querying dwc driver platform data in acp dma driver, current i2s

Re: [PATCH v3] ASoC: da7219: read fmw property to get mclk for non-dts systems

2018-05-07 Thread Daniel Kurtz
On Sun, May 6, 2018 at 10:50 PM Agrawal, Akshu <akshu.agra...@amd.com>
wrote:



> On 5/4/2018 2:45 PM, Adam Thomson wrote:
> > On 03 May 2018 08:59, Akshu Agrawal wrote:
> >
> >> Non-dts based systems can use ACPI DSDT to pass on the mclk
> >> to da7219.
> >> This enables da7219 mclk to be linked to system clock.
> >> Enable/Disable of the mclk is already handled in the codec so
> >> platform drivers don't have to explicitly do handling of mclk.
> >>
> >> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
> >> ---
> >> v2: Fixed kbuild error
> >> v3: Add corresponding clk_put for clk_get
> >>  include/sound/da7219.h|  2 ++
> >>  sound/soc/codecs/da7219.c | 10 +-
> >>  2 files changed, 11 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/sound/da7219.h b/include/sound/da7219.h
> >> index 1bfcb16..df7ddf4 100644
> >> --- a/include/sound/da7219.h
> >> +++ b/include/sound/da7219.h
> >> @@ -38,6 +38,8 @@ struct da7219_pdata {
> >>
> >>  const char *dai_clks_name;
> >>
> >> +const char *mclk_name;
> >> +
> >>  /* Mic */
> >>  enum da7219_micbias_voltage micbias_lvl;
> >>  enum da7219_mic_amp_in_sel mic_amp_in_sel;
> >> diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
> >> index 980a6a8..ecd46fc 100644
> >> --- a/sound/soc/codecs/da7219.c
> >> +++ b/sound/soc/codecs/da7219.c
> >> @@ -1624,6 +1624,8 @@ static struct da7219_pdata
*da7219_fw_to_pdata(struct
> >> snd_soc_component *compone
> >>  dev_warn(dev, "Using default clk name: %s\n",
> >>   pdata->dai_clks_name);
> >>
> >> +device_property_read_string(dev, "dlg,mclk-name",
>mclk_name);
> >> +
> >
> > Personally am still not keen on this. To me the use of a
device_property_*
> > function suggests the same property resides in both DT and ACPI, but
here we're
> > only using this for the ACPI case. DT has no want or need for this. I
still feel
> > we should look at something more generic in the clock framework,
although I do
> > agree with Mark that this should be properly specced.
> >

> I am not an expert in field of ACPI, IMO forming a Spec and changing
> ACPI to have DT like clock framework is good to have but a bigger change
> which should be taken up later.

> The current code of handling of mclk in the driver is usable only by DT.
> The device_property (though ACPI specific) makes this code, a common
> code for DT and ACPI based devices.

> https://www.kernel.org/doc/Documentation/acpi/DSD-properties-rules.txt
> "Still, for the sake of code re-use, it may make sense to provide as
> much of the configuration data as possible in the form of device
> properties and complement that with an ACPI-specific mechanism suitable
> for the use case at hand.."

This sounds like a pretty reasonable justification for addressing the issue
using DSD to me.
For what its worth, you can add:

Reviewed-by: Daniel Kurtz <djku...@chromium.org>



> Thanks,
> Akshu


Re: [PATCH v3] ASoC: da7219: read fmw property to get mclk for non-dts systems

2018-05-07 Thread Daniel Kurtz
On Sun, May 6, 2018 at 10:50 PM Agrawal, Akshu 
wrote:



> On 5/4/2018 2:45 PM, Adam Thomson wrote:
> > On 03 May 2018 08:59, Akshu Agrawal wrote:
> >
> >> Non-dts based systems can use ACPI DSDT to pass on the mclk
> >> to da7219.
> >> This enables da7219 mclk to be linked to system clock.
> >> Enable/Disable of the mclk is already handled in the codec so
> >> platform drivers don't have to explicitly do handling of mclk.
> >>
> >> Signed-off-by: Akshu Agrawal 
> >> ---
> >> v2: Fixed kbuild error
> >> v3: Add corresponding clk_put for clk_get
> >>  include/sound/da7219.h|  2 ++
> >>  sound/soc/codecs/da7219.c | 10 +-
> >>  2 files changed, 11 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/sound/da7219.h b/include/sound/da7219.h
> >> index 1bfcb16..df7ddf4 100644
> >> --- a/include/sound/da7219.h
> >> +++ b/include/sound/da7219.h
> >> @@ -38,6 +38,8 @@ struct da7219_pdata {
> >>
> >>  const char *dai_clks_name;
> >>
> >> +const char *mclk_name;
> >> +
> >>  /* Mic */
> >>  enum da7219_micbias_voltage micbias_lvl;
> >>  enum da7219_mic_amp_in_sel mic_amp_in_sel;
> >> diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
> >> index 980a6a8..ecd46fc 100644
> >> --- a/sound/soc/codecs/da7219.c
> >> +++ b/sound/soc/codecs/da7219.c
> >> @@ -1624,6 +1624,8 @@ static struct da7219_pdata
*da7219_fw_to_pdata(struct
> >> snd_soc_component *compone
> >>  dev_warn(dev, "Using default clk name: %s\n",
> >>   pdata->dai_clks_name);
> >>
> >> +device_property_read_string(dev, "dlg,mclk-name",
>mclk_name);
> >> +
> >
> > Personally am still not keen on this. To me the use of a
device_property_*
> > function suggests the same property resides in both DT and ACPI, but
here we're
> > only using this for the ACPI case. DT has no want or need for this. I
still feel
> > we should look at something more generic in the clock framework,
although I do
> > agree with Mark that this should be properly specced.
> >

> I am not an expert in field of ACPI, IMO forming a Spec and changing
> ACPI to have DT like clock framework is good to have but a bigger change
> which should be taken up later.

> The current code of handling of mclk in the driver is usable only by DT.
> The device_property (though ACPI specific) makes this code, a common
> code for DT and ACPI based devices.

> https://www.kernel.org/doc/Documentation/acpi/DSD-properties-rules.txt
> "Still, for the sake of code re-use, it may make sense to provide as
> much of the configuration data as possible in the form of device
> properties and complement that with an ACPI-specific mechanism suitable
> for the use case at hand.."

This sounds like a pretty reasonable justification for addressing the issue
using DSD to me.
For what its worth, you can add:

Reviewed-by: Daniel Kurtz 



> Thanks,
> Akshu


Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-03 Thread Daniel Kurtz
On Thu, May 3, 2018 at 1:33 AM Mukunda,Vijendar <vijendar.muku...@amd.com>
wrote:



> On Thursday 03 May 2018 11:13 AM, Daniel Kurtz wrote:
> > Some checkpatch nits below...
> >
> > On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda <
vijendar.muku...@amd.com>
> > wrote:
> >
> >> With in ACP, There are three I2S controllers can be
> >> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> >> Default enabled I2S controller instance is I2S SP.
> >> This patch provides required changes to support I2S BT
> >> controller Instance.
> >
> >> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>
> >> ---
> >> v1->v2: defined i2s instance macros in acp header file
> >> v2->v3: sqaushed previous patch series and spilt changes
> >>into multiple patches (acp dma driver code cleanup
> >>patches and bt i2s instance specific changes)
> >> sound/soc/amd/acp-da7219-max98357a.c |  23 
> >> sound/soc/amd/acp-pcm-dma.c  | 256
> > +++
> >> sound/soc/amd/acp.h  |  40 ++
> >> 3 files changed, 262 insertions(+), 57 deletions(-)
> >
> >> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
> > b/sound/soc/amd/acp-da7219-max98357a.c
> >> index 133139d..b3184ab 100644
> >> --- a/sound/soc/amd/acp-da7219-max98357a.c
> >> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> >> @@ -36,6 +36,7 @@
> >> #include 
> >> #include 
> >
> >> +#include "acp.h"
> >> #include "../codecs/da7219.h"
> >> #include "../codecs/da7219-aad.h"
> >
> >> @@ -44,6 +45,7 @@
> >
> >> static struct snd_soc_jack cz_jack;
> >> static struct clk *da7219_dai_clk;
> >> +extern int bt_pad_enable;
> >
> > WARNING: externs should be avoided in .c files

> We don't have .h file for machine driver and It can be ignored for
> one variable.
> >
> >
> >> static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
> >> {
> >> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
> > constraints_channels = {
> >> static int cz_da7219_startup(struct snd_pcm_substream *substream)
> >> {
> >>struct snd_pcm_runtime *runtime = substream->runtime;
> >> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> >> +   struct snd_soc_card *card = rtd->card;
> >> +   struct acp_platform_info *machine =
> > snd_soc_card_get_drvdata(card);
> >
> >>/*
> >> * On this platform for PCM device we support stereo
> >> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct
snd_pcm_substream
> > *substream)
> >>snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
> >>   _rates);
> >
> >> +   machine->i2s_instance = I2S_BT_INSTANCE;
> >
> > I'm not a big fan of this approach, but I don't know any other way to
tell
> > a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT)
to
> > use via the pcm_open() callback.
> >
> > Mark, can you recommend any other way of doing this?

> Hi Dan,

> There have been couple of approaches worked upon this earlier.
> 1) To compare cpu dai name to get the I2S instance value in
> acp_dma_open() call.

> But, Mark suggested not to implement this approach as we are comparing
> dynamically generated cpu dai names.

> 2) We added i2s_instance parameter as platform data to dwc driver.
> By querying dwc driver platform data in acp dma driver, current i2s
> instance was programmed in acp_dma_open ().

> But Mark's latest comment was to implement platform specific changes in
> machine driver. Machine driver and Dma driver should exchange the data
> regarding this. We accepted this and current approach is based on the
> same comment.
> Below is the reference.
> https://lkml.org/lkml/2018/4/18/597

Yes, I saw Mark's previous comment, but what we are trying to implement
here is the SoC specific binding between i2s channel and acp-dma channel.
This is a feature of the SoC, not of the i2s controller, but also not a
feature of the audio configuration on the board.  For these SoCs, the link
between DMA registers & I2S-channel is hard-coded.  The machine driver is
already specifying which i2s channel to use when it configures, for
example, '.cpu_dai_name = "designware-i2s.2.auto"'.  The i2s channel
selection already implies a particular DMA configuration.  It seems
redundant to create this separate out-of-band infrastructure to make the
machine driver also tell its platform driver '.platform_name =
"acp_audio_dma.0.auto"' which i2s channel it is using.

Perhaps the acp-pcm-dma.c should register two different platform drivers,
and let the machine driver pick the appropriate one (ie,
acp_audio_dma.0.auto or acp_audio_dma.1.auto) depending on which i2s port
it needs?  Then each of these would have its own
snd_soc_platform_driver->ops->open() that could setup
snd_pcm_runtime->private_data appropriately?  Or is there another standard
way to have a single snd_soc_platform_driver handle multiple channels?

-Dan


Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-03 Thread Daniel Kurtz
On Thu, May 3, 2018 at 1:33 AM Mukunda,Vijendar 
wrote:



> On Thursday 03 May 2018 11:13 AM, Daniel Kurtz wrote:
> > Some checkpatch nits below...
> >
> > On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda <
vijendar.muku...@amd.com>
> > wrote:
> >
> >> With in ACP, There are three I2S controllers can be
> >> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> >> Default enabled I2S controller instance is I2S SP.
> >> This patch provides required changes to support I2S BT
> >> controller Instance.
> >
> >> Signed-off-by: Vijendar Mukunda 
> >> ---
> >> v1->v2: defined i2s instance macros in acp header file
> >> v2->v3: sqaushed previous patch series and spilt changes
> >>into multiple patches (acp dma driver code cleanup
> >>patches and bt i2s instance specific changes)
> >> sound/soc/amd/acp-da7219-max98357a.c |  23 
> >> sound/soc/amd/acp-pcm-dma.c  | 256
> > +++
> >> sound/soc/amd/acp.h  |  40 ++
> >> 3 files changed, 262 insertions(+), 57 deletions(-)
> >
> >> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
> > b/sound/soc/amd/acp-da7219-max98357a.c
> >> index 133139d..b3184ab 100644
> >> --- a/sound/soc/amd/acp-da7219-max98357a.c
> >> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> >> @@ -36,6 +36,7 @@
> >> #include 
> >> #include 
> >
> >> +#include "acp.h"
> >> #include "../codecs/da7219.h"
> >> #include "../codecs/da7219-aad.h"
> >
> >> @@ -44,6 +45,7 @@
> >
> >> static struct snd_soc_jack cz_jack;
> >> static struct clk *da7219_dai_clk;
> >> +extern int bt_pad_enable;
> >
> > WARNING: externs should be avoided in .c files

> We don't have .h file for machine driver and It can be ignored for
> one variable.
> >
> >
> >> static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
> >> {
> >> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
> > constraints_channels = {
> >> static int cz_da7219_startup(struct snd_pcm_substream *substream)
> >> {
> >>struct snd_pcm_runtime *runtime = substream->runtime;
> >> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> >> +   struct snd_soc_card *card = rtd->card;
> >> +   struct acp_platform_info *machine =
> > snd_soc_card_get_drvdata(card);
> >
> >>/*
> >> * On this platform for PCM device we support stereo
> >> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct
snd_pcm_substream
> > *substream)
> >>snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
> >>   _rates);
> >
> >> +   machine->i2s_instance = I2S_BT_INSTANCE;
> >
> > I'm not a big fan of this approach, but I don't know any other way to
tell
> > a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT)
to
> > use via the pcm_open() callback.
> >
> > Mark, can you recommend any other way of doing this?

> Hi Dan,

> There have been couple of approaches worked upon this earlier.
> 1) To compare cpu dai name to get the I2S instance value in
> acp_dma_open() call.

> But, Mark suggested not to implement this approach as we are comparing
> dynamically generated cpu dai names.

> 2) We added i2s_instance parameter as platform data to dwc driver.
> By querying dwc driver platform data in acp dma driver, current i2s
> instance was programmed in acp_dma_open ().

> But Mark's latest comment was to implement platform specific changes in
> machine driver. Machine driver and Dma driver should exchange the data
> regarding this. We accepted this and current approach is based on the
> same comment.
> Below is the reference.
> https://lkml.org/lkml/2018/4/18/597

Yes, I saw Mark's previous comment, but what we are trying to implement
here is the SoC specific binding between i2s channel and acp-dma channel.
This is a feature of the SoC, not of the i2s controller, but also not a
feature of the audio configuration on the board.  For these SoCs, the link
between DMA registers & I2S-channel is hard-coded.  The machine driver is
already specifying which i2s channel to use when it configures, for
example, '.cpu_dai_name = "designware-i2s.2.auto"'.  The i2s channel
selection already implies a particular DMA configuration.  It seems
redundant to create this separate out-of-band infrastructure to make the
machine driver also tell its platform driver '.platform_name =
"acp_audio_dma.0.auto"' which i2s channel it is using.

Perhaps the acp-pcm-dma.c should register two different platform drivers,
and let the machine driver pick the appropriate one (ie,
acp_audio_dma.0.auto or acp_audio_dma.1.auto) depending on which i2s port
it needs?  Then each of these would have its own
snd_soc_platform_driver->ops->open() that could setup
snd_pcm_runtime->private_data appropriately?  Or is there another standard
way to have a single snd_soc_platform_driver handle multiple channels?

-Dan


Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-02 Thread Daniel Kurtz
Some checkpatch nits below...

On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda 
wrote:

> With in ACP, There are three I2S controllers can be
> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> Default enabled I2S controller instance is I2S SP.
> This patch provides required changes to support I2S BT
> controller Instance.

> Signed-off-by: Vijendar Mukunda 
> ---
> v1->v2: defined i2s instance macros in acp header file
> v2->v3: sqaushed previous patch series and spilt changes
>   into multiple patches (acp dma driver code cleanup
>   patches and bt i2s instance specific changes)
>sound/soc/amd/acp-da7219-max98357a.c |  23 
>sound/soc/amd/acp-pcm-dma.c  | 256
+++
>sound/soc/amd/acp.h  |  40 ++
>3 files changed, 262 insertions(+), 57 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index 133139d..b3184ab 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -36,6 +36,7 @@
>#include 
>#include 

> +#include "acp.h"
>#include "../codecs/da7219.h"
>#include "../codecs/da7219-aad.h"

> @@ -44,6 +45,7 @@

>static struct snd_soc_jack cz_jack;
>static struct clk *da7219_dai_clk;
> +extern int bt_pad_enable;

WARNING: externs should be avoided in .c files


>static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
>{
> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
constraints_channels = {
>static int cz_da7219_startup(struct snd_pcm_substream *substream)
>{
>   struct snd_pcm_runtime *runtime = substream->runtime;
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);

>   /*
>* On this platform for PCM device we support stereo
> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct snd_pcm_substream
*substream)
>   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
>  _rates);

> +   machine->i2s_instance = I2S_BT_INSTANCE;

I'm not a big fan of this approach, but I don't know any other way to tell
a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT) to
use via the pcm_open() callback.

Mark, can you recommend any other way of doing this?

>   return da7219_clk_enable(substream);
>}

> @@ -153,6 +159,11 @@ static void cz_da7219_shutdown(struct
snd_pcm_substream *substream)

>static int cz_max_startup(struct snd_pcm_substream *substream)
>{
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);
> +
> +   machine->i2s_instance = I2S_SP_INSTANCE;
>   return da7219_clk_enable(substream);
>}

> @@ -163,6 +174,11 @@ static void cz_max_shutdown(struct snd_pcm_substream
*substream)

>static int cz_dmic_startup(struct snd_pcm_substream *substream)
>{
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);
> +
> +   machine->i2s_instance = I2S_SP_INSTANCE;
>   return da7219_clk_enable(substream);
>}

> @@ -266,10 +282,16 @@ static int cz_probe(struct platform_device *pdev)
>{
>   int ret;
>   struct snd_soc_card *card;
> +   struct acp_platform_info *machine;

> +   machine = devm_kzalloc(>dev, sizeof(struct
acp_platform_info),
> +  GFP_KERNEL);
> +   if (!machine)
> +   return -ENOMEM;
>   card = _card;
>   cz_card.dev = >dev;
>   platform_set_drvdata(pdev, card);
> +   snd_soc_card_set_drvdata(card, machine);
>   ret = devm_snd_soc_register_card(>dev, _card);
>   if (ret) {
>   dev_err(>dev,
> @@ -277,6 +299,7 @@ static int cz_probe(struct platform_device *pdev)
>   cz_card.name, ret);
>   return ret;
>   }
> +   bt_pad_enable = device_property_read_bool(>dev,
"bt-pad-enable");
>   return 0;
>}

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index ec9cab3..2ea103a 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -37,12 +37,14 @@
>#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
>#define MIN_BUFFER MAX_BUFFER

> -#define ST_PLAYBACK_MAX_PERIOD_SIZE 8192
> +#define ST_PLAYBACK_MAX_PERIOD_SIZE 4096
>#define ST_CAPTURE_MAX_PERIOD_SIZE  ST_PLAYBACK_MAX_PERIOD_SIZE
>#define ST_MAX_BUFFER (ST_PLAYBACK_MAX_PERIOD_SIZE *

Re: [PATCH V3 10/10] ASoC: amd: dma driver changes for bt i2s instance

2018-05-02 Thread Daniel Kurtz
Some checkpatch nits below...

On Tue, May 1, 2018 at 2:53 PM Vijendar Mukunda 
wrote:

> With in ACP, There are three I2S controllers can be
> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> Default enabled I2S controller instance is I2S SP.
> This patch provides required changes to support I2S BT
> controller Instance.

> Signed-off-by: Vijendar Mukunda 
> ---
> v1->v2: defined i2s instance macros in acp header file
> v2->v3: sqaushed previous patch series and spilt changes
>   into multiple patches (acp dma driver code cleanup
>   patches and bt i2s instance specific changes)
>sound/soc/amd/acp-da7219-max98357a.c |  23 
>sound/soc/amd/acp-pcm-dma.c  | 256
+++
>sound/soc/amd/acp.h  |  40 ++
>3 files changed, 262 insertions(+), 57 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index 133139d..b3184ab 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -36,6 +36,7 @@
>#include 
>#include 

> +#include "acp.h"
>#include "../codecs/da7219.h"
>#include "../codecs/da7219-aad.h"

> @@ -44,6 +45,7 @@

>static struct snd_soc_jack cz_jack;
>static struct clk *da7219_dai_clk;
> +extern int bt_pad_enable;

WARNING: externs should be avoided in .c files


>static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
>{
> @@ -132,6 +134,9 @@ static const struct snd_pcm_hw_constraint_list
constraints_channels = {
>static int cz_da7219_startup(struct snd_pcm_substream *substream)
>{
>   struct snd_pcm_runtime *runtime = substream->runtime;
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);

>   /*
>* On this platform for PCM device we support stereo
> @@ -143,6 +148,7 @@ static int cz_da7219_startup(struct snd_pcm_substream
*substream)
>   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
>  _rates);

> +   machine->i2s_instance = I2S_BT_INSTANCE;

I'm not a big fan of this approach, but I don't know any other way to tell
a single "platform" driver (acp-pcm-dma) which of two channels (ST/BT) to
use via the pcm_open() callback.

Mark, can you recommend any other way of doing this?

>   return da7219_clk_enable(substream);
>}

> @@ -153,6 +159,11 @@ static void cz_da7219_shutdown(struct
snd_pcm_substream *substream)

>static int cz_max_startup(struct snd_pcm_substream *substream)
>{
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);
> +
> +   machine->i2s_instance = I2S_SP_INSTANCE;
>   return da7219_clk_enable(substream);
>}

> @@ -163,6 +174,11 @@ static void cz_max_shutdown(struct snd_pcm_substream
*substream)

>static int cz_dmic_startup(struct snd_pcm_substream *substream)
>{
> +   struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +   struct snd_soc_card *card = rtd->card;
> +   struct acp_platform_info *machine =
snd_soc_card_get_drvdata(card);
> +
> +   machine->i2s_instance = I2S_SP_INSTANCE;
>   return da7219_clk_enable(substream);
>}

> @@ -266,10 +282,16 @@ static int cz_probe(struct platform_device *pdev)
>{
>   int ret;
>   struct snd_soc_card *card;
> +   struct acp_platform_info *machine;

> +   machine = devm_kzalloc(>dev, sizeof(struct
acp_platform_info),
> +  GFP_KERNEL);
> +   if (!machine)
> +   return -ENOMEM;
>   card = _card;
>   cz_card.dev = >dev;
>   platform_set_drvdata(pdev, card);
> +   snd_soc_card_set_drvdata(card, machine);
>   ret = devm_snd_soc_register_card(>dev, _card);
>   if (ret) {
>   dev_err(>dev,
> @@ -277,6 +299,7 @@ static int cz_probe(struct platform_device *pdev)
>   cz_card.name, ret);
>   return ret;
>   }
> +   bt_pad_enable = device_property_read_bool(>dev,
"bt-pad-enable");
>   return 0;
>}

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index ec9cab3..2ea103a 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -37,12 +37,14 @@
>#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
>#define MIN_BUFFER MAX_BUFFER

> -#define ST_PLAYBACK_MAX_PERIOD_SIZE 8192
> +#define ST_PLAYBACK_MAX_PERIOD_SIZE 4096
>#define ST_CAPTURE_MAX_PERIOD_SIZE  ST_PLAYBACK_MAX_PERIOD_SIZE
>#define ST_MAX_BUFFER (ST_PLAYBACK_MAX_PERIOD_SIZE *
PLAYBACK_MAX_NUM_PERIODS)
>#define ST_MIN_BUFFER ST_MAX_BUFFER


Re: [PATCH 09/11] ASoC: AMD: Fix clocks in CZ DA7219 machine driver

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:17 AM Vijendar Mukunda <vijendar.muku...@amd.com>
wrote:

> From: Akshu Agrawal <akshu.agra...@amd.com>

> System clock on the platform is 25Mhz and not 24Mhz.

> PLL_OUT for da7219 codec to use DA7219_PLL_FREQ_OUT_98304
> as it is for 48KHz SR.

> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>

Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 5 ++---
>   1 file changed, 2 insertions(+), 3 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index 6495eed..fa5ad5b 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -39,8 +39,7 @@
>   #include "../codecs/da7219.h"
>   #include "../codecs/da7219-aad.h"

> -#define CZ_PLAT_CLK 2400
> -#define MCLK_RATE 24576000
> +#define CZ_PLAT_CLK 2500
>   #define DUAL_CHANNEL   2

>   static struct snd_soc_jack cz_jack;
> @@ -63,7 +62,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  }

>  ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
> - CZ_PLAT_CLK, MCLK_RATE);
> + CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);
>  if (ret < 0) {
>  dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
>  return ret;
> --
> 2.7.4


Re: [PATCH 09/11] ASoC: AMD: Fix clocks in CZ DA7219 machine driver

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:17 AM Vijendar Mukunda 
wrote:

> From: Akshu Agrawal 

> System clock on the platform is 25Mhz and not 24Mhz.

> PLL_OUT for da7219 codec to use DA7219_PLL_FREQ_OUT_98304
> as it is for 48KHz SR.

> Signed-off-by: Akshu Agrawal 
> Signed-off-by: Vijendar Mukunda 

Reviewed-by: Daniel Kurtz 

> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 5 ++---
>   1 file changed, 2 insertions(+), 3 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index 6495eed..fa5ad5b 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -39,8 +39,7 @@
>   #include "../codecs/da7219.h"
>   #include "../codecs/da7219-aad.h"

> -#define CZ_PLAT_CLK 2400
> -#define MCLK_RATE 24576000
> +#define CZ_PLAT_CLK 2500
>   #define DUAL_CHANNEL   2

>   static struct snd_soc_jack cz_jack;
> @@ -63,7 +62,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  }

>  ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
> - CZ_PLAT_CLK, MCLK_RATE);
> + CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);
>  if (ret < 0) {
>  dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
>  return ret;
> --
> 2.7.4


Re: [PATCH 10/11] ASoC: AMD: Add const to snd_soc_ops instances

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:18 AM Vijendar Mukunda <vijendar.muku...@amd.com>
wrote:

> From: Akshu Agrawal <akshu.agra...@amd.com>

> Marking snd_soc_ops instances const

> Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>

Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index fa5ad5b..133139d 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -171,17 +171,17 @@ static void cz_dmic_shutdown(struct
snd_pcm_substream *substream)
>  da7219_clk_disable();
>   }

> -static struct snd_soc_ops cz_da7219_cap_ops = {
> +static const struct snd_soc_ops cz_da7219_cap_ops = {
>  .startup = cz_da7219_startup,
>  .shutdown = cz_da7219_shutdown,
>   };

> -static struct snd_soc_ops cz_max_play_ops = {
> +static const struct snd_soc_ops cz_max_play_ops = {
>  .startup = cz_max_startup,
>  .shutdown = cz_max_shutdown,
>   };

> -static struct snd_soc_ops cz_dmic_cap_ops = {
> +static const struct snd_soc_ops cz_dmic_cap_ops = {
>  .startup = cz_dmic_startup,
>  .shutdown = cz_dmic_shutdown,
>   };
> --
> 2.7.4


Re: [PATCH 10/11] ASoC: AMD: Add const to snd_soc_ops instances

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:18 AM Vijendar Mukunda 
wrote:

> From: Akshu Agrawal 

> Marking snd_soc_ops instances const

> Signed-off-by: Akshu Agrawal 
> Signed-off-by: Vijendar Mukunda 

Reviewed-by: Daniel Kurtz 

> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index fa5ad5b..133139d 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -171,17 +171,17 @@ static void cz_dmic_shutdown(struct
snd_pcm_substream *substream)
>  da7219_clk_disable();
>   }

> -static struct snd_soc_ops cz_da7219_cap_ops = {
> +static const struct snd_soc_ops cz_da7219_cap_ops = {
>  .startup = cz_da7219_startup,
>  .shutdown = cz_da7219_shutdown,
>   };

> -static struct snd_soc_ops cz_max_play_ops = {
> +static const struct snd_soc_ops cz_max_play_ops = {
>  .startup = cz_max_startup,
>  .shutdown = cz_max_shutdown,
>   };

> -static struct snd_soc_ops cz_dmic_cap_ops = {
> +static const struct snd_soc_ops cz_dmic_cap_ops = {
>  .startup = cz_dmic_startup,
>  .shutdown = cz_dmic_shutdown,
>   };
> --
> 2.7.4


Re: [PATCH 02/11] ASoC: amd: dma config parameters changes

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,

On Thu, Apr 26, 2018 at 5:14 AM Vijendar Mukunda 
wrote:

> Added dma configuration parameters to rtd structure.
> Moved dma configuration parameters intialization to
> hw_params callback.
> Removed hard coding in prepare and trigger callbacks.

> Signed-off-by: Vijendar Mukunda 
> ---
>sound/soc/amd/acp-pcm-dma.c | 97
+
>sound/soc/amd/acp.h |  5 +++
>2 files changed, 41 insertions(+), 61 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 9c026c4..f18ed9a 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -321,19 +321,12 @@ static void config_acp_dma(void __iomem *acp_mmio,
>  u32 asic_type)
>{
>   u32 pte_offset, sram_bank;
> -   u16 ch1, ch2, destination, dma_dscr_idx;

>   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
>   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
>   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   destination = TO_ACP_I2S_1;
> -
>   } else {
>   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;

Wait... since this is the capture stream, shouldn't the channels have been:

ch1 = ACP_TO_SYSRAM_CH_NUM; /* 14 */
ch2 = I2S_TO_ACP_DMA_CH_NUM; /* 15 */

Is this an existing bug?  Why does everything still work if these are wrong?

>   switch (asic_type) {
>   case CHIP_STONEY:
>   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> @@ -341,30 +334,19 @@ static void config_acp_dma(void __iomem *acp_mmio,
>   default:
>   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
>   }
> -   destination = FROM_ACP_I2S_1;
>   }
> -
>   acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
>  pte_offset);
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -
>   /* Configure System memory <-> ACP SRAM DMA descriptors */
>   set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, pte_offset, ch1,
> -  sram_bank, dma_dscr_idx,
asic_type);
> -
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15;
> +  rtd->direction, pte_offset,
> +  rtd->ch1, sram_bank,
> +  rtd->dma_dscr_idx_1, asic_type);
>   /* Configure ACP SRAM <-> I2S DMA descriptors */
>   set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
>  rtd->direction, sram_bank,
> -  destination, ch2, dma_dscr_idx,
> -  asic_type);
> +  rtd->destination, rtd->ch2,
> +  rtd->dma_dscr_idx_2, asic_type);
>}

>/* Start a given DMA channel transfer */
> @@ -804,6 +786,21 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>   acp_reg_write(val, adata->acp_mmio,
> mmACP_I2S_16BIT_RESOLUTION_EN);
>   }
> +
> +   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +   rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
> +   rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->destination = TO_ACP_I2S_1;
> +   rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
> +   rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> +   } else {
> +   rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
> +   rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->destination = FROM_ACP_I2S_1;
> +   rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
> +   rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
> +   }
> +

I think you should do this initialization in acp_dma_open(), where the
audio_substream_data is kzalloc'ed and otherwise initialized to match the
provided snd_pcm_substream.

>   size = params_buffer_bytes(params);
>   status = snd_pcm_lib_malloc_pages(substream, size);
>   if (status < 0)
> @@ -898,21 +895,15 @@ static int acp_dma_prepare(struct snd_pcm_substream
*substream)

>   if (!rtd)
>   return -EINVAL;
> -  

Re: [PATCH 02/11] ASoC: amd: dma config parameters changes

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,

On Thu, Apr 26, 2018 at 5:14 AM Vijendar Mukunda 
wrote:

> Added dma configuration parameters to rtd structure.
> Moved dma configuration parameters intialization to
> hw_params callback.
> Removed hard coding in prepare and trigger callbacks.

> Signed-off-by: Vijendar Mukunda 
> ---
>sound/soc/amd/acp-pcm-dma.c | 97
+
>sound/soc/amd/acp.h |  5 +++
>2 files changed, 41 insertions(+), 61 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 9c026c4..f18ed9a 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -321,19 +321,12 @@ static void config_acp_dma(void __iomem *acp_mmio,
>  u32 asic_type)
>{
>   u32 pte_offset, sram_bank;
> -   u16 ch1, ch2, destination, dma_dscr_idx;

>   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
>   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
>   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   destination = TO_ACP_I2S_1;
> -
>   } else {
>   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;

Wait... since this is the capture stream, shouldn't the channels have been:

ch1 = ACP_TO_SYSRAM_CH_NUM; /* 14 */
ch2 = I2S_TO_ACP_DMA_CH_NUM; /* 15 */

Is this an existing bug?  Why does everything still work if these are wrong?

>   switch (asic_type) {
>   case CHIP_STONEY:
>   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> @@ -341,30 +334,19 @@ static void config_acp_dma(void __iomem *acp_mmio,
>   default:
>   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
>   }
> -   destination = FROM_ACP_I2S_1;
>   }
> -
>   acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
>  pte_offset);
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -
>   /* Configure System memory <-> ACP SRAM DMA descriptors */
>   set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, pte_offset, ch1,
> -  sram_bank, dma_dscr_idx,
asic_type);
> -
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15;
> +  rtd->direction, pte_offset,
> +  rtd->ch1, sram_bank,
> +  rtd->dma_dscr_idx_1, asic_type);
>   /* Configure ACP SRAM <-> I2S DMA descriptors */
>   set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
>  rtd->direction, sram_bank,
> -  destination, ch2, dma_dscr_idx,
> -  asic_type);
> +  rtd->destination, rtd->ch2,
> +  rtd->dma_dscr_idx_2, asic_type);
>}

>/* Start a given DMA channel transfer */
> @@ -804,6 +786,21 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>   acp_reg_write(val, adata->acp_mmio,
> mmACP_I2S_16BIT_RESOLUTION_EN);
>   }
> +
> +   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +   rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
> +   rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->destination = TO_ACP_I2S_1;
> +   rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
> +   rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> +   } else {
> +   rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
> +   rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->destination = FROM_ACP_I2S_1;
> +   rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
> +   rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
> +   }
> +

I think you should do this initialization in acp_dma_open(), where the
audio_substream_data is kzalloc'ed and otherwise initialized to match the
provided snd_pcm_substream.

>   size = params_buffer_bytes(params);
>   status = snd_pcm_lib_malloc_pages(substream, size);
>   if (status < 0)
> @@ -898,21 +895,15 @@ static int acp_dma_prepare(struct snd_pcm_substream
*substream)

>   if (!rtd)
>   return -EINVAL;
> -   if (substream->stream == 

Re: [PATCH 05/11] ASoC: amd: pte offset related dma driver changes

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:16 AM Vijendar Mukunda 
wrote:

> Added pte offset variable in audio_substream_data structure.
> Added Stoney related PTE offset macros in acp header file.
> Modified hw_params callback to assign the pte offset value
> based on asic_type.

> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-pcm-dma.c | 26 +++---
>   sound/soc/amd/acp.h |  5 +
>   2 files changed, 24 insertions(+), 7 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 5f34be1..cb22653 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -320,13 +320,11 @@ static void config_acp_dma(void __iomem *acp_mmio,
> struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 pte_offset, sram_bank;
> +   u32 sram_bank;

> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
> -   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> +   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
>  sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   } else {
> -   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   else {
>  switch (asic_type) {
>  case CHIP_STONEY:
>  sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> @@ -336,10 +334,10 @@ static void config_acp_dma(void __iomem *acp_mmio,
>  }
>  }
>  acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> -  pte_offset);
> +  rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
>  set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, pte_offset,
> +  rtd->direction, rtd->pte_offset,
> rtd->ch1, sram_bank,
> rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
> @@ -788,6 +786,13 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  }

>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +   switch (adata->asic_type) {
> +   case CHIP_STONEY:
> +   rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET;
> +   break;
> +   default:
> +   rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> +   }

As in patch 2, I believe this would be better done in acp_dma_open().

Why does Stoney use a different PTE_OFFSET?  Please answer this question in
the commit message.

-Dan

>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = TO_ACP_I2S_1;
> @@ -797,6 +802,13 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH;
>  rtd->byte_cnt_low_reg_offset =
mmACP_I2S_TRANSMIT_BYTE_CNT_LOW;
>  } else {
> +   switch (adata->asic_type) {
> +   case CHIP_STONEY:
> +   rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
> +   break;
> +   default:
> +   rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = FROM_ACP_I2S_1;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 82470bc..2f48d1d 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -10,6 +10,10 @@
>   #define ACP_PLAYBACK_PTE_OFFSET10
>   #define ACP_CAPTURE_PTE_OFFSET 0

> +/* Playback and Capture Offset for Stoney */
> +#define ACP_ST_PLAYBACK_PTE_OFFSET 0x04
> +#define ACP_ST_CAPTURE_PTE_OFFSET  0x00
> +
>   #define ACP_GARLIC_CNTL_DEFAULT0x0FB4
>   #define ACP_ONION_CNTL_DEFAULT 0x0FB4

> @@ -90,6 +94,7 @@ struct audio_substream_data {
>  u16 destination;
>  u16 dma_dscr_idx_1;
>  u16 dma_dscr_idx_2;
> +   u32 pte_offset;
>  u32 byte_cnt_high_reg_offset;
>  u32 byte_cnt_low_reg_offset;
>  uint64_t size;
> --
> 2.7.4


Re: [PATCH 06/11] ASoC: amd: sram bank update changes

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:16 AM Vijendar Mukunda <vijendar.muku...@amd.com>
wrote:

> Added sram bank variable to audio_substream_data structure.

> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>

Move initialization to acp_dma_open(), otherwise this is:
Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
>   sound/soc/amd/acp-pcm-dma.c | 20 +---
>   sound/soc/amd/acp.h | 20 ++--
>   2 files changed, 19 insertions(+), 21 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index cb22653..b7bffc7 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -320,29 +320,16 @@ static void config_acp_dma(void __iomem *acp_mmio,
> struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 sram_bank;
> -
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   else {
> -   switch (asic_type) {
> -   case CHIP_STONEY:
> -   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> -   break;
> -   default:
> -   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
> -   }
> -   }
>  acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
>  set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> rtd->direction, rtd->pte_offset,
> -  rtd->ch1, sram_bank,
> +  rtd->ch1, rtd->sram_bank,
> rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
>  set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, sram_bank,
> +  rtd->direction, rtd->sram_bank,
> rtd->destination, rtd->ch2,
> rtd->dma_dscr_idx_2, asic_type);
>   }
> @@ -795,6 +782,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream
*substream,
>  }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS;
>  rtd->destination = TO_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
>  rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> @@ -805,9 +793,11 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  switch (adata->asic_type) {
>  case CHIP_STONEY:
>  rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
> +   rtd->sram_bank = ACP_SRAM_BANK_2_ADDRESS;
>  break;
>  default:
>  rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   rtd->sram_bank = ACP_SRAM_BANK_5_ADDRESS;
>  }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 2f48d1d..62695ed 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -19,12 +19,19 @@

>   #define ACP_PHYSICAL_BASE  0x14000

> -/* Playback SRAM address (as a destination in dma descriptor) */
> -#define ACP_SHARED_RAM_BANK_1_ADDRESS  0x4002000
> -
> -/* Capture SRAM address (as a source in dma descriptor) */
> -#define ACP_SHARED_RAM_BANK_5_ADDRESS  0x400A000
> -#define ACP_SHARED_RAM_BANK_3_ADDRESS  0x4006000
> +/*
> + * In case of I2S SP controller instance, Stoney uses SRAM bank 1 for
> + * playback and SRAM Bank 2 for capture where as in case of BT I2S
> + * Instance, Stoney uses SRAM Bank 3 for playback & SRAM Bank 4 will
> + * be used for capture. Carrizo uses I2S SP controller instance. SRAM
Banks
> + * 1, 2, 3, 4 will be used for playback & SRAM Banks 5, 6, 7, 8 will be
used
> + * for capture scenario.
> + */
> +#define ACP_SRAM_BANK_1_ADDRESS0x4002000
> +#define ACP_SRAM_BANK_2_ADDRESS0x4004000
> +#define ACP_SRAM_BANK_3_ADDRESS0x4006000
> +#define ACP_SRAM_BANK_4_ADDRESS0x4008000
> +#define ACP_SRAM_BANK_5_ADDRE

Re: [PATCH 05/11] ASoC: amd: pte offset related dma driver changes

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:16 AM Vijendar Mukunda 
wrote:

> Added pte offset variable in audio_substream_data structure.
> Added Stoney related PTE offset macros in acp header file.
> Modified hw_params callback to assign the pte offset value
> based on asic_type.

> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-pcm-dma.c | 26 +++---
>   sound/soc/amd/acp.h |  5 +
>   2 files changed, 24 insertions(+), 7 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 5f34be1..cb22653 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -320,13 +320,11 @@ static void config_acp_dma(void __iomem *acp_mmio,
> struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 pte_offset, sram_bank;
> +   u32 sram_bank;

> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
> -   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> +   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
>  sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   } else {
> -   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   else {
>  switch (asic_type) {
>  case CHIP_STONEY:
>  sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> @@ -336,10 +334,10 @@ static void config_acp_dma(void __iomem *acp_mmio,
>  }
>  }
>  acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> -  pte_offset);
> +  rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
>  set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, pte_offset,
> +  rtd->direction, rtd->pte_offset,
> rtd->ch1, sram_bank,
> rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
> @@ -788,6 +786,13 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  }

>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +   switch (adata->asic_type) {
> +   case CHIP_STONEY:
> +   rtd->pte_offset = ACP_ST_PLAYBACK_PTE_OFFSET;
> +   break;
> +   default:
> +   rtd->pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> +   }

As in patch 2, I believe this would be better done in acp_dma_open().

Why does Stoney use a different PTE_OFFSET?  Please answer this question in
the commit message.

-Dan

>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = TO_ACP_I2S_1;
> @@ -797,6 +802,13 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH;
>  rtd->byte_cnt_low_reg_offset =
mmACP_I2S_TRANSMIT_BYTE_CNT_LOW;
>  } else {
> +   switch (adata->asic_type) {
> +   case CHIP_STONEY:
> +   rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
> +   break;
> +   default:
> +   rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = FROM_ACP_I2S_1;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 82470bc..2f48d1d 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -10,6 +10,10 @@
>   #define ACP_PLAYBACK_PTE_OFFSET10
>   #define ACP_CAPTURE_PTE_OFFSET 0

> +/* Playback and Capture Offset for Stoney */
> +#define ACP_ST_PLAYBACK_PTE_OFFSET 0x04
> +#define ACP_ST_CAPTURE_PTE_OFFSET  0x00
> +
>   #define ACP_GARLIC_CNTL_DEFAULT0x0FB4
>   #define ACP_ONION_CNTL_DEFAULT 0x0FB4

> @@ -90,6 +94,7 @@ struct audio_substream_data {
>  u16 destination;
>  u16 dma_dscr_idx_1;
>  u16 dma_dscr_idx_2;
> +   u32 pte_offset;
>  u32 byte_cnt_high_reg_offset;
>  u32 byte_cnt_low_reg_offset;
>  uint64_t size;
> --
> 2.7.4


Re: [PATCH 06/11] ASoC: amd: sram bank update changes

2018-04-29 Thread Daniel Kurtz
On Thu, Apr 26, 2018 at 5:16 AM Vijendar Mukunda 
wrote:

> Added sram bank variable to audio_substream_data structure.

> Signed-off-by: Vijendar Mukunda 

Move initialization to acp_dma_open(), otherwise this is:
Reviewed-by: Daniel Kurtz 

> ---
>   sound/soc/amd/acp-pcm-dma.c | 20 +---
>   sound/soc/amd/acp.h | 20 ++--
>   2 files changed, 19 insertions(+), 21 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index cb22653..b7bffc7 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -320,29 +320,16 @@ static void config_acp_dma(void __iomem *acp_mmio,
> struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 sram_bank;
> -
> -   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   else {
> -   switch (asic_type) {
> -   case CHIP_STONEY:
> -   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> -   break;
> -   default:
> -   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
> -   }
> -   }
>  acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
>  set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> rtd->direction, rtd->pte_offset,
> -  rtd->ch1, sram_bank,
> +  rtd->ch1, rtd->sram_bank,
> rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
>  set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
> -  rtd->direction, sram_bank,
> +  rtd->direction, rtd->sram_bank,
> rtd->destination, rtd->ch2,
> rtd->dma_dscr_idx_2, asic_type);
>   }
> @@ -795,6 +782,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream
*substream,
>  }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> +   rtd->sram_bank = ACP_SRAM_BANK_1_ADDRESS;
>  rtd->destination = TO_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
>  rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> @@ -805,9 +793,11 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  switch (adata->asic_type) {
>  case CHIP_STONEY:
>  rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
> +   rtd->sram_bank = ACP_SRAM_BANK_2_ADDRESS;
>  break;
>  default:
>  rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
> +   rtd->sram_bank = ACP_SRAM_BANK_5_ADDRESS;
>  }
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 2f48d1d..62695ed 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -19,12 +19,19 @@

>   #define ACP_PHYSICAL_BASE  0x14000

> -/* Playback SRAM address (as a destination in dma descriptor) */
> -#define ACP_SHARED_RAM_BANK_1_ADDRESS  0x4002000
> -
> -/* Capture SRAM address (as a source in dma descriptor) */
> -#define ACP_SHARED_RAM_BANK_5_ADDRESS  0x400A000
> -#define ACP_SHARED_RAM_BANK_3_ADDRESS  0x4006000
> +/*
> + * In case of I2S SP controller instance, Stoney uses SRAM bank 1 for
> + * playback and SRAM Bank 2 for capture where as in case of BT I2S
> + * Instance, Stoney uses SRAM Bank 3 for playback & SRAM Bank 4 will
> + * be used for capture. Carrizo uses I2S SP controller instance. SRAM
Banks
> + * 1, 2, 3, 4 will be used for playback & SRAM Banks 5, 6, 7, 8 will be
used
> + * for capture scenario.
> + */
> +#define ACP_SRAM_BANK_1_ADDRESS0x4002000
> +#define ACP_SRAM_BANK_2_ADDRESS0x4004000
> +#define ACP_SRAM_BANK_3_ADDRESS0x4006000
> +#define ACP_SRAM_BANK_4_ADDRESS0x4008000
> +#define ACP_SRAM_BANK_5_ADDRESS0x400A000

>   #define ACP_DMA_RESET_TIME 1
>   #define ACP_CLOCK_EN_TIME_OUT_VALUE0x00FF
> @@ -95,6 +102,7 @@ struct audio_substream_data {
>  u16 dma_dscr_idx_1;
>  u16 dma_dscr_idx_2;
>  u32 pte_offset;
> +   u32 sram_bank;
>  u32 byte_cnt_high_reg_offset;
>  u32 byte_cnt_low_reg_offset;
>  uint64_t size;
> --
> 2.7.4


Re: [PATCH 04/11] ASoC: amd: removed separate byte count variables for playback and capture

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,

On Thu, Apr 26, 2018 at 5:15 AM Vijendar Mukunda <vijendar.muku...@amd.com>
wrote:

> Removed separate byte count variables for playback and capture.

> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>

Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
>   sound/soc/amd/acp-pcm-dma.c | 19 +--
>   sound/soc/amd/acp.h |  3 +--
>   2 files changed, 6 insertions(+), 16 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 019f696..5f34be1 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -866,13 +866,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct
snd_pcm_substream *substream)
>  buffersize = frames_to_bytes(runtime, runtime->buffer_size);
>  bytescount = acp_get_byte_count(rtd);

> -   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   if (bytescount > rtd->i2ssp_renderbytescount)
> -   bytescount = bytescount -
rtd->i2ssp_renderbytescount;
> -   } else {
> -   if (bytescount > rtd->i2ssp_capturebytescount)
> -   bytescount = bytescount -
rtd->i2ssp_capturebytescount;
> -   }
> +   if (bytescount > rtd->bytescount)
> +   bytescount = bytescount - rtd->bytescount;

nit, this could be:
bytescount -= rtd->bytescount;

>  pos = do_div(bytescount, buffersize);
>  return bytes_to_frames(runtime, pos);
>   }
> @@ -921,9 +916,9 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>  case SNDRV_PCM_TRIGGER_RESUME:
>  bytescount = acp_get_byte_count(rtd);
> +   if (rtd->bytescount == 0)
> +   rtd->bytescount = bytescount;
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   if (rtd->i2ssp_renderbytescount == 0)
> -   rtd->i2ssp_renderbytescount = bytescount;
>  acp_dma_start(rtd->acp_mmio, rtd->ch1, false);
>  while (acp_reg_read(rtd->acp_mmio,
mmACP_DMA_CH_STS) &
>  BIT(rtd->ch1)) {
> @@ -934,9 +929,6 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  }
>  cpu_relax();
>  }
> -   } else {
> -   if (rtd->i2ssp_capturebytescount == 0)
> -   rtd->i2ssp_capturebytescount = bytescount;
>  }
>  acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
>  ret = 0;
> @@ -947,12 +939,11 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  acp_dma_stop(rtd->acp_mmio, rtd->ch1);
>  ret =  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
> -   rtd->i2ssp_renderbytescount = 0;
>  } else {
>  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
>  ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
> -   rtd->i2ssp_capturebytescount = 0;
>  }
> +   rtd->bytescount = 0;
>  break;
>  default:
>  ret = -EINVAL;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 3b076c6..82470bc 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -93,8 +93,7 @@ struct audio_substream_data {
>  u32 byte_cnt_high_reg_offset;
>  u32 byte_cnt_low_reg_offset;
>  uint64_t size;
> -   u64 i2ssp_renderbytescount;
> -   u64 i2ssp_capturebytescount;
> +   u64 bytescount;
>  void __iomem *acp_mmio;
>   };

> --
> 2.7.4


Re: [PATCH 04/11] ASoC: amd: removed separate byte count variables for playback and capture

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,

On Thu, Apr 26, 2018 at 5:15 AM Vijendar Mukunda 
wrote:

> Removed separate byte count variables for playback and capture.

> Signed-off-by: Vijendar Mukunda 

Reviewed-by: Daniel Kurtz 

> ---
>   sound/soc/amd/acp-pcm-dma.c | 19 +--
>   sound/soc/amd/acp.h |  3 +--
>   2 files changed, 6 insertions(+), 16 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 019f696..5f34be1 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -866,13 +866,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct
snd_pcm_substream *substream)
>  buffersize = frames_to_bytes(runtime, runtime->buffer_size);
>  bytescount = acp_get_byte_count(rtd);

> -   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   if (bytescount > rtd->i2ssp_renderbytescount)
> -   bytescount = bytescount -
rtd->i2ssp_renderbytescount;
> -   } else {
> -   if (bytescount > rtd->i2ssp_capturebytescount)
> -   bytescount = bytescount -
rtd->i2ssp_capturebytescount;
> -   }
> +   if (bytescount > rtd->bytescount)
> +   bytescount = bytescount - rtd->bytescount;

nit, this could be:
bytescount -= rtd->bytescount;

>  pos = do_div(bytescount, buffersize);
>  return bytes_to_frames(runtime, pos);
>   }
> @@ -921,9 +916,9 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>  case SNDRV_PCM_TRIGGER_RESUME:
>  bytescount = acp_get_byte_count(rtd);
> +   if (rtd->bytescount == 0)
> +   rtd->bytescount = bytescount;
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   if (rtd->i2ssp_renderbytescount == 0)
> -   rtd->i2ssp_renderbytescount = bytescount;
>  acp_dma_start(rtd->acp_mmio, rtd->ch1, false);
>  while (acp_reg_read(rtd->acp_mmio,
mmACP_DMA_CH_STS) &
>  BIT(rtd->ch1)) {
> @@ -934,9 +929,6 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  }
>  cpu_relax();
>  }
> -   } else {
> -   if (rtd->i2ssp_capturebytescount == 0)
> -   rtd->i2ssp_capturebytescount = bytescount;
>  }
>  acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
>  ret = 0;
> @@ -947,12 +939,11 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  acp_dma_stop(rtd->acp_mmio, rtd->ch1);
>  ret =  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
> -   rtd->i2ssp_renderbytescount = 0;
>  } else {
>  acp_dma_stop(rtd->acp_mmio, rtd->ch2);
>  ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
> -   rtd->i2ssp_capturebytescount = 0;
>  }
> +   rtd->bytescount = 0;
>  break;
>  default:
>  ret = -EINVAL;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 3b076c6..82470bc 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -93,8 +93,7 @@ struct audio_substream_data {
>  u32 byte_cnt_high_reg_offset;
>  u32 byte_cnt_low_reg_offset;
>  uint64_t size;
> -   u64 i2ssp_renderbytescount;
> -   u64 i2ssp_capturebytescount;
> +   u64 bytescount;
>  void __iomem *acp_mmio;
>   };

> --
> 2.7.4


Re: [PATCH 03/11] ASoC: amd: added byte count register offset variables to rtd

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,


On Thu, Apr 26, 2018 at 5:14 AM Vijendar Mukunda <vijendar.muku...@amd.com>
wrote:

> Added byte count register offset variables to audio_substream_data
> structure. Modified dma pointer callback.

> Signed-off-by: Vijendar Mukunda <vijendar.muku...@amd.com>

Please fix the small indentation nits, otherwise this one is:

Reviewed-by: Daniel Kurtz <djku...@chromium.org>

> ---
>   sound/soc/amd/acp-pcm-dma.c | 36 +++-
>   sound/soc/amd/acp.h |  2 ++
>   2 files changed, 17 insertions(+), 21 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index f18ed9a..019f696 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -793,12 +793,18 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  rtd->destination = TO_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
>  rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> +   rtd->byte_cnt_high_reg_offset =
> +   mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH;

Indent relative to line above with 2 tabs.

> +   rtd->byte_cnt_low_reg_offset =
mmACP_I2S_TRANSMIT_BYTE_CNT_LOW;
>  } else {
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = FROM_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
>  rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
> +   rtd->byte_cnt_high_reg_offset =
> +   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;

here too.

> +   rtd->byte_cnt_low_reg_offset =
mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
>  }

>  size = params_buffer_bytes(params);
> @@ -834,26 +840,15 @@ static int acp_dma_hw_free(struct snd_pcm_substream
*substream)
>  return snd_pcm_lib_free_pages(substream);
>   }

> -static u64 acp_get_byte_count(void __iomem *acp_mmio, int stream)
> +static u64 acp_get_byte_count(struct audio_substream_data *rtd)
>   {
> -   union acp_dma_count playback_dma_count;
> -   union acp_dma_count capture_dma_count;
> -   u64 bytescount = 0;
> +   union acp_dma_count byte_count;

> -   if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   playback_dma_count.bcount.high = acp_reg_read(acp_mmio,
> -   mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH);
> -   playback_dma_count.bcount.low  = acp_reg_read(acp_mmio,
> -   mmACP_I2S_TRANSMIT_BYTE_CNT_LOW);
> -   bytescount = playback_dma_count.bytescount;
> -   } else {
> -   capture_dma_count.bcount.high = acp_reg_read(acp_mmio,
> -   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH);
> -   capture_dma_count.bcount.low  = acp_reg_read(acp_mmio,
> -   mmACP_I2S_RECEIVED_BYTE_CNT_LOW);
> -   bytescount = capture_dma_count.bytescount;
> -   }
> -   return bytescount;
> +   byte_count.bcount.high = acp_reg_read(rtd->acp_mmio,
> +
rtd->byte_cnt_high_reg_offset);
> +   byte_count.bcount.low  = acp_reg_read(rtd->acp_mmio,
> +
rtd->byte_cnt_low_reg_offset);
> +   return byte_count.bytescount;
>   }

>   static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream
*substream)
> @@ -869,7 +864,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct
snd_pcm_substream *substream)
>  return -EINVAL;

>  buffersize = frames_to_bytes(runtime, runtime->buffer_size);
> -   bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream);
> +   bytescount = acp_get_byte_count(rtd);

>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  if (bytescount > rtd->i2ssp_renderbytescount)
> @@ -925,8 +920,7 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  case SNDRV_PCM_TRIGGER_START:
>  case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>  case SNDRV_PCM_TRIGGER_RESUME:
> -   bytescount = acp_get_byte_count(rtd->acp_mmio,
> -   substream->stream);
> +   bytescount = acp_get_byte_count(rtd);
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  if (rtd->i2ssp_renderbytescount == 0)
>  rtd->i2ssp_renderbytescount = bytescount;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 5e25428..3b076c6 100644
> --- a/sound/s

Re: [PATCH 03/11] ASoC: amd: added byte count register offset variables to rtd

2018-04-29 Thread Daniel Kurtz
Hi Vijendar,


On Thu, Apr 26, 2018 at 5:14 AM Vijendar Mukunda 
wrote:

> Added byte count register offset variables to audio_substream_data
> structure. Modified dma pointer callback.

> Signed-off-by: Vijendar Mukunda 

Please fix the small indentation nits, otherwise this one is:

Reviewed-by: Daniel Kurtz 

> ---
>   sound/soc/amd/acp-pcm-dma.c | 36 +++-
>   sound/soc/amd/acp.h |  2 ++
>   2 files changed, 17 insertions(+), 21 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index f18ed9a..019f696 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -793,12 +793,18 @@ static int acp_dma_hw_params(struct
snd_pcm_substream *substream,
>  rtd->destination = TO_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = PLAYBACK_START_DMA_DESCR_CH12;
>  rtd->dma_dscr_idx_2 = PLAYBACK_START_DMA_DESCR_CH13;
> +   rtd->byte_cnt_high_reg_offset =
> +   mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH;

Indent relative to line above with 2 tabs.

> +   rtd->byte_cnt_low_reg_offset =
mmACP_I2S_TRANSMIT_BYTE_CNT_LOW;
>  } else {
>  rtd->ch1 = SYSRAM_TO_ACP_CH_NUM;
>  rtd->ch2 = ACP_TO_I2S_DMA_CH_NUM;
>  rtd->destination = FROM_ACP_I2S_1;
>  rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
>  rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
> +   rtd->byte_cnt_high_reg_offset =
> +   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;

here too.

> +   rtd->byte_cnt_low_reg_offset =
mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
>  }

>  size = params_buffer_bytes(params);
> @@ -834,26 +840,15 @@ static int acp_dma_hw_free(struct snd_pcm_substream
*substream)
>  return snd_pcm_lib_free_pages(substream);
>   }

> -static u64 acp_get_byte_count(void __iomem *acp_mmio, int stream)
> +static u64 acp_get_byte_count(struct audio_substream_data *rtd)
>   {
> -   union acp_dma_count playback_dma_count;
> -   union acp_dma_count capture_dma_count;
> -   u64 bytescount = 0;
> +   union acp_dma_count byte_count;

> -   if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> -   playback_dma_count.bcount.high = acp_reg_read(acp_mmio,
> -   mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH);
> -   playback_dma_count.bcount.low  = acp_reg_read(acp_mmio,
> -   mmACP_I2S_TRANSMIT_BYTE_CNT_LOW);
> -   bytescount = playback_dma_count.bytescount;
> -   } else {
> -   capture_dma_count.bcount.high = acp_reg_read(acp_mmio,
> -   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH);
> -   capture_dma_count.bcount.low  = acp_reg_read(acp_mmio,
> -   mmACP_I2S_RECEIVED_BYTE_CNT_LOW);
> -   bytescount = capture_dma_count.bytescount;
> -   }
> -   return bytescount;
> +   byte_count.bcount.high = acp_reg_read(rtd->acp_mmio,
> +
rtd->byte_cnt_high_reg_offset);
> +   byte_count.bcount.low  = acp_reg_read(rtd->acp_mmio,
> +
rtd->byte_cnt_low_reg_offset);
> +   return byte_count.bytescount;
>   }

>   static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream
*substream)
> @@ -869,7 +864,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct
snd_pcm_substream *substream)
>  return -EINVAL;

>  buffersize = frames_to_bytes(runtime, runtime->buffer_size);
> -   bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream);
> +   bytescount = acp_get_byte_count(rtd);

>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  if (bytescount > rtd->i2ssp_renderbytescount)
> @@ -925,8 +920,7 @@ static int acp_dma_trigger(struct snd_pcm_substream
*substream, int cmd)
>  case SNDRV_PCM_TRIGGER_START:
>  case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>  case SNDRV_PCM_TRIGGER_RESUME:
> -   bytescount = acp_get_byte_count(rtd->acp_mmio,
> -   substream->stream);
> +   bytescount = acp_get_byte_count(rtd);
>  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>  if (rtd->i2ssp_renderbytescount == 0)
>  rtd->i2ssp_renderbytescount = bytescount;
> diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
> index 5e25428..3b076c6 100644
> --- a/sound/soc/amd/acp.h
> +++ b/sound/soc/amd/acp.h
> @@ -90,6 +90,8 @@ struct audio_substream_data {
>  u16 destination;
>  u16 dma_dscr_idx_1;
>  u16 dma_dscr_idx_2;
> +   u32 byte_cnt_high_reg_offset;
> +   u32 byte_cnt_low_reg_offset;
>  uint64_t size;
>  u64 i2ssp_renderbytescount;
>  u64 i2ssp_capturebytescount;
> --
> 2.7.4


Re: [PATCH 2/3] ASoC: AMD: Move clk enable from hw_params/free to startup/shutdown

2018-04-24 Thread Daniel Kurtz
On Mon, Apr 23, 2018 at 9:03 PM Vijendar Mukunda 
wrote:

> From: Akshu Agrawal 

> hw_param can be called multiple times and thus we can have
> more clk enable. The clk may not get diabled due to refcounting.
> startup/shutdown ensures single clk enable/disable call.

> Signed-off-by: Akshu Agrawal 
> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 54

>   1 file changed, 37 insertions(+), 17 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index b205c78..0f16f6d 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -38,8 +38,7 @@
>   #include "../codecs/da7219.h"
>   #include "../codecs/da7219-aad.h"

> -#define CZ_PLAT_CLK 2400
> -#define MCLK_RATE 24576000
> +#define CZ_PLAT_CLK 2500
>   #define DUAL_CHANNEL   2

>   static struct snd_soc_jack cz_jack;
> @@ -62,7 +61,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  }

>  ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
> - CZ_PLAT_CLK, MCLK_RATE);
> + CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);

These are unrelated fixes that should be in their own patch.

>  if (ret < 0) {
>  dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
>  return ret;
> @@ -85,8 +84,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  return 0;
>   }

> -static int cz_da7219_hw_params(struct snd_pcm_substream *substream,
> -struct snd_pcm_hw_params *params)
> +static int da7219_clk_enable(struct snd_pcm_substream *substream)
>   {
>  int ret = 0;
>  struct snd_soc_pcm_runtime *rtd = substream->private_data;
> @@ -100,11 +98,9 @@ static int cz_da7219_hw_params(struct
snd_pcm_substream *substream,
>  return ret;
>   }

> -static int cz_da7219_hw_free(struct snd_pcm_substream *substream)
> +static void da7219_clk_disable(void)
>   {
>  clk_disable_unprepare(da7219_dai_clk);
> -
> -   return 0;
>   }

>   static const unsigned int channels[] = {
> @@ -127,7 +123,7 @@ static const struct snd_pcm_hw_constraint_list
constraints_channels = {
>  .mask = 0,
>   };

> -static int cz_fe_startup(struct snd_pcm_substream *substream)
> +static int cz_da7219_startup(struct snd_pcm_substream *substream)
>   {
>  struct snd_pcm_runtime *runtime = substream->runtime;

> @@ -141,23 +137,47 @@ static int cz_fe_startup(struct snd_pcm_substream
*substream)
>  snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> _rates);

> -   return 0;
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
> +}
> +
> +static int cz_max_startup(struct snd_pcm_substream *substream)
> +{
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_max_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
> +}
> +
> +static int cz_dmic_startup(struct snd_pcm_substream *substream)
> +{
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
>   }

This is ok, or you could combine the common cz_max_* & cz_dmic_*.


>   static struct snd_soc_ops cz_da7219_cap_ops = {

I think these should all be "static const struct snd_soc_ops"  (please fix
in a separate patch).

> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> -   .startup = cz_fe_startup,
> +   .startup = cz_da7219_startup,
> +   .shutdown = cz_da7219_shutdown,
>   };

>   static struct snd_soc_ops cz_max_play_ops = {
> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> +   .startup = cz_max_startup,
> +   .shutdown = cz_max_shutdown,
>   };

>   static struct snd_soc_ops cz_dmic_cap_ops = {
> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> +   .startup = cz_dmic_startup,
> +   .shutdown = cz_dmic_shutdown,
>   };

>   static struct snd_soc_dai_link cz_dai_7219_98357[] = {
> --
> 2.7.4


Re: [PATCH 2/3] ASoC: AMD: Move clk enable from hw_params/free to startup/shutdown

2018-04-24 Thread Daniel Kurtz
On Mon, Apr 23, 2018 at 9:03 PM Vijendar Mukunda 
wrote:

> From: Akshu Agrawal 

> hw_param can be called multiple times and thus we can have
> more clk enable. The clk may not get diabled due to refcounting.
> startup/shutdown ensures single clk enable/disable call.

> Signed-off-by: Akshu Agrawal 
> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-da7219-max98357a.c | 54

>   1 file changed, 37 insertions(+), 17 deletions(-)

> diff --git a/sound/soc/amd/acp-da7219-max98357a.c
b/sound/soc/amd/acp-da7219-max98357a.c
> index b205c78..0f16f6d 100644
> --- a/sound/soc/amd/acp-da7219-max98357a.c
> +++ b/sound/soc/amd/acp-da7219-max98357a.c
> @@ -38,8 +38,7 @@
>   #include "../codecs/da7219.h"
>   #include "../codecs/da7219-aad.h"

> -#define CZ_PLAT_CLK 2400
> -#define MCLK_RATE 24576000
> +#define CZ_PLAT_CLK 2500
>   #define DUAL_CHANNEL   2

>   static struct snd_soc_jack cz_jack;
> @@ -62,7 +61,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  }

>  ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
> - CZ_PLAT_CLK, MCLK_RATE);
> + CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);

These are unrelated fixes that should be in their own patch.

>  if (ret < 0) {
>  dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
>  return ret;
> @@ -85,8 +84,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime
*rtd)
>  return 0;
>   }

> -static int cz_da7219_hw_params(struct snd_pcm_substream *substream,
> -struct snd_pcm_hw_params *params)
> +static int da7219_clk_enable(struct snd_pcm_substream *substream)
>   {
>  int ret = 0;
>  struct snd_soc_pcm_runtime *rtd = substream->private_data;
> @@ -100,11 +98,9 @@ static int cz_da7219_hw_params(struct
snd_pcm_substream *substream,
>  return ret;
>   }

> -static int cz_da7219_hw_free(struct snd_pcm_substream *substream)
> +static void da7219_clk_disable(void)
>   {
>  clk_disable_unprepare(da7219_dai_clk);
> -
> -   return 0;
>   }

>   static const unsigned int channels[] = {
> @@ -127,7 +123,7 @@ static const struct snd_pcm_hw_constraint_list
constraints_channels = {
>  .mask = 0,
>   };

> -static int cz_fe_startup(struct snd_pcm_substream *substream)
> +static int cz_da7219_startup(struct snd_pcm_substream *substream)
>   {
>  struct snd_pcm_runtime *runtime = substream->runtime;

> @@ -141,23 +137,47 @@ static int cz_fe_startup(struct snd_pcm_substream
*substream)
>  snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> _rates);

> -   return 0;
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
> +}
> +
> +static int cz_max_startup(struct snd_pcm_substream *substream)
> +{
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_max_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
> +}
> +
> +static int cz_dmic_startup(struct snd_pcm_substream *substream)
> +{
> +   return da7219_clk_enable(substream);
> +}
> +
> +static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
> +{
> +   da7219_clk_disable();
>   }

This is ok, or you could combine the common cz_max_* & cz_dmic_*.


>   static struct snd_soc_ops cz_da7219_cap_ops = {

I think these should all be "static const struct snd_soc_ops"  (please fix
in a separate patch).

> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> -   .startup = cz_fe_startup,
> +   .startup = cz_da7219_startup,
> +   .shutdown = cz_da7219_shutdown,
>   };

>   static struct snd_soc_ops cz_max_play_ops = {
> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> +   .startup = cz_max_startup,
> +   .shutdown = cz_max_shutdown,
>   };

>   static struct snd_soc_ops cz_dmic_cap_ops = {
> -   .hw_params = cz_da7219_hw_params,
> -   .hw_free = cz_da7219_hw_free,
> +   .startup = cz_dmic_startup,
> +   .shutdown = cz_dmic_shutdown,
>   };

>   static struct snd_soc_dai_link cz_dai_7219_98357[] = {
> --
> 2.7.4


Re: [PATCH 1/3] ASoC: amd: acp dma driver code cleanup

2018-04-24 Thread Daniel Kurtz
Hi Vijendar,


On Mon, Apr 23, 2018 at 9:02 PM Vijendar Mukunda 
wrote:

> Added dma configuration parameters in audio_substream_data
> structure. Moved dma configuration parameters initialization
> to dma hw params callback.
> Removed separate byte count variables for playback and capture.
> Added variables to store ACP register offsets in audio_substream_data
> structure.

Thanks for splitting the patch, this is moving in the right direction, but
still very difficult to review since it is mixing different changes
together.
Just try to make each patch a single logical cleanup.
For example, perhaps create a set of patches that does:
   (1) Variable renames (eg audio_config -> rtd) & white space cleanup
   (2) Add dma configuration parameters to audio_substream_data structure
and initialize them in hw_params.
   (3) Remove separate byte count variables for playback and capture
   (4) Update the PTE offsets
   (5) Update the SRAM_BANKs

Note that (1) doesn't change functionality at all, (2) refactors but
doesn't change behavior or logic, (3) simplifies behavior but doesn't
change logic, and (4) & (5) build on the others but start making real
logical changes.

-Dan


> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-pcm-dma.c | 241
++--
>   sound/soc/amd/acp.h |  35 +--
>   2 files changed, 126 insertions(+), 150 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 5ffe2ef..4a4bbdf 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -317,54 +317,21 @@ static void acp_pte_config(void __iomem *acp_mmio,
struct page *pg,
>   }

>   static void config_acp_dma(void __iomem *acp_mmio,
> -  struct audio_substream_data *audio_config,
> +  struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 pte_offset, sram_bank;
> -   u16 ch1, ch2, destination, dma_dscr_idx;
> -
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) {
> -   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
> -   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   destination = TO_ACP_I2S_1;
> -
> -   } else {
> -   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
> -   switch (asic_type) {
> -   case CHIP_STONEY:
> -   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> -   break;
> -   default:
> -   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
> -   }
> -   destination = FROM_ACP_I2S_1;
> -   }
> -
> -   acp_pte_config(acp_mmio, audio_config->pg,
audio_config->num_of_pages,
> -  pte_offset);
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -
> +   acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> +  rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
> -   set_acp_sysmem_dma_descriptors(acp_mmio, audio_config->size,
> -  audio_config->direction,
pte_offset, ch1,
> -  sram_bank, dma_dscr_idx,
asic_type);
> -
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15;
> +   set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> +  rtd->direction, rtd->pte_offset,
> +  rtd->ch1, rtd->sram_bank,
> +  rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
> -   set_acp_to_i2s_dma_descriptors(acp_mmio, audio_config->size,
> -  audio_config->direction, sram_bank,
> -  destination, ch2, dma_dscr_idx,
> -  asic_type);
> +   set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
> +  rtd->direction, rtd->sram_bank,
> +  rtd->destination, rtd->ch2,
> +  rtd->dma_dscr_idx_2, asic_type);
>   }

>   /* Start a given DMA channel transfer */
> @@ -700,7 +667,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)

>   static int acp_dma_open(struct snd_pcm_substream *substream)
>   {
> -   u16 bank;
>   

Re: [PATCH 1/3] ASoC: amd: acp dma driver code cleanup

2018-04-24 Thread Daniel Kurtz
Hi Vijendar,


On Mon, Apr 23, 2018 at 9:02 PM Vijendar Mukunda 
wrote:

> Added dma configuration parameters in audio_substream_data
> structure. Moved dma configuration parameters initialization
> to dma hw params callback.
> Removed separate byte count variables for playback and capture.
> Added variables to store ACP register offsets in audio_substream_data
> structure.

Thanks for splitting the patch, this is moving in the right direction, but
still very difficult to review since it is mixing different changes
together.
Just try to make each patch a single logical cleanup.
For example, perhaps create a set of patches that does:
   (1) Variable renames (eg audio_config -> rtd) & white space cleanup
   (2) Add dma configuration parameters to audio_substream_data structure
and initialize them in hw_params.
   (3) Remove separate byte count variables for playback and capture
   (4) Update the PTE offsets
   (5) Update the SRAM_BANKs

Note that (1) doesn't change functionality at all, (2) refactors but
doesn't change behavior or logic, (3) simplifies behavior but doesn't
change logic, and (4) & (5) build on the others but start making real
logical changes.

-Dan


> Signed-off-by: Vijendar Mukunda 
> ---
>   sound/soc/amd/acp-pcm-dma.c | 241
++--
>   sound/soc/amd/acp.h |  35 +--
>   2 files changed, 126 insertions(+), 150 deletions(-)

> diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
> index 5ffe2ef..4a4bbdf 100644
> --- a/sound/soc/amd/acp-pcm-dma.c
> +++ b/sound/soc/amd/acp-pcm-dma.c
> @@ -317,54 +317,21 @@ static void acp_pte_config(void __iomem *acp_mmio,
struct page *pg,
>   }

>   static void config_acp_dma(void __iomem *acp_mmio,
> -  struct audio_substream_data *audio_config,
> +  struct audio_substream_data *rtd,
> u32 asic_type)
>   {
> -   u32 pte_offset, sram_bank;
> -   u16 ch1, ch2, destination, dma_dscr_idx;
> -
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK) {
> -   pte_offset = ACP_PLAYBACK_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
> -   sram_bank = ACP_SHARED_RAM_BANK_1_ADDRESS;
> -   destination = TO_ACP_I2S_1;
> -
> -   } else {
> -   pte_offset = ACP_CAPTURE_PTE_OFFSET;
> -   ch1 = SYSRAM_TO_ACP_CH_NUM;
> -   ch2 = ACP_TO_I2S_DMA_CH_NUM;
> -   switch (asic_type) {
> -   case CHIP_STONEY:
> -   sram_bank = ACP_SHARED_RAM_BANK_3_ADDRESS;
> -   break;
> -   default:
> -   sram_bank = ACP_SHARED_RAM_BANK_5_ADDRESS;
> -   }
> -   destination = FROM_ACP_I2S_1;
> -   }
> -
> -   acp_pte_config(acp_mmio, audio_config->pg,
audio_config->num_of_pages,
> -  pte_offset);
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
> -
> +   acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
> +  rtd->pte_offset);
>  /* Configure System memory <-> ACP SRAM DMA descriptors */
> -   set_acp_sysmem_dma_descriptors(acp_mmio, audio_config->size,
> -  audio_config->direction,
pte_offset, ch1,
> -  sram_bank, dma_dscr_idx,
asic_type);
> -
> -   if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
> -   dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
> -   else
> -   dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15;
> +   set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
> +  rtd->direction, rtd->pte_offset,
> +  rtd->ch1, rtd->sram_bank,
> +  rtd->dma_dscr_idx_1, asic_type);
>  /* Configure ACP SRAM <-> I2S DMA descriptors */
> -   set_acp_to_i2s_dma_descriptors(acp_mmio, audio_config->size,
> -  audio_config->direction, sram_bank,
> -  destination, ch2, dma_dscr_idx,
> -  asic_type);
> +   set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
> +  rtd->direction, rtd->sram_bank,
> +  rtd->destination, rtd->ch2,
> +  rtd->dma_dscr_idx_2, asic_type);
>   }

>   /* Start a given DMA channel transfer */
> @@ -700,7 +667,6 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)

>   static int acp_dma_open(struct snd_pcm_substream *substream)
>   {
> -   u16 bank;
>  int ret = 0;
>  struct snd_pcm_runtime 

Re: [PATCH v2 2/3] ASoC: amd: dma driver changes for BT I2S instance

2018-04-18 Thread Daniel Kurtz
Hi Vijendar,

On Wed, Apr 18, 2018 at 5:02 AM Vijendar Mukunda 
wrote:

> With in ACP, There are three I2S controllers can be
> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> Default enabled I2S controller instance is I2S SP.
> This patch provides required changes to support I2S BT
> controller Instance.

I like the direction this patch is taking, but I think it would be easier
to review if you could split it into 2 parts:
  (1) the cleanup of the existing driver to use a simplified flow for
playback vs capture paths.
  (2) adding the BT I2S channel.


Thanks,
-Dan


Re: [PATCH v2 2/3] ASoC: amd: dma driver changes for BT I2S instance

2018-04-18 Thread Daniel Kurtz
Hi Vijendar,

On Wed, Apr 18, 2018 at 5:02 AM Vijendar Mukunda 
wrote:

> With in ACP, There are three I2S controllers can be
> configured/enabled ( I2S SP, I2S MICSP, I2S BT).
> Default enabled I2S controller instance is I2S SP.
> This patch provides required changes to support I2S BT
> controller Instance.

I like the direction this patch is taking, but I think it would be easier
to review if you could split it into 2 parts:
  (1) the cleanup of the existing driver to use a simplified flow for
playback vs capture paths.
  (2) adding the BT I2S channel.


Thanks,
-Dan


[PATCH] drm/amdgpu/acp: Fix slab-out-of-bounds in mfd_add_device in acp_hw_init

2018-04-13 Thread Daniel Kurtz
Commit 51f7415039d4 ("drm/amd/amdgpu: creating two I2S instances for
stoney/cz") added support for the "BT_I2S" ACP i2s channel.  As part of
this change, one additional acp resource was added, but the "num_resource"
count was accidentally incremented by 2.

This incorrect count eventually causes mfd_add_device() to try to access
an invalid memory address (the location of non-existent resource 5.

This fault was detected by running a KASAN enabled kernel, which produced
the following splat at boot:

[6.612987] 
==
[6.613509] BUG: KASAN: slab-out-of-bounds in mfd_add_device+0x4bc/0x7a7
[6.613509] Read of size 8 at addr 880107d4dc58 by task swapper/0/1
[6.613509]
[6.613509] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.33 #349
[6.613509] Hardware name: Google Grunt/Grunt, BIOS 
Google_Grunt.10543.0.2018_04_03_1812 04/02/2018
[6.613509] Call Trace:
[6.613509]  dump_stack+0x4d/0x63
[6.613509]  print_address_description+0x80/0x2d6
[6.613509]  ? mfd_add_device+0x4bc/0x7a7
[6.613509]  kasan_report+0x255/0x295
[6.613509]  mfd_add_device+0x4bc/0x7a7
[6.613509]  ? kasan_kmalloc+0x99/0xa8
[6.613509]  ? mfd_add_devices+0x58/0xe4
[6.613509]  ? __kmalloc+0x154/0x178
[6.613509]  mfd_add_devices+0xa5/0xe4
[6.613509]  acp_hw_init+0x92e/0xc4a
[6.613509]  amdgpu_device_init+0x1dfb/0x22a2
[6.613509]  ? kmalloc_order+0x53/0x5d
[6.613509]  ? kmalloc_order_trace+0x23/0xb3
[6.613509]  amdgpu_driver_load_kms+0xce/0x267
[6.613509]  drm_dev_register+0x169/0x2fb
[6.613509]  amdgpu_pci_probe+0x217/0x242
[6.613509]  pci_device_probe+0x101/0x18e
[6.613509]  driver_probe_device+0x1dd/0x419
[6.613509]  ? ___might_sleep+0x80/0x1b6
[6.613509]  __driver_attach+0x9f/0xc9
[6.613509]  ? driver_probe_device+0x419/0x419
[6.613509]  bus_for_each_dev+0xbc/0xe1
[6.613509]  bus_add_driver+0x189/0x2c0
[6.613509]  driver_register+0x108/0x156
[6.613509]  ? ttm_init+0x67/0x67
[6.613509]  do_one_initcall+0xb2/0x161
[6.613509]  kernel_init_freeable+0x25a/0x308
[6.613509]  ? rest_init+0xcc/0xcc
[6.613509]  kernel_init+0x11/0x10d
[6.613509]  ? rest_init+0xcc/0xcc
[6.613509]  ret_from_fork+0x22/0x40
[6.613509]
[6.613509] Allocated by task 1:
[6.613509]  save_stack+0x46/0xce
[6.613509]  kasan_kmalloc+0x99/0xa8
[6.613509]  kmem_cache_alloc_trace+0x11a/0x13e
[6.613509]  acp_hw_init+0x210/0xc4a
[6.613509]  amdgpu_device_init+0x1dfb/0x22a2
[6.613509]  amdgpu_driver_load_kms+0xce/0x267
[6.613509]  drm_dev_register+0x169/0x2fb
[6.613509]  amdgpu_pci_probe+0x217/0x242
[6.613509]  pci_device_probe+0x101/0x18e
[6.613509]  driver_probe_device+0x1dd/0x419
[6.613509]  __driver_attach+0x9f/0xc9
[6.613509]  bus_for_each_dev+0xbc/0xe1
[6.613509]  bus_add_driver+0x189/0x2c0
[6.613509]  driver_register+0x108/0x156
[6.613509]  do_one_initcall+0xb2/0x161
[6.613509]  kernel_init_freeable+0x25a/0x308
[6.613509]  kernel_init+0x11/0x10d
[6.613509]  ret_from_fork+0x22/0x40
[6.613509]
[6.613509] Freed by task 0:
[6.613509] (stack is not available)
[6.613509]
[6.613509] The buggy address belongs to the object at 880107d4db08
[6.613509]  which belongs to the cache kmalloc-512 of size 512
[6.613509] The buggy address is located 336 bytes inside of
[6.613509]  512-byte region [880107d4db08, 880107d4dd08)
[6.613509] The buggy address belongs to the page:
[6.613509] page:ea00041f5300 count:1 mapcount:0 mapping:  
(null) index:0x0 compound_mapcount: 0
[6.613509] flags: 0x80008100(slab|head)
[6.613509] raw: 80008100   
000100120012
[6.613509] raw: ea0004208520 88010b001680 88010b002cc0 

[6.613509] page dumped because: kasan: bad access detected
[6.613509]
[6.613509] Memory state around the buggy address:
[6.613509]  880107d4db00: fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[6.613509]  880107d4db80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[6.613509] >880107d4dc00: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc 
fc
[6.613509] ^
[6.613509]  880107d4dc80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[6.613509]  880107d4dd00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[6.613509] 
==

Fixes: 51f7415039d4 ("drm/amd/amdgpu: creating two I2S instances for stoney/cz")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c 
b/drivers/gpu/drm/amd/amdgpu/amd

[PATCH] drm/amdgpu/acp: Fix slab-out-of-bounds in mfd_add_device in acp_hw_init

2018-04-13 Thread Daniel Kurtz
Commit 51f7415039d4 ("drm/amd/amdgpu: creating two I2S instances for
stoney/cz") added support for the "BT_I2S" ACP i2s channel.  As part of
this change, one additional acp resource was added, but the "num_resource"
count was accidentally incremented by 2.

This incorrect count eventually causes mfd_add_device() to try to access
an invalid memory address (the location of non-existent resource 5.

This fault was detected by running a KASAN enabled kernel, which produced
the following splat at boot:

[6.612987] 
==
[6.613509] BUG: KASAN: slab-out-of-bounds in mfd_add_device+0x4bc/0x7a7
[6.613509] Read of size 8 at addr 880107d4dc58 by task swapper/0/1
[6.613509]
[6.613509] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.33 #349
[6.613509] Hardware name: Google Grunt/Grunt, BIOS 
Google_Grunt.10543.0.2018_04_03_1812 04/02/2018
[6.613509] Call Trace:
[6.613509]  dump_stack+0x4d/0x63
[6.613509]  print_address_description+0x80/0x2d6
[6.613509]  ? mfd_add_device+0x4bc/0x7a7
[6.613509]  kasan_report+0x255/0x295
[6.613509]  mfd_add_device+0x4bc/0x7a7
[6.613509]  ? kasan_kmalloc+0x99/0xa8
[6.613509]  ? mfd_add_devices+0x58/0xe4
[6.613509]  ? __kmalloc+0x154/0x178
[6.613509]  mfd_add_devices+0xa5/0xe4
[6.613509]  acp_hw_init+0x92e/0xc4a
[6.613509]  amdgpu_device_init+0x1dfb/0x22a2
[6.613509]  ? kmalloc_order+0x53/0x5d
[6.613509]  ? kmalloc_order_trace+0x23/0xb3
[6.613509]  amdgpu_driver_load_kms+0xce/0x267
[6.613509]  drm_dev_register+0x169/0x2fb
[6.613509]  amdgpu_pci_probe+0x217/0x242
[6.613509]  pci_device_probe+0x101/0x18e
[6.613509]  driver_probe_device+0x1dd/0x419
[6.613509]  ? ___might_sleep+0x80/0x1b6
[6.613509]  __driver_attach+0x9f/0xc9
[6.613509]  ? driver_probe_device+0x419/0x419
[6.613509]  bus_for_each_dev+0xbc/0xe1
[6.613509]  bus_add_driver+0x189/0x2c0
[6.613509]  driver_register+0x108/0x156
[6.613509]  ? ttm_init+0x67/0x67
[6.613509]  do_one_initcall+0xb2/0x161
[6.613509]  kernel_init_freeable+0x25a/0x308
[6.613509]  ? rest_init+0xcc/0xcc
[6.613509]  kernel_init+0x11/0x10d
[6.613509]  ? rest_init+0xcc/0xcc
[6.613509]  ret_from_fork+0x22/0x40
[6.613509]
[6.613509] Allocated by task 1:
[6.613509]  save_stack+0x46/0xce
[6.613509]  kasan_kmalloc+0x99/0xa8
[6.613509]  kmem_cache_alloc_trace+0x11a/0x13e
[6.613509]  acp_hw_init+0x210/0xc4a
[6.613509]  amdgpu_device_init+0x1dfb/0x22a2
[6.613509]  amdgpu_driver_load_kms+0xce/0x267
[6.613509]  drm_dev_register+0x169/0x2fb
[6.613509]  amdgpu_pci_probe+0x217/0x242
[6.613509]  pci_device_probe+0x101/0x18e
[6.613509]  driver_probe_device+0x1dd/0x419
[6.613509]  __driver_attach+0x9f/0xc9
[6.613509]  bus_for_each_dev+0xbc/0xe1
[6.613509]  bus_add_driver+0x189/0x2c0
[6.613509]  driver_register+0x108/0x156
[6.613509]  do_one_initcall+0xb2/0x161
[6.613509]  kernel_init_freeable+0x25a/0x308
[6.613509]  kernel_init+0x11/0x10d
[6.613509]  ret_from_fork+0x22/0x40
[6.613509]
[6.613509] Freed by task 0:
[6.613509] (stack is not available)
[6.613509]
[6.613509] The buggy address belongs to the object at 880107d4db08
[6.613509]  which belongs to the cache kmalloc-512 of size 512
[6.613509] The buggy address is located 336 bytes inside of
[6.613509]  512-byte region [880107d4db08, 880107d4dd08)
[6.613509] The buggy address belongs to the page:
[6.613509] page:ea00041f5300 count:1 mapcount:0 mapping:  
(null) index:0x0 compound_mapcount: 0
[6.613509] flags: 0x80008100(slab|head)
[6.613509] raw: 80008100   
000100120012
[6.613509] raw: ea0004208520 88010b001680 88010b002cc0 

[6.613509] page dumped because: kasan: bad access detected
[6.613509]
[6.613509] Memory state around the buggy address:
[6.613509]  880107d4db00: fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[6.613509]  880107d4db80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[6.613509] >880107d4dc00: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc 
fc
[6.613509] ^
[6.613509]  880107d4dc80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[6.613509]  880107d4dd00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[6.613509] 
==

Fixes: 51f7415039d4 ("drm/amd/amdgpu: creating two I2S instances for stoney/cz")
Signed-off-by: Daniel Kurtz 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index 20f20079935b..42

[PATCH v6] earlycon: Use a pointer table to fix __earlycon_table stride

2018-04-06 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
Suggested-by: Aaron Durbin <adur...@chromium.org>
Reviewed-by: Rob Herring <r...@kernel.org>
Tested-by: Guenter Roeck <gro...@chromium.org>
Reviewed-by: Guenter Roeck <gro...@chromium.org>
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

Changes since v3:
 * Fixed typos in commit message

Changes since v4:
 * removed Change-Id: from commit message

Changes since v5:
 * None, just re-posting per request from greg k-h

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 278841c75b97..af240573e482 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -188,7 +188,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 1d356105f25a..b4c9fda9d833 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlyc

[PATCH v6] earlycon: Use a pointer table to fix __earlycon_table stride

2018-04-06 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz 
Suggested-by: Aaron Durbin 
Reviewed-by: Rob Herring 
Tested-by: Guenter Roeck 
Reviewed-by: Guenter Roeck 
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

Changes since v3:
 * Fixed typos in commit message

Changes since v4:
 * removed Change-Id: from commit message

Changes since v5:
 * None, just re-posting per request from greg k-h

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 278841c75b97..af240573e482 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -188,7 +188,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 1d356105f25a..b4c9fda9d833 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const 

[PATCH] mmc: sdhci-pci: Only do AMD tuning for HS200

2018-04-06 Thread Daniel Kurtz
Commit c31165d7400b ("mmc: sdhci-pci: Add support for HS200 tuning mode
on AMD, eMMC-4.5.1") added a HS200 tuning method for use with AMD SDHCI
controllers.  As described in the commit subject, this tuning is specific
for HS200.  However, as implemented, this method is used for all host
timings, because platform_execute_tuning, if it exists, is called
unconditionally by sdhci_execute_tuning().  This breaks tuning when using
the AMD controller with, for example, a DDR50 SD card.

Instead, we can implement an amd execute_tuning wrapper callback, and
then conditionally do the HS200 specific tuning for HS200, and otherwise
call back to the standard sdhci_execute_tuning().

Signed-off-by: Daniel Kurtz <djku...@chromium.org>
---
 drivers/mmc/host/sdhci-pci-core.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c 
b/drivers/mmc/host/sdhci-pci-core.c
index 787434e5589d..78c25ad35fd2 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1312,7 +1312,7 @@ static void amd_enable_manual_tuning(struct pci_dev *pdev)
pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val);
 }
 
-static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
+static int amd_execute_tuning_hs200(struct sdhci_host *host, u32 opcode)
 {
struct sdhci_pci_slot *slot = sdhci_priv(host);
struct pci_dev *pdev = slot->chip->pdev;
@@ -1351,6 +1351,27 @@ static int amd_execute_tuning(struct sdhci_host *host, 
u32 opcode)
return 0;
 }
 
+static int amd_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+
+   /* AMD requires custom HS200 tuning */
+   if (host->timing == MMC_TIMING_MMC_HS200)
+   return amd_execute_tuning_hs200(host, opcode);
+
+   /* Otherwise perform standard SDHCI tuning */
+   return sdhci_execute_tuning(mmc, opcode);
+}
+
+static int amd_probe_slot(struct sdhci_pci_slot *slot)
+{
+   struct mmc_host_ops *ops = >host->mmc_host_ops;
+
+   ops->execute_tuning = amd_execute_tuning;
+
+   return 0;
+}
+
 static int amd_probe(struct sdhci_pci_chip *chip)
 {
struct pci_dev  *smbus_dev;
@@ -1385,12 +1406,12 @@ static const struct sdhci_ops amd_sdhci_pci_ops = {
.set_bus_width  = sdhci_set_bus_width,
.reset  = sdhci_reset,
.set_uhs_signaling  = sdhci_set_uhs_signaling,
-   .platform_execute_tuning= amd_execute_tuning,
 };
 
 static const struct sdhci_pci_fixes sdhci_amd = {
.probe  = amd_probe,
.ops= _sdhci_pci_ops,
+   .probe_slot = amd_probe_slot,
 };
 
 static const struct pci_device_id pci_ids[] = {
-- 
2.17.0.484.g0c8726318c-goog



[PATCH] mmc: sdhci-pci: Only do AMD tuning for HS200

2018-04-06 Thread Daniel Kurtz
Commit c31165d7400b ("mmc: sdhci-pci: Add support for HS200 tuning mode
on AMD, eMMC-4.5.1") added a HS200 tuning method for use with AMD SDHCI
controllers.  As described in the commit subject, this tuning is specific
for HS200.  However, as implemented, this method is used for all host
timings, because platform_execute_tuning, if it exists, is called
unconditionally by sdhci_execute_tuning().  This breaks tuning when using
the AMD controller with, for example, a DDR50 SD card.

Instead, we can implement an amd execute_tuning wrapper callback, and
then conditionally do the HS200 specific tuning for HS200, and otherwise
call back to the standard sdhci_execute_tuning().

Signed-off-by: Daniel Kurtz 
---
 drivers/mmc/host/sdhci-pci-core.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c 
b/drivers/mmc/host/sdhci-pci-core.c
index 787434e5589d..78c25ad35fd2 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1312,7 +1312,7 @@ static void amd_enable_manual_tuning(struct pci_dev *pdev)
pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val);
 }
 
-static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
+static int amd_execute_tuning_hs200(struct sdhci_host *host, u32 opcode)
 {
struct sdhci_pci_slot *slot = sdhci_priv(host);
struct pci_dev *pdev = slot->chip->pdev;
@@ -1351,6 +1351,27 @@ static int amd_execute_tuning(struct sdhci_host *host, 
u32 opcode)
return 0;
 }
 
+static int amd_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+
+   /* AMD requires custom HS200 tuning */
+   if (host->timing == MMC_TIMING_MMC_HS200)
+   return amd_execute_tuning_hs200(host, opcode);
+
+   /* Otherwise perform standard SDHCI tuning */
+   return sdhci_execute_tuning(mmc, opcode);
+}
+
+static int amd_probe_slot(struct sdhci_pci_slot *slot)
+{
+   struct mmc_host_ops *ops = >host->mmc_host_ops;
+
+   ops->execute_tuning = amd_execute_tuning;
+
+   return 0;
+}
+
 static int amd_probe(struct sdhci_pci_chip *chip)
 {
struct pci_dev  *smbus_dev;
@@ -1385,12 +1406,12 @@ static const struct sdhci_ops amd_sdhci_pci_ops = {
.set_bus_width  = sdhci_set_bus_width,
.reset  = sdhci_reset,
.set_uhs_signaling  = sdhci_set_uhs_signaling,
-   .platform_execute_tuning= amd_execute_tuning,
 };
 
 static const struct sdhci_pci_fixes sdhci_amd = {
.probe  = amd_probe,
.ops= _sdhci_pci_ops,
+   .probe_slot = amd_probe_slot,
 };
 
 static const struct pci_device_id pci_ids[] = {
-- 
2.17.0.484.g0c8726318c-goog



Re: [PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-04-03 Thread Daniel Kurtz
Hi Jeffy,

Sorry for delayed response.

On Mon, Mar 26, 2018 at 1:58 AM JeffyChen <jeffy.c...@rock-chips.com> wrote:

> Hi Daniel,

> Thanks for your reply.

> On 03/26/2018 02:31 PM, Daniel Kurtz wrote:
> >> >+struct rk_iommudata {
> >> >+   struct rk_iommu *iommu;
> >> >+};
> > Why do we need this struct?  Can't we just assign a pointer to struct
> > rk_iommu directly to dev->archdata.iommu?
> >
> hmmm, i was trying to add more device related data in patch[13]:

>struct rk_iommudata {
> +   struct device_link *link; /* runtime PM link from IOMMU to master
*/
>  struct rk_iommu *iommu;
>};
> >

Can't you just add link to rk_iommu directly?


Re: [PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-04-03 Thread Daniel Kurtz
Hi Jeffy,

Sorry for delayed response.

On Mon, Mar 26, 2018 at 1:58 AM JeffyChen  wrote:

> Hi Daniel,

> Thanks for your reply.

> On 03/26/2018 02:31 PM, Daniel Kurtz wrote:
> >> >+struct rk_iommudata {
> >> >+   struct rk_iommu *iommu;
> >> >+};
> > Why do we need this struct?  Can't we just assign a pointer to struct
> > rk_iommu directly to dev->archdata.iommu?
> >
> hmmm, i was trying to add more device related data in patch[13]:

>struct rk_iommudata {
> +   struct device_link *link; /* runtime PM link from IOMMU to master
*/
>  struct rk_iommu *iommu;
>};
> >

Can't you just add link to rk_iommu directly?


Re: [PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-03-26 Thread Daniel Kurtz
roup, >dev, NULL);
> +   iommu_device_link(>iommu, dev);

>  return 0;
>   }

> -static int rk_iommu_add_device(struct device *dev)
> +static void rk_iommu_remove_device(struct device *dev)
>   {
> -   struct iommu_group *group;
>  struct rk_iommu *iommu;
> -   int ret;
> -
> -   if (!rk_iommu_is_dev_iommu_master(dev))
> -   return -ENODEV;
> -
> -   group = iommu_group_get(dev);
> -   if (!group) {
> -   group = iommu_group_alloc();
> -   if (IS_ERR(group)) {
> -   dev_err(dev, "Failed to allocate IOMMU group\n");
> -   return PTR_ERR(group);
> -   }
> -   }
> -
> -   ret = iommu_group_add_device(group, dev);
> -   if (ret)
> -   goto err_put_group;
> -
> -   ret = rk_iommu_group_set_iommudata(group, dev);
> -   if (ret)
> -   goto err_remove_device;

>  iommu = rk_iommu_from_dev(dev);
> -   if (iommu)
> -   iommu_device_link(>iommu, dev);

> -   iommu_group_put(group);
> -
> -   return 0;
> -
> -err_remove_device:
> +   iommu_device_unlink(>iommu, dev);
>  iommu_group_remove_device(dev);
> -err_put_group:
> -   iommu_group_put(group);
> -   return ret;
>   }

> -static void rk_iommu_remove_device(struct device *dev)
> +static int rk_iommu_of_xlate(struct device *dev,
> +struct of_phandle_args *args)
>   {
> -   struct rk_iommu *iommu;
> +   struct platform_device *iommu_dev;
> +   struct rk_iommudata *data;

> -   if (!rk_iommu_is_dev_iommu_master(dev))
> -   return;
> +   data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
> +   if (!data)
> +   return -ENOMEM;

> -   iommu = rk_iommu_from_dev(dev);
> -   if (iommu)
> -   iommu_device_unlink(>iommu, dev);
> +   iommu_dev = of_find_device_by_node(args->np);

> -   iommu_group_remove_device(dev);
> +   data->iommu = platform_get_drvdata(iommu_dev);
> +   dev->archdata.iommu = data;
> +
> +   of_dev_put(iommu_dev);
> +
> +   return 0;
>   }

>   static const struct iommu_ops rk_iommu_ops = {
> @@ -1106,7 +1045,9 @@ static const struct iommu_ops rk_iommu_ops = {
>  .add_device = rk_iommu_add_device,
>  .remove_device = rk_iommu_remove_device,
>  .iova_to_phys = rk_iommu_iova_to_phys,
> +   .device_group = generic_device_group,
>  .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
> +   .of_xlate = rk_iommu_of_xlate,
>   };

>   static int rk_iommu_probe(struct platform_device *pdev)
> @@ -1178,6 +1119,8 @@ static int rk_iommu_probe(struct platform_device
*pdev)
>  goto err_unprepare_clocks;

>  iommu_device_set_ops(>iommu, _iommu_ops);
> +   iommu_device_set_fwnode(>iommu, >of_node->fwnode);
> +
>  err = iommu_device_register(>iommu);
>  if (err)
>  goto err_remove_sysfs;
> @@ -1250,6 +1193,8 @@ static int __init rk_iommu_init(void)
>   }
>   subsys_initcall(rk_iommu_init);

> +IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
> +
>   MODULE_DESCRIPTION("IOMMU API for Rockchip");
>   MODULE_AUTHOR("Simon Xue <x...@rock-chips.com> and Daniel Kurtz <
djku...@chromium.org>");
>   MODULE_ALIAS("platform:rockchip-iommu");
> --
> 2.11.0


Re: [PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-03-26 Thread Daniel Kurtz
t;   }

> -static int rk_iommu_add_device(struct device *dev)
> +static void rk_iommu_remove_device(struct device *dev)
>   {
> -   struct iommu_group *group;
>  struct rk_iommu *iommu;
> -   int ret;
> -
> -   if (!rk_iommu_is_dev_iommu_master(dev))
> -   return -ENODEV;
> -
> -   group = iommu_group_get(dev);
> -   if (!group) {
> -   group = iommu_group_alloc();
> -   if (IS_ERR(group)) {
> -   dev_err(dev, "Failed to allocate IOMMU group\n");
> -   return PTR_ERR(group);
> -   }
> -   }
> -
> -   ret = iommu_group_add_device(group, dev);
> -   if (ret)
> -   goto err_put_group;
> -
> -   ret = rk_iommu_group_set_iommudata(group, dev);
> -   if (ret)
> -   goto err_remove_device;

>  iommu = rk_iommu_from_dev(dev);
> -   if (iommu)
> -   iommu_device_link(>iommu, dev);

> -   iommu_group_put(group);
> -
> -   return 0;
> -
> -err_remove_device:
> +   iommu_device_unlink(>iommu, dev);
>  iommu_group_remove_device(dev);
> -err_put_group:
> -   iommu_group_put(group);
> -   return ret;
>   }

> -static void rk_iommu_remove_device(struct device *dev)
> +static int rk_iommu_of_xlate(struct device *dev,
> +struct of_phandle_args *args)
>   {
> -   struct rk_iommu *iommu;
> +   struct platform_device *iommu_dev;
> +   struct rk_iommudata *data;

> -   if (!rk_iommu_is_dev_iommu_master(dev))
> -   return;
> +   data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
> +   if (!data)
> +   return -ENOMEM;

> -   iommu = rk_iommu_from_dev(dev);
> -   if (iommu)
> -   iommu_device_unlink(>iommu, dev);
> +   iommu_dev = of_find_device_by_node(args->np);

> -   iommu_group_remove_device(dev);
> +   data->iommu = platform_get_drvdata(iommu_dev);
> +   dev->archdata.iommu = data;
> +
> +   of_dev_put(iommu_dev);
> +
> +   return 0;
>   }

>   static const struct iommu_ops rk_iommu_ops = {
> @@ -1106,7 +1045,9 @@ static const struct iommu_ops rk_iommu_ops = {
>  .add_device = rk_iommu_add_device,
>  .remove_device = rk_iommu_remove_device,
>  .iova_to_phys = rk_iommu_iova_to_phys,
> +   .device_group = generic_device_group,
>  .pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
> +   .of_xlate = rk_iommu_of_xlate,
>   };

>   static int rk_iommu_probe(struct platform_device *pdev)
> @@ -1178,6 +1119,8 @@ static int rk_iommu_probe(struct platform_device
*pdev)
>  goto err_unprepare_clocks;

>  iommu_device_set_ops(>iommu, _iommu_ops);
> +   iommu_device_set_fwnode(>iommu, >of_node->fwnode);
> +
>  err = iommu_device_register(>iommu);
>  if (err)
>  goto err_remove_sysfs;
> @@ -1250,6 +1193,8 @@ static int __init rk_iommu_init(void)
>   }
>   subsys_initcall(rk_iommu_init);

> +IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
> +
>   MODULE_DESCRIPTION("IOMMU API for Rockchip");
>   MODULE_AUTHOR("Simon Xue  and Daniel Kurtz <
djku...@chromium.org>");
>   MODULE_ALIAS("platform:rockchip-iommu");
> --
> 2.11.0


Re: [PATCH v2 0/2] Fix __earlycon_table stride... again

2018-03-23 Thread Daniel Kurtz
On Fri, Mar 23, 2018 at 7:34 AM Greg Kroah-Hartman <
gre...@linuxfoundation.org> wrote:

> On Tue, Mar 20, 2018 at 11:57:10AM -0600, Daniel Kurtz wrote:
> > The __earlycon_table lives in a special "__earlycon_table" section.  The
> > contents of this table are added using some macros that deposit
individual
> > struct earlycon_id entries into this section.  The linker then defines
a symbol
> > __earlycon_table that is supposed to contain the addresss of the first
of these
> > entries.  The code in earlycon.c and fdt.c then tries to access the
memory
> > pointed to by __earlycon_table as an array of struct earlycon_id
entries.
> >
> > Unfortunately, the compiler doesn't always place the entries such that
they
> > are an array.  Let's fix that.
> >
> > Patch 1 of the series is a fix that should hopefully fix a kbuild error
that
> > seems to be triggered by Patch 2.

> Doesn't seem like that worked :(

> And I have a bunch of different versions of this patch in my to-review
> queue, and I can't figure out which is the "latest" one.

> Can you resend it, after getting the build error fixed, so I know which
> to attempt to apply?

Please take Patch Set v5 (fixes kbuild errors and commit message typos):
https://patchwork.kernel.org/patch/10298043/

thanks,
-djk


> thanks,

> greg k-h


Re: [PATCH v2 0/2] Fix __earlycon_table stride... again

2018-03-23 Thread Daniel Kurtz
On Fri, Mar 23, 2018 at 7:34 AM Greg Kroah-Hartman <
gre...@linuxfoundation.org> wrote:

> On Tue, Mar 20, 2018 at 11:57:10AM -0600, Daniel Kurtz wrote:
> > The __earlycon_table lives in a special "__earlycon_table" section.  The
> > contents of this table are added using some macros that deposit
individual
> > struct earlycon_id entries into this section.  The linker then defines
a symbol
> > __earlycon_table that is supposed to contain the addresss of the first
of these
> > entries.  The code in earlycon.c and fdt.c then tries to access the
memory
> > pointed to by __earlycon_table as an array of struct earlycon_id
entries.
> >
> > Unfortunately, the compiler doesn't always place the entries such that
they
> > are an array.  Let's fix that.
> >
> > Patch 1 of the series is a fix that should hopefully fix a kbuild error
that
> > seems to be triggered by Patch 2.

> Doesn't seem like that worked :(

> And I have a bunch of different versions of this patch in my to-review
> queue, and I can't figure out which is the "latest" one.

> Can you resend it, after getting the build error fixed, so I know which
> to attempt to apply?

Please take Patch Set v5 (fixes kbuild errors and commit message typos):
https://patchwork.kernel.org/patch/10298043/

thanks,
-djk


> thanks,

> greg k-h


[PATCH v5] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
Suggested-by: Aaron Durbin <adur...@chromium.org>
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

Changes since v3:
 * Fixed typos in commit message

Changes since v4:
 * removed Change-Id: from commit message

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-exter

[PATCH v5] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz 
Suggested-by: Aaron Durbin 
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

Changes since v3:
 * Fixed typos in commit message

Changes since v4:
 * removed Change-Id: from commit message

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+

[PATCH v4] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Change-Id: Ic42c4db0c8b034fa6aa2bf02eef0fdc159478ac4
Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
Suggested-by: Aaron Durbin <adur...@chromium.org>
---
 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern const struct earlycon_id *__earlycon_table_end[];
 
 

[PATCH v4] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correspond
to the 64-byte aligned contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Change-Id: Ic42c4db0c8b034fa6aa2bf02eef0fdc159478ac4
Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz 
Suggested-by: Aaron Durbin 
---
 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern const struct earlycon_id *__earlycon_table_end[];
 
 #if defined(CONFIG_SERIAL_EARLYCON) && !defi

[PATCH v3] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correpsond
to the 64-byte alignbed contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
Suggested-by: Aaron Durbin <adur...@chromium.org>
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern cons

[PATCH v3] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correpsond
to the 64-byte alignbed contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz 
Suggested-by: Aaron Durbin 
---
Changes since v2:
 * Use __initconst instead of __initdata to avoid h8300 and alpha kbuild errors

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..c4219b9cbb70 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern const struct earlycon_id *__earlycon_table_end[];
 
 #if defined(

[PATCH v2 2/2] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correpsond
to the 64-byte alignbed contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz <djku...@chromium.org>
Suggested-by: Aaron Durbin <adur...@chromium.org>
---
Changes since v1:
 * added Suggested-by and Fixes, and reworded the commit message per Randy. 

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..93b7add47087 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern cons

[PATCH v2 2/2] earlycon: Use a pointer table to fix __earlycon_table stride

2018-03-20 Thread Daniel Kurtz
Commit 99492c39f39f ("earlycon: Fix __earlycon_table stride") tried to fix
__earlycon_table stride by forcing the earlycon_id struct alignment to 32
and asking the linker to 32-byte align the __earlycon_table symbol.  This
fix was based on commit 07fca0e57fca92 ("tracing: Properly align linker
defined symbols") which tried a similar fix for the tracing subsystem.

However, this fix doesn't quite work because there is no guarantee that
gcc will place structures packed into an array format.  In fact, gcc 4.9
chooses to 64-byte align these structs by inserting additional padding
between the entries because it has no clue that they are supposed to be in
an array.  If we are unlucky, the linker will assign symbol
"__earlycon_table" to a 32-byte aligned address which does not correpsond
to the 64-byte alignbed contents of section "__earlycon_table".

To address this same problem, the fix to the tracing system was
subsequently re-implemented using a more robust table of pointers approach
by commits:
 3d56e331b653 ("tracing: Replace syscall_meta_data struct array with pointer 
array")
 654986462939 ("tracepoints: Fix section alignment using pointer array")
 e4a9ea5ee7c8 ("tracing: Replace trace_event struct array with pointer array")

Let's use this same "array of pointers to structs" approach for
EARLYCON_TABLE.

Fixes: 99492c39f39f ("earlycon: Fix __earlycon_table stride")
Signed-off-by: Daniel Kurtz 
Suggested-by: Aaron Durbin 
---
Changes since v1:
 * added Suggested-by and Fixes, and reworded the commit message per Randy. 

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d676375..6da20b9688f7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
int offset;
const char *p, *q, *options = NULL;
int l;
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
const void *fdt = initial_boot_params;
 
offset = fdt_path_offset(fdt, "/chosen");
@@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
return 0;
}
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
+
if (!match->compatible[0])
continue;
 
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a24278380fec..22683393a0f2 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct 
earlycon_id *match)
  */
 int __init setup_earlycon(char *buf)
 {
-   const struct earlycon_id *match;
+   const struct earlycon_id **p_match;
 
if (!buf || !buf[0])
return -EINVAL;
@@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
 
-   for (match = __earlycon_table; match < __earlycon_table_end; match++) {
+   for (p_match = __earlycon_table; p_match < __earlycon_table_end;
+p_match++) {
+   const struct earlycon_id *match = *p_match;
size_t len = strlen(match->name);
 
if (strncmp(buf, match->name, len))
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1ab0e520d6fc..e17de55c2542 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -179,7 +179,7 @@
 #endif
 
 #ifdef CONFIG_SERIAL_EARLYCON
-#define EARLYCON_TABLE() STRUCT_ALIGN();   \
+#define EARLYCON_TABLE() . = ALIGN(8); \
 VMLINUX_SYMBOL(__earlycon_table) = .;  \
 KEEP(*(__earlycon_table))  \
 VMLINUX_SYMBOL(__earlycon_table_end) = .;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b32df49a3bd5..93b7add47087 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -351,10 +351,10 @@ struct earlycon_id {
charname[16];
charcompatible[128];
int (*setup)(struct earlycon_device *, const char *options);
-} __aligned(32);
+};
 
-extern const struct earlycon_id __earlycon_table[];
-extern const struct earlycon_id __earlycon_table_end[];
+extern const struct earlycon_id *__earlycon_table[];
+extern const struct earlycon_id *__earlycon_table_end[];
 
 #if defined(

[PATCH v2 0/2] Fix __earlycon_table stride... again

2018-03-20 Thread Daniel Kurtz
The __earlycon_table lives in a special "__earlycon_table" section.  The
contents of this table are added using some macros that deposit individual
struct earlycon_id entries into this section.  The linker then defines a symbol
__earlycon_table that is supposed to contain the addresss of the first of these
entries.  The code in earlycon.c and fdt.c then tries to access the memory
pointed to by __earlycon_table as an array of struct earlycon_id entries.

Unfortunately, the compiler doesn't always place the entries such that they
are an array.  Let's fix that.

Patch 1 of the series is a fix that should hopefully fix a kbuild error that
seems to be triggered by Patch 2.

Daniel Kurtz (2):
  serial: sh-sci: Remove __initdata attribute for struct 'port_cfg'
  earlycon: Use a pointer table to fix __earlycon_table stride

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 drivers/tty/serial/sh-sci.c   |  2 +-
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 5 files changed, 25 insertions(+), 13 deletions(-)

-- 
2.16.2.804.g6dcf76e118-goog



[PATCH v2 0/2] Fix __earlycon_table stride... again

2018-03-20 Thread Daniel Kurtz
The __earlycon_table lives in a special "__earlycon_table" section.  The
contents of this table are added using some macros that deposit individual
struct earlycon_id entries into this section.  The linker then defines a symbol
__earlycon_table that is supposed to contain the addresss of the first of these
entries.  The code in earlycon.c and fdt.c then tries to access the memory
pointed to by __earlycon_table as an array of struct earlycon_id entries.

Unfortunately, the compiler doesn't always place the entries such that they
are an array.  Let's fix that.

Patch 1 of the series is a fix that should hopefully fix a kbuild error that
seems to be triggered by Patch 2.

Daniel Kurtz (2):
  serial: sh-sci: Remove __initdata attribute for struct 'port_cfg'
  earlycon: Use a pointer table to fix __earlycon_table stride

 drivers/of/fdt.c  |  7 +--
 drivers/tty/serial/earlycon.c |  6 --
 drivers/tty/serial/sh-sci.c   |  2 +-
 include/asm-generic/vmlinux.lds.h |  2 +-
 include/linux/serial_core.h   | 21 ++---
 5 files changed, 25 insertions(+), 13 deletions(-)

-- 
2.16.2.804.g6dcf76e118-goog



  1   2   3   4   5   6   7   8   9   >