Re: [U-Boot] [PATCH 30/33] x86: sound: Add support for broadwell I2S

2019-02-13 Thread Bin Meng
On Tue, Jan 22, 2019 at 9:14 AM Simon Glass  wrote:
>
> I2S is used to send digital audio data to an audio codec. Add support for
> this on broadwell.
>
> Signed-off-by: Simon Glass 
> ---
>
>  drivers/sound/Makefile|   1 +
>  drivers/sound/broadwell_i2s.c | 306 ++
>  drivers/sound/broadwell_i2s.h | 301 +
>  3 files changed, 608 insertions(+)
>  create mode 100644 drivers/sound/broadwell_i2s.c
>  create mode 100644 drivers/sound/broadwell_i2s.h
>

Reviewed-by: Bin Meng 
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH 30/33] x86: sound: Add support for broadwell I2S

2019-01-21 Thread Simon Glass
I2S is used to send digital audio data to an audio codec. Add support for
this on broadwell.

Signed-off-by: Simon Glass 
---

 drivers/sound/Makefile|   1 +
 drivers/sound/broadwell_i2s.c | 306 ++
 drivers/sound/broadwell_i2s.h | 301 +
 3 files changed, 608 insertions(+)
 create mode 100644 drivers/sound/broadwell_i2s.c
 create mode 100644 drivers/sound/broadwell_i2s.h

diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index f01fb2f739..102b3bca1a 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_SOUND_MAX98090)  += max98090.o maxim_codec.o
 obj-$(CONFIG_SOUND_MAX98095)   += max98095.o maxim_codec.o
 obj-$(CONFIG_SOUND_INTEL_HDA)  += hda_codec.o
 obj-$(CONFIG_SOUND_I8254)  += i8254_beep.o
+obj-$(CONFIG_INTEL_BROADWELL)  += broadwell_i2s.o
 obj-$(CONFIG_SOUND_IVYBRIDGE)  += ivybridge_sound.o
diff --git a/drivers/sound/broadwell_i2s.c b/drivers/sound/broadwell_i2s.c
new file mode 100644
index 00..a03bb5e4dc
--- /dev/null
+++ b/drivers/sound/broadwell_i2s.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Intel Broadwell I2S driver
+ *
+ * Copyright 2019 Google LLC
+ *
+ * Modified from dc i2s/broadwell/broadwell.c
+ */
+
+#define LOG_CATEGORY UCLASS_I2S
+
+#include 
+#include 
+#include 
+#include 
+#include "broadwell_i2s.h"
+
+enum {
+   BDW_SHIM_START_ADDRESS = 0xfb000,
+   BDW_SSP0_START_ADDRESS = 0xfc000,
+   BDW_SSP1_START_ADDRESS = 0xfd000,
+};
+
+struct broadwell_i2s_priv {
+   enum frame_sync_rel_timing_t rel_timing;
+   enum frame_sync_pol_t sfrm_polarity;
+   enum end_transfer_state_t end_transfer_state;
+   enum clock_mode_t sclk_mode;
+   uint sclk_dummy_stop;   /* 0-31 */
+   uint sclk_frame_width;  /* 1-38 */
+   struct i2s_shim_regs *shim;
+   struct broadwell_i2s_regs *regs;
+};
+
+static void init_shim_csr(struct broadwell_i2s_priv *priv)
+{
+   /*
+* Select SSP clock
+* Turn off low power clock
+* Set PIO mode
+* Stall DSP core
+*/
+   clrsetbits_le32(&priv->shim->csr,
+   SHIM_CS_S0IOCS | SHIM_CS_LPCS | SHIM_CS_DCS_MASK,
+   SHIM_CS_S1IOCS | SHIM_CS_SBCS_SSP1_24MHZ |
+   SHIM_CS_SBCS_SSP0_24MHZ | SHIM_CS_SDPM_PIO_SSP1 |
+   SHIM_CS_SDPM_PIO_SSP0 | SHIM_CS_STALL |
+   SHIM_CS_DCS_DSP32_AF32);
+}
+
+static void init_shim_clkctl(struct i2s_uc_priv *uc_priv,
+struct broadwell_i2s_priv *priv)
+{
+   uint32_t clkctl = readl(&priv->shim->clkctl);
+
+   /* Set 24Mhz mclk, prevent local clock gating, enable SSP0 clock */
+   clkctl &= SHIM_CLKCTL_RESERVED;
+   clkctl |= SHIM_CLKCTL_MCLK_24MHZ | SHIM_CLKCTL_DCPLCG;
+
+   /* Enable requested SSP interface */
+   if (uc_priv->id)
+   clkctl |= SHIM_CLKCTL_SCOE_SSP1 | SHIM_CLKCTL_SFLCGB_SSP1_CGD;
+   else
+   clkctl |= SHIM_CLKCTL_SCOE_SSP0 | SHIM_CLKCTL_SFLCGB_SSP0_CGD;
+
+   writel(clkctl, &priv->shim->clkctl);
+}
+
+static void init_sscr0(struct i2s_uc_priv *uc_priv,
+  struct broadwell_i2s_priv *priv)
+{
+   uint32_t sscr0;
+   uint scale;
+
+   /* Set data size based on BPS */
+   if (uc_priv->bitspersample > 16)
+   sscr0 = (uc_priv->bitspersample - 16 - 1) << SSP_SSC0_DSS_SHIFT
+| SSP_SSC0_EDSS;
+   else
+   sscr0 = (uc_priv->bitspersample - 1) << SSP_SSC0_DSS_SHIFT;
+
+   /* Set network mode, Stereo PSP frame format */
+   sscr0 |= SSP_SSC0_MODE_NETWORK |
+   SSP_SSC0_FRDC_STEREO |
+   SSP_SSC0_FRF_PSP |
+   SSP_SSC0_TIM |
+   SSP_SSC0_RIM |
+   SSP_SSC0_ECS_PCH |
+   SSP_SSC0_NCS_PCH |
+   SSP_SSC0_ACS_PCH;
+
+   /* Scale 24MHz MCLK */
+   scale = uc_priv->audio_pll_clk / uc_priv->samplingrate / uc_priv->bfs;
+   sscr0 |= scale << SSP_SSC0_SCR_SHIFT;
+
+   writel(sscr0, &priv->regs->sscr0);
+}
+
+static void init_sscr1(struct broadwell_i2s_priv *priv)
+{
+   uint32_t sscr1 = readl(&priv->regs->sscr1);
+
+   sscr1 &= SSP_SSC1_RESERVED;
+
+   /* Set as I2S master */
+   sscr1 |= SSP_SSC1_SCLKDIR_MASTER | SSP_SSC1_SCLKDIR_MASTER;
+
+   /* Enable TXD tristate behavior for PCH */
+   sscr1 |= SSP_SSC1_TTELP | SSP_SSC1_TTE;
+
+   /* Disable DMA Tx/Rx service request */
+   sscr1 |= SSP_SSC1_TSRE | SSP_SSC1_RSRE;
+
+   /* Clock on during transfer */
+   sscr1 |= SSP_SSC1_SCFR;
+
+   /* Set FIFO thresholds */
+   sscr1 |= SSP_FIFO_SIZE << SSP_SSC1_RFT_SHIFT;
+   sscr1 |= SSP_FIFO_SIZE << SSP_SSC1_TFT_SHIFT;
+
+   /* Disable interrupts */
+   sscr1 &= ~(SSP_SSC1_EBCEI | SSP_SSC1_TINTE | SSP_SSC1_PINTE);
+   sscr1 &= ~(SSP_SSC1_LBM | SSP_SSC1_RWOT);
+
+   writel(sscr1,