[PATCH] dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size

2020-11-13 Thread Sugar Zhang
Actually, burst size is equal to '1 << desc->rqcfg.brst_size'.
we should use burst size, not desc->rqcfg.brst_size.

dma memcpy performance on Rockchip RV1126
@ 1512MHz A7, 1056MHz LPDDR3, 200MHz DMA:

dmatest:

/# echo dma0chan0 > /sys/module/dmatest/parameters/channel
/# echo 4194304 > /sys/module/dmatest/parameters/test_buf_size
/# echo 8 > /sys/module/dmatest/parameters/iterations
/# echo y > /sys/module/dmatest/parameters/norandom
/# echo y > /sys/module/dmatest/parameters/verbose
/# echo 1 > /sys/module/dmatest/parameters/run

dmatest: dma0chan0-copy0: result #1: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #2: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #3: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #4: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #5: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #6: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #7: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40
dmatest: dma0chan0-copy0: result #8: 'test passed' with src_off=0x0 dst_off=0x0 
len=0x40

Before:

  dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 48 iops 200338 KB/s (0)

After this patch:

  dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 179 iops 734873 KB/s (0)

After this patch and increase dma clk to 400MHz:

  dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 259 iops 1062929 KB/s 
(0)

Signed-off-by: Sugar Zhang 
---

 drivers/dma/pl330.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index e9f0101..0f5c193 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2799,7 +2799,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t 
dst,
 * If burst size is smaller than bus width then make sure we only
 * transfer one at a time to avoid a burst stradling an MFIFO entry.
 */
-   if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
+   if (burst * 8 < pl330->pcfg.data_bus_width)
desc->rqcfg.brst_len = 1;
 
desc->bytes_requested = len;
-- 
2.7.4





[PATCH] ASoC: rockchip: spdif: Handle clk by pm runtime

2020-07-13 Thread Sugar Zhang
This patch handle the clk by pm runtime mechanism to simplify
the clk management.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_spdif.c | 59 +++--
 1 file changed, 17 insertions(+), 42 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 6635145..6748108 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -306,44 +306,22 @@ static int rk_spdif_probe(struct platform_device *pdev)
return -ENOMEM;
 
spdif->hclk = devm_clk_get(>dev, "hclk");
-   if (IS_ERR(spdif->hclk)) {
-   dev_err(>dev, "Can't retrieve rk_spdif bus clock\n");
+   if (IS_ERR(spdif->hclk))
return PTR_ERR(spdif->hclk);
-   }
-   ret = clk_prepare_enable(spdif->hclk);
-   if (ret) {
-   dev_err(spdif->dev, "hclock enable failed %d\n", ret);
-   return ret;
-   }
 
spdif->mclk = devm_clk_get(>dev, "mclk");
-   if (IS_ERR(spdif->mclk)) {
-   dev_err(>dev, "Can't retrieve rk_spdif master clock\n");
-   ret = PTR_ERR(spdif->mclk);
-   goto err_disable_hclk;
-   }
-
-   ret = clk_prepare_enable(spdif->mclk);
-   if (ret) {
-   dev_err(spdif->dev, "clock enable failed %d\n", ret);
-   goto err_disable_clocks;
-   }
+   if (IS_ERR(spdif->mclk))
+   return PTR_ERR(spdif->mclk);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(>dev, res);
-   if (IS_ERR(regs)) {
-   ret = PTR_ERR(regs);
-   goto err_disable_clocks;
-   }
+   if (IS_ERR(regs))
+   return PTR_ERR(regs);
 
spdif->regmap = devm_regmap_init_mmio_clk(>dev, "hclk", regs,
  _spdif_regmap_config);
-   if (IS_ERR(spdif->regmap)) {
-   dev_err(>dev,
-   "Failed to initialise managed register map\n");
-   ret = PTR_ERR(spdif->regmap);
-   goto err_disable_clocks;
-   }
+   if (IS_ERR(spdif->regmap))
+   return PTR_ERR(spdif->regmap);
 
spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR;
spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -352,47 +330,44 @@ static int rk_spdif_probe(struct platform_device *pdev)
spdif->dev = >dev;
dev_set_drvdata(>dev, spdif);
 
-   pm_runtime_set_active(>dev);
pm_runtime_enable(>dev);
-   pm_request_idle(>dev);
+   if (!pm_runtime_enabled(>dev)) {
+   ret = rk_spdif_runtime_resume(>dev);
+   if (ret)
+   goto err_pm_runtime;
+   }
 
ret = devm_snd_soc_register_component(>dev,
  _spdif_component,
  _spdif_dai, 1);
if (ret) {
dev_err(>dev, "Could not register DAI\n");
-   goto err_pm_runtime;
+   goto err_pm_suspend;
}
 
ret = devm_snd_dmaengine_pcm_register(>dev, NULL, 0);
if (ret) {
dev_err(>dev, "Could not register PCM\n");
-   goto err_pm_runtime;
+   goto err_pm_suspend;
}
 
return 0;
 
+err_pm_suspend:
+   if (!pm_runtime_status_suspended(>dev))
+   rk_spdif_runtime_suspend(>dev);
 err_pm_runtime:
pm_runtime_disable(>dev);
-err_disable_clocks:
-   clk_disable_unprepare(spdif->mclk);
-err_disable_hclk:
-   clk_disable_unprepare(spdif->hclk);
 
return ret;
 }
 
 static int rk_spdif_remove(struct platform_device *pdev)
 {
-   struct rk_spdif_dev *spdif = dev_get_drvdata(>dev);
-
pm_runtime_disable(>dev);
if (!pm_runtime_status_suspended(>dev))
rk_spdif_runtime_suspend(>dev);
 
-   clk_disable_unprepare(spdif->mclk);
-   clk_disable_unprepare(spdif->hclk);
-
return 0;
 }
 
-- 
2.7.4





Re: [PATCH v2 01/13] dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'

2020-06-28 Thread sugar zhang



On 2020/6/24 15:54, Vinod Koul wrote:

On 09-06-20, 09:14, Sugar Zhang wrote:

There is no reason to limit the performance on the 'NO-FLUSHP' SoCs,
cuz these platforms are just that the 'FLUSHP' instruction is broken.

Lets not use terms like cuz... 'because' is perfect term :)

It can rephrased to:
There is no reason to limit the performance on the 'NO-FLUSHP' SoCs
beacuse 'FLUSHP' instruction is broken on these platforms, so remove the
limit to improve the efficiency

Thanks, I will send a v3 including these.



so, remove the limit to improve the efficiency.

Signed-off-by: Sugar Zhang 
---

Changes in v2: None

  drivers/dma/pl330.c | 34 ++
  1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6a158ee..ff0a91f 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1183,9 +1183,6 @@ static inline int _ldst_peripheral(struct pl330_dmac 
*pl330,
  {
int off = 0;
  
-	if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)

-   cond = BURST;
-
/*
 * do FLUSHP at beginning to clear any stale dma requests before the
 * first WFP.
@@ -1231,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned 
dry_run, u8 buf[],
  }
  
  /*

- * transfer dregs with single transfers to peripheral, or a reduced size burst
- * for mem-to-mem.
+ * only the unaligned bursts transfers have the dregs.
+ * transfer dregs with a reduced size burst to peripheral,
+ * or a reduced size burst for mem-to-mem.

This is not related to broken flush and should be a different patch
explaining why this changes were done

ok, I will split this patch in v3.

   */
  static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
const struct _xfer_spec *pxs, int transfer_length)
@@ -1247,8 +1245,23 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int 
dry_run, u8 buf[],
case DMA_MEM_TO_DEV:
/* fall through */
case DMA_DEV_TO_MEM:
-   off += _ldst_peripheral(pl330, dry_run, [off], pxs,
-   transfer_length, SINGLE);
+   /*
+* dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) /
+* BRST_SIZE(ccr)
+* the dregs len must be smaller than burst len,
+* so, for higher efficiency, we can modify CCR
+* to use a reduced size burst len for the dregs.
+*/
+   dregs_ccr = pxs->ccr;
+   dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
+   (0xf << CC_DSTBRSTLEN_SHFT));
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_SRCBRSTLEN_SHFT);
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_DSTBRSTLEN_SHFT);
+   off += _emit_MOV(dry_run, [off], CCR, dregs_ccr);
+   off += _ldst_peripheral(pl330, dry_run, [off], pxs, 1,
+   BURST);
break;
  
  	case DMA_MEM_TO_MEM:

@@ -2221,9 +2234,7 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan 
*pch,
  
  static int fixup_burst_len(int max_burst_len, int quirks)

  {
-   if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-   return 1;
-   else if (max_burst_len > PL330_MAX_BURST)
+   if (max_burst_len > PL330_MAX_BURST)
return PL330_MAX_BURST;
else if (max_burst_len < 1)
return 1;
@@ -3128,8 +3139,7 @@ pl330_probe(struct amba_device *adev, const struct 
amba_id *id)
pd->dst_addr_widths = PL330_DMA_BUSWIDTHS;
pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
-   pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ?
-1 : PL330_MAX_BURST);
+   pd->max_burst = PL330_MAX_BURST;
  
  	ret = dma_async_device_register(pd);

if (ret) {
--
2.7.4



--





Re: [PATCH v2 0/13] Patches to improve transfer efficiency for Rockchip SoCs.

2020-06-12 Thread sugar zhang

Hi Peter,

Thanks for testing! but, as I know, GMAC does not use the general 
dma(pl330) for data transfer,


so, these patchs should not be helpful for your case.

在 2020/6/12 9:15, Peter Geis 写道:

On Thu, Jun 11, 2020 at 9:06 PM Peter Geis  wrote:

Good Evening,

I am currently testing this on the rk3399-rockpro64, and it appears to
fully fix the gmac problem without using txpbl.
PCIe also seems to be more stable at high load.
I need to conduct long term testing, but it seems to be doing very well.

Belay that, it does make it harder to trigger, but the issue still
remains on the rk3399.


Unfortunately it doesn't fix the rk3328 gmac controller.

Tested-by: Peter Geis 

On Mon, Jun 8, 2020 at 9:15 PM Sugar Zhang  wrote:



Changes in v2:
- fix FATAL ERROR: Unable to parse input tree

Sugar Zhang (13):
   dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'
   dmaengine: pl330: Add quirk 'arm,pl330-periph-burst'
   dt-bindings: dma: pl330: Document the quirk 'arm,pl330-periph-burst'
   ARM: dts: rk3036: Add 'arm,pl330-periph-burst' for dmac
   ARM: dts: rk322x: Add 'arm,pl330-periph-burst' for dmac
   ARM: dts: rk3288: Add 'arm,pl330-periph-burst' for dmac
   ARM: dts: rk3xxx: Add 'arm,pl330-periph-burst' for dmac
   ARM: dts: rv1108: Add 'arm,pl330-periph-burst' for dmac
   arm64: dts: px30: Add 'arm,pl330-periph-burst' for dmac
   arm64: dts: rk3308: Add 'arm,pl330-periph-burst' for dmac
   arm64: dts: rk3328: Add 'arm,pl330-periph-burst' for dmac
   arm64: dts: rk3368: Add 'arm,pl330-periph-burst' for dmac
   arm64: dts: rk3399: Add 'arm,pl330-periph-burst' for dmac

  .../devicetree/bindings/dma/arm-pl330.txt  |  1 +
  arch/arm/boot/dts/rk3036.dtsi  |  1 +
  arch/arm/boot/dts/rk322x.dtsi  |  1 +
  arch/arm/boot/dts/rk3288.dtsi  |  3 ++
  arch/arm/boot/dts/rk3xxx.dtsi  |  3 ++
  arch/arm/boot/dts/rv1108.dtsi  |  1 +
  arch/arm64/boot/dts/rockchip/px30.dtsi |  1 +
  arch/arm64/boot/dts/rockchip/rk3308.dtsi   |  2 +
  arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  1 +
  arch/arm64/boot/dts/rockchip/rk3368.dtsi   |  2 +
  arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  2 +
  drivers/dma/pl330.c| 44 +++---
  12 files changed, 49 insertions(+), 13 deletions(-)

--
2.7.4




___
Linux-rockchip mailing list
linux-rockc...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip



--
Best Regards!
张学广/Sugar
福州瑞芯微电子股份有限公司
Fuzhou Rockchip Electronics Co.Ltd





[PATCH v2 03/13] dt-bindings: dma: pl330: Document the quirk 'arm,pl330-periph-burst'

2020-06-08 Thread Sugar Zhang
This patch Adds the quirk 'arm,pl330-periph-burst' for pl330.

Signed-off-by: Sugar Zhang 
---

Changes in v2: None

 Documentation/devicetree/bindings/dma/arm-pl330.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt 
b/Documentation/devicetree/bindings/dma/arm-pl330.txt
index 2c7fd19..315e901 100644
--- a/Documentation/devicetree/bindings/dma/arm-pl330.txt
+++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt
@@ -16,6 +16,7 @@ Optional properties:
   - dma-channels: contains the total number of DMA channels supported by the 
DMAC
   - dma-requests: contains the total number of DMA requests supported by the 
DMAC
   - arm,pl330-broken-no-flushp: quirk for avoiding to execute DMAFLUSHP
+  - arm,pl330-periph-burst: quirk for performing burst transfer only
   - resets: contains an entry for each entry in reset-names.
See ../reset/reset.txt for details.
   - reset-names: must contain at least "dma", and optional is "dma-ocp".
-- 
2.7.4





[PATCH v2 02/13] dmaengine: pl330: Add quirk 'arm,pl330-periph-burst'

2020-06-08 Thread Sugar Zhang
This patch adds the qurik to use busrt transfers only
for pl330 controller, even for request with a length of 1.

Although, the correct way should be: if the peripheral request
length is 1, the peripheral should use SINGLE request, and then
notify the dmac using SINGLE mode by src/dst_maxburst with 1.

For example, on the Rockchip SoCs, all the peripherals can use
SINGLE or BURST request by setting GRF registers. it is possible
that if these peripheral drivers are used only for Rockchip SoCs.
Unfortunately, it's not, such as dw uart, which is used so widely,
and we can't set src/dst_maxburst according to the SoCs' specific
to compatible with all the other SoCs.

So, for convenience, all the peripherals are set as BURST request
by default on the Rockchip SoCs. even for request with a length of 1.
the current pl330 driver will perform SINGLE transfer if the client's
maxburst is 1, which still should be working according to chapter 2.6.6
of datasheet which describe how DMAC performs SINGLE transfers for
a BURST request. unfortunately, it's broken on the Rockchip SoCs,
which support only matching transfers, such as BURST transfer for
BURST request, SINGLE transfer for SINGLE request.

Finaly, we add the quirk to specify pl330 to use burst transfers only.

Signed-off-by: Sugar Zhang 
---

Changes in v2: None

 drivers/dma/pl330.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index ff0a91f..1941ec6 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -33,7 +33,8 @@
 #define PL330_MAX_PERI 32
 #define PL330_MAX_BURST 16
 
-#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
+#define PL330_QUIRK_BROKEN_NO_FLUSHP   BIT(0)
+#define PL330_QUIRK_PERIPH_BURST   BIT(1)
 
 enum pl330_cachectrl {
CCTRL0, /* Noncacheable and nonbufferable */
@@ -509,6 +510,10 @@ static struct pl330_of_quirks {
{
.quirk = "arm,pl330-broken-no-flushp",
.id = PL330_QUIRK_BROKEN_NO_FLUSHP,
+   },
+   {
+   .quirk = "arm,pl330-periph-burst",
+   .id = PL330_QUIRK_PERIPH_BURST,
}
 };
 
@@ -1206,6 +1211,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned 
dry_run, u8 buf[],
int off = 0;
enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE;
 
+   if (pl330->quirks & PL330_QUIRK_PERIPH_BURST)
+   cond = BURST;
+
switch (pxs->desc->rqtype) {
case DMA_MEM_TO_DEV:
/* fall through */
-- 
2.7.4





[PATCH v2 01/13] dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'

2020-06-08 Thread Sugar Zhang
There is no reason to limit the performance on the 'NO-FLUSHP' SoCs,
cuz these platforms are just that the 'FLUSHP' instruction is broken.
so, remove the limit to improve the efficiency.

Signed-off-by: Sugar Zhang 
---

Changes in v2: None

 drivers/dma/pl330.c | 34 ++
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6a158ee..ff0a91f 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1183,9 +1183,6 @@ static inline int _ldst_peripheral(struct pl330_dmac 
*pl330,
 {
int off = 0;
 
-   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-   cond = BURST;
-
/*
 * do FLUSHP at beginning to clear any stale dma requests before the
 * first WFP.
@@ -1231,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned 
dry_run, u8 buf[],
 }
 
 /*
- * transfer dregs with single transfers to peripheral, or a reduced size burst
- * for mem-to-mem.
+ * only the unaligned bursts transfers have the dregs.
+ * transfer dregs with a reduced size burst to peripheral,
+ * or a reduced size burst for mem-to-mem.
  */
 static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
const struct _xfer_spec *pxs, int transfer_length)
@@ -1247,8 +1245,23 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int 
dry_run, u8 buf[],
case DMA_MEM_TO_DEV:
/* fall through */
case DMA_DEV_TO_MEM:
-   off += _ldst_peripheral(pl330, dry_run, [off], pxs,
-   transfer_length, SINGLE);
+   /*
+* dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) /
+* BRST_SIZE(ccr)
+* the dregs len must be smaller than burst len,
+* so, for higher efficiency, we can modify CCR
+* to use a reduced size burst len for the dregs.
+*/
+   dregs_ccr = pxs->ccr;
+   dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
+   (0xf << CC_DSTBRSTLEN_SHFT));
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_SRCBRSTLEN_SHFT);
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_DSTBRSTLEN_SHFT);
+   off += _emit_MOV(dry_run, [off], CCR, dregs_ccr);
+   off += _ldst_peripheral(pl330, dry_run, [off], pxs, 1,
+   BURST);
break;
 
case DMA_MEM_TO_MEM:
@@ -2221,9 +2234,7 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan 
*pch,
 
 static int fixup_burst_len(int max_burst_len, int quirks)
 {
-   if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-   return 1;
-   else if (max_burst_len > PL330_MAX_BURST)
+   if (max_burst_len > PL330_MAX_BURST)
return PL330_MAX_BURST;
else if (max_burst_len < 1)
return 1;
@@ -3128,8 +3139,7 @@ pl330_probe(struct amba_device *adev, const struct 
amba_id *id)
pd->dst_addr_widths = PL330_DMA_BUSWIDTHS;
pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
-   pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ?
-1 : PL330_MAX_BURST);
+   pd->max_burst = PL330_MAX_BURST;
 
ret = dma_async_device_register(pd);
if (ret) {
-- 
2.7.4





[PATCH v2 0/13] Patches to improve transfer efficiency for Rockchip SoCs.

2020-06-08 Thread Sugar Zhang



Changes in v2:
- fix FATAL ERROR: Unable to parse input tree

Sugar Zhang (13):
  dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'
  dmaengine: pl330: Add quirk 'arm,pl330-periph-burst'
  dt-bindings: dma: pl330: Document the quirk 'arm,pl330-periph-burst'
  ARM: dts: rk3036: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk322x: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk3288: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk3xxx: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rv1108: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: px30: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3308: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3328: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3368: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3399: Add 'arm,pl330-periph-burst' for dmac

 .../devicetree/bindings/dma/arm-pl330.txt  |  1 +
 arch/arm/boot/dts/rk3036.dtsi  |  1 +
 arch/arm/boot/dts/rk322x.dtsi  |  1 +
 arch/arm/boot/dts/rk3288.dtsi  |  3 ++
 arch/arm/boot/dts/rk3xxx.dtsi  |  3 ++
 arch/arm/boot/dts/rv1108.dtsi  |  1 +
 arch/arm64/boot/dts/rockchip/px30.dtsi |  1 +
 arch/arm64/boot/dts/rockchip/rk3308.dtsi   |  2 +
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  1 +
 arch/arm64/boot/dts/rockchip/rk3368.dtsi   |  2 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  2 +
 drivers/dma/pl330.c| 44 +++---
 12 files changed, 49 insertions(+), 13 deletions(-)

-- 
2.7.4





[PATCH v2 04/13] ARM: dts: rk3036: Add 'arm,pl330-periph-burst' for dmac

2020-06-08 Thread Sugar Zhang
This patch Add the quirk to specify to use burst transfer
for better compatible and higher performance.

Signed-off-by: Sugar Zhang 

---

Changes in v2:
- fix FATAL ERROR: Unable to parse input tree

 arch/arm/boot/dts/rk3036.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index d9a0c9a2..0935670 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -67,6 +67,7 @@
 ;
#dma-cells = <1>;
arm,pl330-broken-no-flushp;
+   arm,pl330-periph-burst;
clocks = < ACLK_DMAC2>;
clock-names = "apb_pclk";
};
-- 
2.7.4





[PATCH v1 03/13] dt-bindings: dma: pl330: Document the quirk 'arm,pl330-periph-burst'

2020-06-08 Thread Sugar Zhang
This patch Adds the quirk 'arm,pl330-periph-burst' for pl330.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/dma/arm-pl330.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt 
b/Documentation/devicetree/bindings/dma/arm-pl330.txt
index 2c7fd19..315e901 100644
--- a/Documentation/devicetree/bindings/dma/arm-pl330.txt
+++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt
@@ -16,6 +16,7 @@ Optional properties:
   - dma-channels: contains the total number of DMA channels supported by the 
DMAC
   - dma-requests: contains the total number of DMA requests supported by the 
DMAC
   - arm,pl330-broken-no-flushp: quirk for avoiding to execute DMAFLUSHP
+  - arm,pl330-periph-burst: quirk for performing burst transfer only
   - resets: contains an entry for each entry in reset-names.
See ../reset/reset.txt for details.
   - reset-names: must contain at least "dma", and optional is "dma-ocp".
-- 
2.7.4





[PATCH v1 02/13] dmaengine: pl330: Add quirk 'arm,pl330-periph-burst'

2020-06-08 Thread Sugar Zhang
This patch adds the qurik to use busrt transfers only
for pl330 controller, even for request with a length of 1.

Although, the correct way should be: if the peripheral request
length is 1, the peripheral should use SINGLE request, and then
notify the dmac using SINGLE mode by src/dst_maxburst with 1.

For example, on the Rockchip SoCs, all the peripherals can use
SINGLE or BURST request by setting GRF registers. it is possible
that if these peripheral drivers are used only for Rockchip SoCs.
Unfortunately, it's not, such as dw uart, which is used so widely,
and we can't set src/dst_maxburst according to the SoCs' specific
to compatible with all the other SoCs.

So, for convenience, all the peripherals are set as BURST request
by default on the Rockchip SoCs. even for request with a length of 1.
the current pl330 driver will perform SINGLE transfer if the client's
maxburst is 1, which still should be working according to chapter 2.6.6
of datasheet which describe how DMAC performs SINGLE transfers for
a BURST request. unfortunately, it's broken on the Rockchip SoCs,
which support only matching transfers, such as BURST transfer for
BURST request, SINGLE transfer for SINGLE request.

Finaly, we add the quirk to specify pl330 to use burst transfers only.

Signed-off-by: Sugar Zhang 
---

 drivers/dma/pl330.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index ff0a91f..1941ec6 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -33,7 +33,8 @@
 #define PL330_MAX_PERI 32
 #define PL330_MAX_BURST 16
 
-#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
+#define PL330_QUIRK_BROKEN_NO_FLUSHP   BIT(0)
+#define PL330_QUIRK_PERIPH_BURST   BIT(1)
 
 enum pl330_cachectrl {
CCTRL0, /* Noncacheable and nonbufferable */
@@ -509,6 +510,10 @@ static struct pl330_of_quirks {
{
.quirk = "arm,pl330-broken-no-flushp",
.id = PL330_QUIRK_BROKEN_NO_FLUSHP,
+   },
+   {
+   .quirk = "arm,pl330-periph-burst",
+   .id = PL330_QUIRK_PERIPH_BURST,
}
 };
 
@@ -1206,6 +1211,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned 
dry_run, u8 buf[],
int off = 0;
enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE;
 
+   if (pl330->quirks & PL330_QUIRK_PERIPH_BURST)
+   cond = BURST;
+
switch (pxs->desc->rqtype) {
case DMA_MEM_TO_DEV:
/* fall through */
-- 
2.7.4





[PATCH v1 01/13] dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'

2020-06-08 Thread Sugar Zhang
There is no reason to limit the performance on the 'NO-FLUSHP' SoCs,
cuz these platforms are just that the 'FLUSHP' instruction is broken.
so, remove the limit to improve the efficiency.

Signed-off-by: Sugar Zhang 
---

 drivers/dma/pl330.c | 34 ++
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6a158ee..ff0a91f 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1183,9 +1183,6 @@ static inline int _ldst_peripheral(struct pl330_dmac 
*pl330,
 {
int off = 0;
 
-   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-   cond = BURST;
-
/*
 * do FLUSHP at beginning to clear any stale dma requests before the
 * first WFP.
@@ -1231,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned 
dry_run, u8 buf[],
 }
 
 /*
- * transfer dregs with single transfers to peripheral, or a reduced size burst
- * for mem-to-mem.
+ * only the unaligned bursts transfers have the dregs.
+ * transfer dregs with a reduced size burst to peripheral,
+ * or a reduced size burst for mem-to-mem.
  */
 static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
const struct _xfer_spec *pxs, int transfer_length)
@@ -1247,8 +1245,23 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int 
dry_run, u8 buf[],
case DMA_MEM_TO_DEV:
/* fall through */
case DMA_DEV_TO_MEM:
-   off += _ldst_peripheral(pl330, dry_run, [off], pxs,
-   transfer_length, SINGLE);
+   /*
+* dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) /
+* BRST_SIZE(ccr)
+* the dregs len must be smaller than burst len,
+* so, for higher efficiency, we can modify CCR
+* to use a reduced size burst len for the dregs.
+*/
+   dregs_ccr = pxs->ccr;
+   dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
+   (0xf << CC_DSTBRSTLEN_SHFT));
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_SRCBRSTLEN_SHFT);
+   dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+   CC_DSTBRSTLEN_SHFT);
+   off += _emit_MOV(dry_run, [off], CCR, dregs_ccr);
+   off += _ldst_peripheral(pl330, dry_run, [off], pxs, 1,
+   BURST);
break;
 
case DMA_MEM_TO_MEM:
@@ -2221,9 +2234,7 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan 
*pch,
 
 static int fixup_burst_len(int max_burst_len, int quirks)
 {
-   if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-   return 1;
-   else if (max_burst_len > PL330_MAX_BURST)
+   if (max_burst_len > PL330_MAX_BURST)
return PL330_MAX_BURST;
else if (max_burst_len < 1)
return 1;
@@ -3128,8 +3139,7 @@ pl330_probe(struct amba_device *adev, const struct 
amba_id *id)
pd->dst_addr_widths = PL330_DMA_BUSWIDTHS;
pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
-   pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ?
-1 : PL330_MAX_BURST);
+   pd->max_burst = PL330_MAX_BURST;
 
ret = dma_async_device_register(pd);
if (ret) {
-- 
2.7.4





[PATCH v1 0/13] Patches to improve dma transfer efficiency for Rockchip SoCs.

2020-06-08 Thread Sugar Zhang




Sugar Zhang (13):
  dmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP'
  dmaengine: pl330: Add quirk 'arm,pl330-periph-burst'
  dt-bindings: dma: pl330: Document the quirk 'arm,pl330-periph-burst'
  ARM: dts: rk3036: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk322x: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk3288: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rk3xxx: Add 'arm,pl330-periph-burst' for dmac
  ARM: dts: rv1108: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: px30: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3308: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3328: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3368: Add 'arm,pl330-periph-burst' for dmac
  arm64: dts: rk3399: Add 'arm,pl330-periph-burst' for dmac

 .../devicetree/bindings/dma/arm-pl330.txt  |  1 +
 arch/arm/boot/dts/rk3036.dtsi  |  1 +
 arch/arm/boot/dts/rk322x.dtsi  |  1 +
 arch/arm/boot/dts/rk3288.dtsi  |  3 ++
 arch/arm/boot/dts/rk3xxx.dtsi  |  3 ++
 arch/arm/boot/dts/rv1108.dtsi  |  1 +
 arch/arm64/boot/dts/rockchip/px30.dtsi |  1 +
 arch/arm64/boot/dts/rockchip/rk3308.dtsi   |  2 +
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  1 +
 arch/arm64/boot/dts/rockchip/rk3368.dtsi   |  2 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  2 +
 drivers/dma/pl330.c| 44 +++---
 12 files changed, 49 insertions(+), 13 deletions(-)

-- 
2.7.4





[PATCH v1 04/13] ARM: dts: rk3036: Add 'arm,pl330-periph-burst' for dmac

2020-06-08 Thread Sugar Zhang
This patch Add the quirk to specify to use burst transfer
for better compatible and higher performance.

Signed-off-by: Sugar Zhang 
---

 arch/arm/boot/dts/rk3036.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index d9a0c9a2..cfec7d6 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -67,6 +67,7 @@
 ;
#dma-cells = <1>;
arm,pl330-broken-no-flushp;
++  arm,pl330-periph-burst;
clocks = < ACLK_DMAC2>;
clock-names = "apb_pclk";
};
-- 
2.7.4





[PATCH v1] dmaengine: pl330: Make sure the debug is idle before doing DMAGO

2020-06-03 Thread Sugar Zhang
According to the datasheet of pl330:

Example 2-1 Using DMAGO with the debug instruction registers

1. Create a program for the DMA channel
2. Store the program in a region of system memory
3. Poll the DBGSTATUS Register to ensure that the debug is idle
4. Write to the DBGINST0 Register
5. Write to the DBGINST1 Register
6. Write zero to the DBGCMD Register

so, we should make sure the debug is idle before step 4/5/6, not
only step 6. if not, there maybe a risk that fail to write DBGINST0/1.

Signed-off-by: Sugar Zhang 
---

 drivers/dma/pl330.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 88b884c..6a158ee 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -885,6 +885,12 @@ static inline void _execute_DBGINSN(struct pl330_thread 
*thrd,
void __iomem *regs = thrd->dmac->base;
u32 val;
 
+   /* If timed out due to halted state-machine */
+   if (_until_dmac_idle(thrd)) {
+   dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n");
+   return;
+   }
+
val = (insn[0] << 16) | (insn[1] << 24);
if (!as_manager) {
val |= (1 << 0);
@@ -895,12 +901,6 @@ static inline void _execute_DBGINSN(struct pl330_thread 
*thrd,
val = le32_to_cpu(*((__le32 *)[2]));
writel(val, regs + DBGINST1);
 
-   /* If timed out due to halted state-machine */
-   if (_until_dmac_idle(thrd)) {
-   dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n");
-   return;
-   }
-
/* Get going */
writel(0, regs + DBGCMD);
 }
-- 
2.7.4





[PATCH v1 12/12] ASoC: rockchip: pdm: Correct PDM_CTRL0 reg value

2019-04-03 Thread Sugar Zhang
This patch fix the wrong reg value for rk322x/rk322xh,
cuz there is no STORE JUSTIFIED MODE on it.

on rk322x/rk322xh, the same bit means PDM_MODE/RESERVED,
if the bit is set to RESERVED, the controller will not work.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index e89beeb..6c0f242 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -210,7 +210,9 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream 
*substream,
regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
   PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_EN, PDM_CLK_EN);
-   regmap_update_bits(pdm->regmap, PDM_CTRL0, PDM_MODE_MSK, PDM_MODE_LJ);
+   if (pdm->version != RK_PDM_RK3229)
+   regmap_update_bits(pdm->regmap, PDM_CTRL0,
+  PDM_MODE_MSK, PDM_MODE_LJ);
 
val = 0;
switch (params_format(params)) {
@@ -468,7 +470,8 @@ static const struct regmap_config 
rockchip_pdm_regmap_config = {
 };
 
 static const struct of_device_id rockchip_pdm_match[] = {
-   { .compatible = "rockchip,pdm", },
+   { .compatible = "rockchip,pdm",
+ .data = (void *)RK_PDM_RK3229 },
{ .compatible = "rockchip,px30-pdm",
  .data = (void *)RK_PDM_RK3308 },
{ .compatible = "rockchip,rk1808-pdm",
-- 
2.7.4





[PATCH v1 11/12] ASoC: rockchip: pdm: Mark RXFIFO_DATA as volatile and precious

2019-04-03 Thread Sugar Zhang
This patch marks RXFIFO_DATA as precious to avoid being read
outside a call from the driver, such as regmap debugfs

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 955cdc2..e89beeb 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -415,6 +415,7 @@ static bool rockchip_pdm_rd_reg(struct device *dev, 
unsigned int reg)
case PDM_INT_CLR:
case PDM_INT_ST:
case PDM_DATA_VALID:
+   case PDM_RXFIFO_DATA:
case PDM_VERSION:
return true;
default:
@@ -429,6 +430,17 @@ static bool rockchip_pdm_volatile_reg(struct device *dev, 
unsigned int reg)
case PDM_FIFO_CTRL:
case PDM_INT_CLR:
case PDM_INT_ST:
+   case PDM_RXFIFO_DATA:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static bool rockchip_pdm_precious_reg(struct device *dev, unsigned int reg)
+{
+   switch (reg) {
+   case PDM_RXFIFO_DATA:
return true;
default:
return false;
@@ -451,6 +463,7 @@ static const struct regmap_config 
rockchip_pdm_regmap_config = {
.writeable_reg = rockchip_pdm_wr_reg,
.readable_reg = rockchip_pdm_rd_reg,
.volatile_reg = rockchip_pdm_volatile_reg,
+   .precious_reg = rockchip_pdm_precious_reg,
.cache_type = REGCACHE_FLAT,
 };
 
-- 
2.7.4





[PATCH v1 10/12] ASoC: rockchip: pdm: adjust waterlevel in frame unit

2019-04-03 Thread Sugar Zhang
This patch make the waterlevel more reasonable, because the pdm
controller share the single FIFO(128 entries) with each channel.
adjust waterlevel in frame to meet the vad or dma frames request.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 3e1c5fd..955cdc2 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -255,8 +255,9 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream 
*substream,
regmap_update_bits(pdm->regmap, PDM_CTRL0,
   PDM_PATH_MSK | PDM_VDW_MSK,
   val);
+   /* all channels share the single FIFO */
regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK,
-  PDM_DMA_RDL(16));
+  PDM_DMA_RDL(8 * params_channels(params)));
 
return 0;
 }
-- 
2.7.4





[PATCH v1 09/12] dt-bindings: sound: add compatible for rk1808

2019-04-03 Thread Sugar Zhang
This patch adds bindings for rk1808 soc.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip,pdm.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
index 3e0eb73..98572a2 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -4,6 +4,7 @@ Required properties:
 
 - compatible: "rockchip,pdm"
   - "rockchip,px30-pdm"
+  - "rockchip,rk1808-pdm"
   - "rockchip,rk3308-pdm"
 - reg: physical base address of the controller and length of memory mapped
   region.
-- 
2.7.4





[PATCH v1 08/12] ASoC: rockchip: pdm: add compatible for rk1808

2019-04-03 Thread Sugar Zhang
This patch adds support for rk1808, the pdm controller
is the same as rk3308.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 4f93a74..3e1c5fd 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -457,6 +457,8 @@ static const struct of_device_id rockchip_pdm_match[] = {
{ .compatible = "rockchip,pdm", },
{ .compatible = "rockchip,px30-pdm",
  .data = (void *)RK_PDM_RK3308 },
+   { .compatible = "rockchip,rk1808-pdm",
+ .data = (void *)RK_PDM_RK3308 },
{ .compatible = "rockchip,rk3308-pdm",
  .data = (void *)RK_PDM_RK3308 },
{},
-- 
2.7.4





[PATCH v1 07/12] dt-bindings: sound: rockchip: add compatible for rk3308/px30

2019-04-03 Thread Sugar Zhang
This patch adds bindings for rk3308/px30.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip,pdm.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
index 47f164f..3e0eb73 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -3,6 +3,8 @@
 Required properties:
 
 - compatible: "rockchip,pdm"
+  - "rockchip,px30-pdm"
+  - "rockchip,rk3308-pdm"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - dmas: DMA specifiers for rx dma. See the DMA client binding,
@@ -12,6 +14,8 @@ Required properties:
 - clock-names: should contain following:
- "pdm_hclk": clock for PDM BUS
- "pdm_clk" : clock for PDM controller
+- resets: a list of phandle + reset-specifer paris, one for each entry in 
reset-names.
+- reset-names: reset names, should include "pdm-m".
 - pinctrl-names: Must contain a "default" entry.
 - pinctrl-N: One property must exist for each entry in
 pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
-- 
2.7.4





[PATCH v1 06/12] ASoC: rockchip: pdm: fixup pdm fractional div

2019-04-03 Thread Sugar Zhang
This patch adds support fractional div for rk3308.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 172 --
 sound/soc/rockchip/rockchip_pdm.h |   9 ++
 2 files changed, 139 insertions(+), 42 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index c50494b..4f93a74 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -17,14 +17,23 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
 #include "rockchip_pdm.h"
 
 #define PDM_DMA_BURST_SIZE (8) /* size * width: 8*4 = 32 bytes */
+#define PDM_SIGNOFF_CLK_RATE   (1)
+
+enum rk_pdm_version {
+   RK_PDM_RK3229,
+   RK_PDM_RK3308,
+};
 
 struct rk_pdm_dev {
struct device *dev;
@@ -32,22 +41,51 @@ struct rk_pdm_dev {
struct clk *hclk;
struct regmap *regmap;
struct snd_dmaengine_dai_dma_data capture_dma_data;
+   struct reset_control *reset;
+   enum rk_pdm_version version;
 };
 
 struct rk_pdm_clkref {
unsigned int sr;
unsigned int clk;
+   unsigned int clk_out;
+};
+
+struct rk_pdm_ds_ratio {
+   unsigned int ratio;
+   unsigned int sr;
 };
 
 static struct rk_pdm_clkref clkref[] = {
-   { 8000, 4096 },
-   { 11025, 56448000 },
-   { 12000, 6144 },
+   { 8000, 4096, 2048000 },
+   { 11025, 56448000, 2822400 },
+   { 12000, 6144, 3072000 },
+   { 8000, 98304000, 2048000 },
+   { 12000, 98304000, 3072000 },
+};
+
+static struct rk_pdm_ds_ratio ds_ratio[] = {
+   { 0, 192000 },
+   { 0, 176400 },
+   { 0, 128000 },
+   { 1, 96000 },
+   { 1, 88200 },
+   { 1, 64000 },
+   { 2, 48000 },
+   { 2, 44100 },
+   { 2, 32000 },
+   { 3, 24000 },
+   { 3, 22050 },
+   { 3, 16000 },
+   { 4, 12000 },
+   { 4, 11025 },
+   { 4, 8000 },
 };
 
-static unsigned int get_pdm_clk(unsigned int sr)
+static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
+   unsigned int *clk_src, unsigned int *clk_out)
 {
-   unsigned int i, count, clk, div;
+   unsigned int i, count, clk, div, rate;
 
clk = 0;
if (!sr)
@@ -59,14 +97,39 @@ static unsigned int get_pdm_clk(unsigned int sr)
continue;
div = sr / clkref[i].sr;
if ((div & (div - 1)) == 0) {
+   *clk_out = clkref[i].clk_out;
+   rate = clk_round_rate(pdm->clk, clkref[i].clk);
+   if (rate != clkref[i].clk)
+   continue;
clk = clkref[i].clk;
+   *clk_src = clkref[i].clk;
break;
}
}
 
+   if (!clk) {
+   clk = clk_round_rate(pdm->clk, PDM_SIGNOFF_CLK_RATE);
+   *clk_src = clk;
+   }
return clk;
 }
 
+static unsigned int get_pdm_ds_ratio(unsigned int sr)
+{
+   unsigned int i, count, ratio;
+
+   ratio = 0;
+   if (!sr)
+   return ratio;
+
+   count = ARRAY_SIZE(ds_ratio);
+   for (i = 0; i < count; i++) {
+   if (sr == ds_ratio[i].sr)
+   ratio = ds_ratio[i].ratio;
+   }
+   return ratio;
+}
+
 static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai)
 {
return snd_soc_dai_get_drvdata(dai);
@@ -95,40 +158,52 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream 
*substream,
struct rk_pdm_dev *pdm = to_info(dai);
unsigned int val = 0;
unsigned int clk_rate, clk_div, samplerate;
+   unsigned int clk_src, clk_out;
+   unsigned long m, n;
+   bool change;
int ret;
 
+   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+   return 0;
+
samplerate = params_rate(params);
-   clk_rate = get_pdm_clk(samplerate);
+   clk_rate = get_pdm_clk(pdm, samplerate, _src, _out);
if (!clk_rate)
return -EINVAL;
 
-   ret = clk_set_rate(pdm->clk, clk_rate);
+   ret = clk_set_rate(pdm->clk, clk_src);
if (ret)
return -EINVAL;
 
-   clk_div = DIV_ROUND_CLOSEST(clk_rate, samplerate);
-
-   switch (clk_div) {
-   case 320:
-   val = PDM_CLK_320FS;
-   break;
-   case 640:
-   val = PDM_CLK_640FS;
-   break;
-   case 1280:
-   val = PDM_CLK_1280FS;
-   break;
-   case 2560:
-   val = PDM_CLK_2560FS;
-   break;
-   case 5120:
-   val = PDM_CLK_5120FS;
-   break;
-   default:
-   dev_err(pdm->dev, "unsupported div: %d\n", clk_div);
-   return -EINVAL;
+   if (pdm->version == RK_PDM_RK330

[PATCH v1 05/12] ASoC: rockchip: pdm: change dma burst to 8

2019-04-03 Thread Sugar Zhang
This patch decreases the transfer bursts to avoid the fifo overrun.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index abbb6d7..c50494b 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -24,7 +24,7 @@
 
 #include "rockchip_pdm.h"
 
-#define PDM_DMA_BURST_SIZE (16) /* size * width: 16*4 = 64 bytes */
+#define PDM_DMA_BURST_SIZE (8) /* size * width: 8*4 = 32 bytes */
 
 struct rk_pdm_dev {
struct device *dev;
-- 
2.7.4





[PATCH v1 02/12] ASoC: rockchip: pdm: using left justified store mode

2019-04-03 Thread Sugar Zhang
This patch set left justified store mode default.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 1 +
 sound/soc/rockchip/rockchip_pdm.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 8a2e3bb..360ebf2 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -135,6 +135,7 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream 
*substream,
regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
   PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_EN, PDM_CLK_EN);
+   regmap_update_bits(pdm->regmap, PDM_CTRL0, PDM_MODE_MSK, PDM_MODE_LJ);
 
val = 0;
switch (params_format(params)) {
diff --git a/sound/soc/rockchip/rockchip_pdm.h 
b/sound/soc/rockchip/rockchip_pdm.h
index 886b48d1..00a8fa1 100644
--- a/sound/soc/rockchip/rockchip_pdm.h
+++ b/sound/soc/rockchip/rockchip_pdm.h
@@ -42,6 +42,9 @@
 
 /* PDM CTRL0 */
 #define PDM_PATH_MSK   (0xf << 27)
+#define PDM_MODE_MSK   BIT(31)
+#define PDM_MODE_RJ0
+#define PDM_MODE_LJBIT(31)
 #define PDM_PATH3_EN   BIT(30)
 #define PDM_PATH2_EN   BIT(29)
 #define PDM_PATH1_EN   BIT(28)
-- 
2.7.4





[PATCH v1 03/12] ASoC: rockchip: pdm: add default regs

2019-04-03 Thread Sugar Zhang
This patch add default regs value for controller.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 360ebf2..8c1be59 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -363,11 +363,19 @@ static bool rockchip_pdm_volatile_reg(struct device *dev, 
unsigned int reg)
}
 }
 
+static const struct reg_default rockchip_pdm_reg_defaults[] = {
+   {0x04, 0x7817},
+   {0x08, 0x0bb8ea60},
+   {0x18, 0x001f},
+};
+
 static const struct regmap_config rockchip_pdm_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = PDM_VERSION,
+   .reg_defaults = rockchip_pdm_reg_defaults,
+   .num_reg_defaults = ARRAY_SIZE(rockchip_pdm_reg_defaults),
.writeable_reg = rockchip_pdm_wr_reg,
.readable_reg = rockchip_pdm_rd_reg,
.volatile_reg = rockchip_pdm_volatile_reg,
-- 
2.7.4





[PATCH v1 04/12] ASoC: rockchip: pdm: optimize clear logic

2019-04-03 Thread Sugar Zhang
There is no need to reset controller every time, do this
once in pdm_probe.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 8c1be59..abbb6d7 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -183,9 +183,6 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream 
*substream,
   val);
regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK,
   PDM_DMA_RDL(16));
-   regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
-  PDM_RX_MASK | PDM_RX_CLR_MASK,
-  PDM_RX_STOP | PDM_RX_CLR_WR);
}
 
return 0;
@@ -355,6 +352,7 @@ static bool rockchip_pdm_volatile_reg(struct device *dev, 
unsigned int reg)
 {
switch (reg) {
case PDM_SYSCONFIG:
+   case PDM_FIFO_CTRL:
case PDM_INT_CLR:
case PDM_INT_ST:
return true;
@@ -438,6 +436,7 @@ static int rockchip_pdm_probe(struct platform_device *pdev)
goto err_suspend;
}
 
+   rockchip_pdm_rxctrl(pdm, 0);
ret = devm_snd_dmaengine_pcm_register(>dev, NULL, 0);
if (ret) {
dev_err(>dev, "could not register pcm: %d\n", ret);
-- 
2.7.4





[PATCH v1 01/12] ASoC: rockchip: pdm: fix regmap_ops hang issue

2019-04-03 Thread Sugar Zhang
This is because set_fmt ops maybe called when PD is off,
and in such case, regmap_ops will lead system hang.
enale PD before doing regmap_ops.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_pdm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
index 400e29e..8a2e3bb 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -208,7 +208,9 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
 
+   pm_runtime_get_sync(cpu_dai->dev);
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
+   pm_runtime_put(cpu_dai->dev);
 
return 0;
 }
-- 
2.7.4





[PATCH v1 0/12] Patches to update pdm for rockchip socs

2019-04-03 Thread Sugar Zhang
These patches to add support pdm for rk322x/rk1808/rk3308/px30 socs
and fix some issues.


Sugar Zhang (12):
  ASoC: rockchip: pdm: fix regmap_ops hang issue
  ASoC: rockchip: pdm: using left justified store mode
  ASoC: rockchip: pdm: add default regs
  ASoC: rockchip: pdm: optimize clear logic
  ASoC: rockchip: pdm: change dma burst to 8
  ASoC: rockchip: pdm: fixup pdm fractional div
  dt-bindings: sound: rockchip: add compatible for rk3308/px30
  ASoC: rockchip: pdm: add compatible for rk1808
  dt-bindings: sound: add compatible for rk1808
  ASoC: rockchip: pdm: adjust waterlevel in frame unit
  ASoC: rockchip: pdm: Mark RXFIFO_DATA as volatile and precious
  ASoC: rockchip: pdm: Correct PDM_CTRL0 reg value

 .../devicetree/bindings/sound/rockchip,pdm.txt |   5 +
 sound/soc/rockchip/rockchip_pdm.c  | 209 -
 sound/soc/rockchip/rockchip_pdm.h  |  12 ++
 3 files changed, 180 insertions(+), 46 deletions(-)

-- 
2.7.4





[PATCH] dmaengine: pl330: _stop: clear interrupt status

2019-04-03 Thread Sugar Zhang
This patch kill instructs the DMAC to immediately terminate
execution of a thread. and then clear the interrupt status,
at last, stop generating interrupts for DMA_SEV. to guarantee
the next dma start is clean. otherwise, one interrupt maybe leave
to next start and make some mistake.

we can reporduce the problem as follows:

DMASEV: modify the event-interrupt resource, and if the INTEN sets
function as interrupt, the DMAC will set irq HIGH to
generate interrupt. write INTCLR to clear interrupt.

DMA EXECUTING INSTRUCTS DMA TERMINATE
|   |
|   |
   ..._stop
|   |
|   spin_lock_irqsave
 DMASEV |
|   |
|   mask INTEN
|   |
|DMAKILL
|   |
|   spin_unlock_irqrestore

in above case, a interrupt was left, and if we unmask INTEN, the DMAC
will set irq HIGH to generate interrupt.

to fix this, do as follows:

DMA EXECUTING INSTRUCTS DMA TERMINATE
|   |
|   |
   ..._stop
|   |
|   spin_lock_irqsave
 DMASEV |
|   |
|DMAKILL
|   |
|  clear INTCLR
|   mask INTEN
|   |
|   spin_unlock_irqrestore

Signed-off-by: Sugar Zhang 
---

 drivers/dma/pl330.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index eec79fd..56695ff 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -966,6 +966,7 @@ static void _stop(struct pl330_thread *thrd)
 {
void __iomem *regs = thrd->dmac->base;
u8 insn[6] = {0, 0, 0, 0, 0, 0};
+   u32 inten = readl(regs + INTEN);
 
if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
@@ -978,10 +979,13 @@ static void _stop(struct pl330_thread *thrd)
 
_emit_KILL(0, insn);
 
-   /* Stop generating interrupts for SEV */
-   writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
-
_execute_DBGINSN(thrd, insn, is_manager(thrd));
+
+   /* clear the event */
+   if (inten & (1 << thrd->ev))
+   writel(1 << thrd->ev, regs + INTCLR);
+   /* Stop generating interrupts for SEV */
+   writel(inten & ~(1 << thrd->ev), regs + INTEN);
 }
 
 /* Start doing req 'idx' of thread 'thrd' */
-- 
2.7.4





[PATCH v2 1/2] arm64: dts: rockchip: add rk3328 pdm node

2017-08-21 Thread Sugar Zhang
This patch add pdm controller device node for rk3328.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

Changes in v2:
- separate pinctrl pins
  remove unused fsync clk, it's debug pins

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 77 
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 0be96ce..c4f52ec 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,27 @@
clock-output-names = "xin24m";
};
 
+   pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = < SCLK_PDM>, < HCLK_PDM>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_clk_sleep
+_sdi0_sleep
+_sdi1_sleep
+_sdi2_sleep
+_sdi3_sleep>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
@@ -734,6 +755,62 @@
};
};
 
+   pdm-0 {
+   pdmm0_clk: pdmm0-clk {
+   rockchip,pins = <2 RK_PC2 2 _pull_none>;
+   };
+
+   pdmm0_fsync: pdmm0-fsync {
+   rockchip,pins = <2 RK_PC7 2 _pull_none>;
+   };
+
+   pdmm0_sdi0: pdmm0-sdi0 {
+   rockchip,pins = <2 RK_PC3 2 _pull_none>;
+   };
+
+   pdmm0_sdi1: pdmm0-sdi1 {
+   rockchip,pins = <2 RK_PC4 2 _pull_none>;
+   };
+
+   pdmm0_sdi2: pdmm0-sdi2 {
+   rockchip,pins = <2 RK_PC5 2 _pull_none>;
+   };
+
+   pdmm0_sdi3: pdmm0-sdi3 {
+   rockchip,pins = <2 RK_PC6 2 _pull_none>;
+   };
+
+   pdmm0_clk_sleep: pdmm0-clk-sleep {
+   rockchip,pins =
+   <2 RK_PC2 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi0_sleep: pdmm0-sdi0-sleep {
+   rockchip,pins =
+   <2 RK_PC3 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi1_sleep: pdmm0-sdi1-sleep {
+   rockchip,pins =
+   <2 RK_PC4 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi2_sleep: pdmm0-sdi2-sleep {
+   rockchip,pins =
+   <2 RK_PC5 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi3_sleep: pdmm0-sdi3-sleep {
+   rockchip,pins =
+   <2 RK_PC6 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_fsync_sleep: pdmm0-fsync-sleep {
+   rockchip,pins =
+   <2 RK_PC7 RK_FUNC_GPIO 
_input_high>;
+   };
+   };
+
i2s1 {
i2s1_mclk: i2s1-mclk {
rockchip,pins = <2 RK_PB7 1 _pull_none>;
-- 
2.7.4




[PATCH v2 2/2] ASoC: rockchip: separate pinctrl pins from each other

2017-08-21 Thread Sugar Zhang
pdm sdi0~3 pins are optional, for example, if 4ch required,
only sdi0~1 need to be enabled.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

Changes in v2: None

 Documentation/devicetree/bindings/sound/rockchip,pdm.txt | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
index 921729d..2ad66f6 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -29,11 +29,14 @@ pdm: pdm@ff04 {
dma-names = "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <_clk
-_fsync
 _sdi0
 _sdi1
 _sdi2
 _sdi3>;
-   pinctrl-1 = <_sleep>;
+   pinctrl-1 = <_clk_sleep
+_sdi0_sleep
+_sdi1_sleep
+_sdi2_sleep
+_sdi3_sleep>;
status = "disabled";
 };
-- 
2.7.4




[PATCH v2 1/2] arm64: dts: rockchip: add rk3328 pdm node

2017-08-21 Thread Sugar Zhang
This patch add pdm controller device node for rk3328.

Signed-off-by: Sugar Zhang 

---

Changes in v2:
- separate pinctrl pins
  remove unused fsync clk, it's debug pins

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 77 
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 0be96ce..c4f52ec 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,27 @@
clock-output-names = "xin24m";
};
 
+   pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = < SCLK_PDM>, < HCLK_PDM>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_clk_sleep
+_sdi0_sleep
+_sdi1_sleep
+_sdi2_sleep
+_sdi3_sleep>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
@@ -734,6 +755,62 @@
};
};
 
+   pdm-0 {
+   pdmm0_clk: pdmm0-clk {
+   rockchip,pins = <2 RK_PC2 2 _pull_none>;
+   };
+
+   pdmm0_fsync: pdmm0-fsync {
+   rockchip,pins = <2 RK_PC7 2 _pull_none>;
+   };
+
+   pdmm0_sdi0: pdmm0-sdi0 {
+   rockchip,pins = <2 RK_PC3 2 _pull_none>;
+   };
+
+   pdmm0_sdi1: pdmm0-sdi1 {
+   rockchip,pins = <2 RK_PC4 2 _pull_none>;
+   };
+
+   pdmm0_sdi2: pdmm0-sdi2 {
+   rockchip,pins = <2 RK_PC5 2 _pull_none>;
+   };
+
+   pdmm0_sdi3: pdmm0-sdi3 {
+   rockchip,pins = <2 RK_PC6 2 _pull_none>;
+   };
+
+   pdmm0_clk_sleep: pdmm0-clk-sleep {
+   rockchip,pins =
+   <2 RK_PC2 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi0_sleep: pdmm0-sdi0-sleep {
+   rockchip,pins =
+   <2 RK_PC3 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi1_sleep: pdmm0-sdi1-sleep {
+   rockchip,pins =
+   <2 RK_PC4 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi2_sleep: pdmm0-sdi2-sleep {
+   rockchip,pins =
+   <2 RK_PC5 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_sdi3_sleep: pdmm0-sdi3-sleep {
+   rockchip,pins =
+   <2 RK_PC6 RK_FUNC_GPIO 
_input_high>;
+   };
+
+   pdmm0_fsync_sleep: pdmm0-fsync-sleep {
+   rockchip,pins =
+   <2 RK_PC7 RK_FUNC_GPIO 
_input_high>;
+   };
+   };
+
i2s1 {
i2s1_mclk: i2s1-mclk {
rockchip,pins = <2 RK_PB7 1 _pull_none>;
-- 
2.7.4




[PATCH v2 2/2] ASoC: rockchip: separate pinctrl pins from each other

2017-08-21 Thread Sugar Zhang
pdm sdi0~3 pins are optional, for example, if 4ch required,
only sdi0~1 need to be enabled.

Signed-off-by: Sugar Zhang 
---

Changes in v2: None

 Documentation/devicetree/bindings/sound/rockchip,pdm.txt | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
index 921729d..2ad66f6 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -29,11 +29,14 @@ pdm: pdm@ff04 {
dma-names = "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <_clk
-_fsync
 _sdi0
 _sdi1
 _sdi2
 _sdi3>;
-   pinctrl-1 = <_sleep>;
+   pinctrl-1 = <_clk_sleep
+_sdi0_sleep
+_sdi1_sleep
+_sdi2_sleep
+_sdi3_sleep>;
status = "disabled";
 };
-- 
2.7.4




[PATCH v2 0/2] Patches to add support pdm controller for rk3328

2017-08-21 Thread Sugar Zhang
These patches to add support pdm for rk3328 socs.

Changes in v2:
- separate pinctrl pins
  remove unused fsync clk, it's debug pins

Sugar Zhang (2):
  arm64: dts: rockchip: add rk3328 pdm node
  ASoC: rockchip: separate pinctrl pins from each other

 .../devicetree/bindings/sound/rockchip,pdm.txt |  7 +-
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   | 77 ++
 2 files changed, 82 insertions(+), 2 deletions(-)

-- 
2.7.4




[PATCH v2 0/2] Patches to add support pdm controller for rk3328

2017-08-21 Thread Sugar Zhang
These patches to add support pdm for rk3328 socs.

Changes in v2:
- separate pinctrl pins
  remove unused fsync clk, it's debug pins

Sugar Zhang (2):
  arm64: dts: rockchip: add rk3328 pdm node
  ASoC: rockchip: separate pinctrl pins from each other

 .../devicetree/bindings/sound/rockchip,pdm.txt |  7 +-
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   | 77 ++
 2 files changed, 82 insertions(+), 2 deletions(-)

-- 
2.7.4




[PATCH] ASoC: rockchip: add bindings for i2s

2017-07-30 Thread Sugar Zhang
This patch add bindings for rk3036/rk3228/rk3328/rk3366 i2s.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 Documentation/devicetree/bindings/sound/rockchip-i2s.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 206aba1..b208a75 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -7,8 +7,12 @@ Required properties:
 
 - compatible: should be one of the following:
- "rockchip,rk3066-i2s": for rk3066
+   - "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+   - "rockchip,rk3228-i2s", "rockchip,rk3066-i2s": for rk3228
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+   - "rockchip,rk3328-i2s", "rockchip,rk3066-i2s": for rk3328
+   - "rockchip,rk3366-i2s", "rockchip,rk3066-i2s": for rk3366
- "rockchip,rk3368-i2s", "rockchip,rk3066-i2s": for rk3368
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
 - reg: physical base address of the controller and length of memory mapped
-- 
2.7.4




[PATCH] ASoC: rockchip: add bindings for i2s

2017-07-30 Thread Sugar Zhang
This patch add bindings for rk3036/rk3228/rk3328/rk3366 i2s.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip-i2s.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 206aba1..b208a75 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -7,8 +7,12 @@ Required properties:
 
 - compatible: should be one of the following:
- "rockchip,rk3066-i2s": for rk3066
+   - "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+   - "rockchip,rk3228-i2s", "rockchip,rk3066-i2s": for rk3228
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+   - "rockchip,rk3328-i2s", "rockchip,rk3066-i2s": for rk3328
+   - "rockchip,rk3366-i2s", "rockchip,rk3066-i2s": for rk3366
- "rockchip,rk3368-i2s", "rockchip,rk3066-i2s": for rk3368
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
 - reg: physical base address of the controller and length of memory mapped
-- 
2.7.4




[PATCH v1 0/2] Patches to add i2s, spdif node for rk3328

2017-07-27 Thread Sugar Zhang
These patches to add i2s, spdif dt nodes for rk3328 soc.


Sugar Zhang (2):
  arm64: dts: rockchip: add rk3328 i2s nodes
  arm64: dts: rockchip: add rk3328 spdif node

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 46 
 1 file changed, 46 insertions(+)

-- 
2.7.4




[PATCH v1 0/2] Patches to add i2s, spdif node for rk3328

2017-07-27 Thread Sugar Zhang
These patches to add i2s, spdif dt nodes for rk3328 soc.


Sugar Zhang (2):
  arm64: dts: rockchip: add rk3328 i2s nodes
  arm64: dts: rockchip: add rk3328 spdif node

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 46 
 1 file changed, 46 insertions(+)

-- 
2.7.4




[PATCH v1 2/2] arm64: dts: rockchip: add rk3328 spdif node

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk3328.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index f1a284b..d278670 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -189,6 +189,19 @@
status = "disabled";
};
 
+   spdif: spdif@ff03 {
+   compatible = "rockchip,rk3328-spdif";
+   reg = <0x0 0xff03 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
-- 
2.7.4




[PATCH v1 1/2] arm64: dts: rockchip: add rk3328 i2s nodes

2017-07-27 Thread Sugar Zhang
This patch add the i2s dt nodes for rk3328.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 33 
 1 file changed, 33 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 0be96ce..f1a284b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,39 @@
clock-output-names = "xin24m";
};
 
+   i2s0: i2s@ff00 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff00 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S0>, < HCLK_I2S0_8CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 11>, < 12>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
+   i2s1: i2s@ff01 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff01 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S1>, < HCLK_I2S1_8CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 14>, < 15>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
+   i2s2: i2s@ff02 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff02 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S2>, < HCLK_I2S2_2CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 0>, < 1>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
-- 
2.7.4




[PATCH v1 2/2] arm64: dts: rockchip: add rk3328 spdif node

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk3328.

Signed-off-by: Sugar Zhang 

---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index f1a284b..d278670 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -189,6 +189,19 @@
status = "disabled";
};
 
+   spdif: spdif@ff03 {
+   compatible = "rockchip,rk3328-spdif";
+   reg = <0x0 0xff03 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
-- 
2.7.4




[PATCH v1 1/2] arm64: dts: rockchip: add rk3328 i2s nodes

2017-07-27 Thread Sugar Zhang
This patch add the i2s dt nodes for rk3328.

Signed-off-by: Sugar Zhang 
---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 33 
 1 file changed, 33 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 0be96ce..f1a284b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,39 @@
clock-output-names = "xin24m";
};
 
+   i2s0: i2s@ff00 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff00 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S0>, < HCLK_I2S0_8CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 11>, < 12>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
+   i2s1: i2s@ff01 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff01 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S1>, < HCLK_I2S1_8CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 14>, < 15>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
+   i2s2: i2s@ff02 {
+   compatible = "rockchip,rk3328-i2s", "rockchip,rk3066-i2s";
+   reg = <0x0 0xff02 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_I2S2>, < HCLK_I2S2_2CH>;
+   clock-names = "i2s_clk", "i2s_hclk";
+   dmas = < 0>, < 1>;
+   dma-names = "tx", "rx";
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
-- 
2.7.4




[PATCH] arm64: dts: rockchip: add rk3368 spdif node

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk3368 soc.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 6d5dc05..59c4158 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -700,6 +700,19 @@
interrupts = ;
};
 
+   spdif: spdif@ff88 {
+   compatible = "rockchip,rk3368-spdif";
+   reg = <0x0 0xff88 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF_8CH>, < HCLK_SPDIF>;
+   clock-names = "mclk", "hclk";
+   dmas = <_bus 3>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s_2ch: i2s-2ch@ff89 {
compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
reg = <0x0 0xff89 0x0 0x1000>;
@@ -1024,6 +1037,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <2 23 RK_FUNC_1 
_pull_none>;
+   };
+   };
+
spi0 {
spi0_clk: spi0-clk {
rockchip,pins = <1 29 RK_FUNC_2 _pull_up>;
-- 
2.7.4




[PATCH] arm64: dts: rockchip: add rk3368 spdif node

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk3368 soc.

Signed-off-by: Sugar Zhang 
---

 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 6d5dc05..59c4158 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -700,6 +700,19 @@
interrupts = ;
};
 
+   spdif: spdif@ff88 {
+   compatible = "rockchip,rk3368-spdif";
+   reg = <0x0 0xff88 0x0 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF_8CH>, < HCLK_SPDIF>;
+   clock-names = "mclk", "hclk";
+   dmas = <_bus 3>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s_2ch: i2s-2ch@ff89 {
compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
reg = <0x0 0xff89 0x0 0x1000>;
@@ -1024,6 +1037,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <2 23 RK_FUNC_1 
_pull_none>;
+   };
+   };
+
spi0 {
spi0_clk: spi0-clk {
rockchip,pins = <1 29 RK_FUNC_2 _pull_up>;
-- 
2.7.4




[PATCH] ARM: dts: rockchip: add spdif for rk322x SoCs

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk322x SoCs.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 arch/arm/boot/dts/rk322x.dtsi | 20 
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index f3e4ffd..b3b80e1 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -196,6 +196,20 @@
status = "disabled";
};
 
+   spdif: spdif@100d {
+   compatible = "rockchip,rk3228-spdif";
+   reg = <0x100d 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   #dma-cells = <1>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s2: i2s2@100e {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100e 0x4000>;
@@ -835,6 +849,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <3 31 RK_FUNC_2 
_pull_none>;
+   };
+   };
+
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 24 RK_FUNC_GPIO 
_pull_none>;
-- 
2.7.4




[PATCH] ARM: dts: rockchip: add spdif for rk322x SoCs

2017-07-27 Thread Sugar Zhang
This patch add the spdif dt node for rk322x SoCs.

Signed-off-by: Sugar Zhang 
---

 arch/arm/boot/dts/rk322x.dtsi | 20 
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index f3e4ffd..b3b80e1 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -196,6 +196,20 @@
status = "disabled";
};
 
+   spdif: spdif@100d {
+   compatible = "rockchip,rk3228-spdif";
+   reg = <0x100d 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   #dma-cells = <1>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s2: i2s2@100e {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100e 0x4000>;
@@ -835,6 +849,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <3 31 RK_FUNC_2 
_pull_none>;
+   };
+   };
+
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 24 RK_FUNC_GPIO 
_pull_none>;
-- 
2.7.4




[PATCH v1 0/2] Patches to add support pdm controller for rk3328

2017-06-13 Thread Sugar Zhang
These patches to add support pdm for rk3328 socs.


Sugar Zhang (2):
  ASoC: rockchip: add support for pdm controller
  arm64: dts: rk3328: add pdm node

 .../devicetree/bindings/sound/rockchip,pdm.txt |  39 ++
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  55 +++
 sound/soc/rockchip/Kconfig |   9 +
 sound/soc/rockchip/Makefile|   2 +
 sound/soc/rockchip/rockchip_pdm.c  | 516 +
 sound/soc/rockchip/rockchip_pdm.h  |  83 
 6 files changed, 704 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,pdm.txt
 create mode 100644 sound/soc/rockchip/rockchip_pdm.c
 create mode 100644 sound/soc/rockchip/rockchip_pdm.h

-- 
1.9.1




[PATCH v1 0/2] Patches to add support pdm controller for rk3328

2017-06-13 Thread Sugar Zhang
These patches to add support pdm for rk3328 socs.


Sugar Zhang (2):
  ASoC: rockchip: add support for pdm controller
  arm64: dts: rk3328: add pdm node

 .../devicetree/bindings/sound/rockchip,pdm.txt |  39 ++
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  55 +++
 sound/soc/rockchip/Kconfig |   9 +
 sound/soc/rockchip/Makefile|   2 +
 sound/soc/rockchip/rockchip_pdm.c  | 516 +
 sound/soc/rockchip/rockchip_pdm.h  |  83 
 6 files changed, 704 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,pdm.txt
 create mode 100644 sound/soc/rockchip/rockchip_pdm.c
 create mode 100644 sound/soc/rockchip/rockchip_pdm.h

-- 
1.9.1




[PATCH v1 1/2] ASoC: rockchip: add support for pdm controller

2017-06-13 Thread Sugar Zhang
The Pulse Density Modulation Interface Controller (PDMC) is
a PDM interface controller and decoder that support PDM format.
It integrates a clock generator driving the PDM microphone
and embeds filters which decimate the incoming bit stream to
obtain most common audio rates.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 .../devicetree/bindings/sound/rockchip,pdm.txt |  39 ++
 sound/soc/rockchip/Kconfig |   9 +
 sound/soc/rockchip/Makefile|   2 +
 sound/soc/rockchip/rockchip_pdm.c  | 516 +
 sound/soc/rockchip/rockchip_pdm.h  |  83 
 5 files changed, 649 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,pdm.txt
 create mode 100644 sound/soc/rockchip/rockchip_pdm.c
 create mode 100644 sound/soc/rockchip/rockchip_pdm.h

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
new file mode 100644
index 000..921729d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -0,0 +1,39 @@
+* Rockchip PDM controller
+
+Required properties:
+
+- compatible: "rockchip,pdm"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- dmas: DMA specifiers for rx dma. See the DMA client binding,
+   Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in 
clock-names.
+- clock-names: should contain following:
+   - "pdm_hclk": clock for PDM BUS
+   - "pdm_clk" : clock for PDM controller
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-N: One property must exist for each entry in
+pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
+for details of the property values.
+
+Example for rk3328 PDM controller:
+
+pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = <_pdm>, <_gates28 0>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   #dma-cells = <1>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_fsync
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_sleep>;
+   status = "disabled";
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index e3ca1e9..c844878 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -15,6 +15,15 @@ config SND_SOC_ROCKCHIP_I2S
  Rockchip I2S device. The device supports upto maximum of
  8 channels each for play and record.
 
+config SND_SOC_ROCKCHIP_PDM
+   tristate "Rockchip PDM Controller Driver"
+   depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   help
+ Say Y or M if you want to add support for PDM driver for
+ Rockchip PDM Controller. The Controller supports up to maximum of
+ 8 channels record.
+
 config SND_SOC_ROCKCHIP_SPDIF
tristate "Rockchip SPDIF Device Driver"
depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index 991f91b..105f0e1 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -1,8 +1,10 @@
 # ROCKCHIP Platform Support
 snd-soc-rockchip-i2s-objs := rockchip_i2s.o
+snd-soc-rockchip-pdm-objs := rockchip_pdm.o
 snd-soc-rockchip-spdif-objs := rockchip_spdif.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
new file mode 100644
index 000..c5ddeed
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -0,0 +1,516 @@
+/*
+ * Rockchip PDM ALSA SoC Digital Audio Interface(DAI)  driver
+ *
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 

[PATCH v1 2/2] arm64: dts: rk3328: add pdm node

2017-06-13 Thread Sugar Zhang
This patch add pdm controller device node for rk3328.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 55 
 1 file changed, 55 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 7e69f1f..2435044 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,25 @@
clock-output-names = "xin24m";
};
 
+   pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = < SCLK_PDM>, < HCLK_PDM>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   #dma-cells = <1>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_fsync
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_sleep>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
@@ -701,6 +720,42 @@
};
};
 
+   pdm-0 {
+   pdmm0_clk: pdmm0-clk {
+   rockchip,pins = <2 RK_PC2 2 _pull_none>;
+   };
+
+   pdmm0_fsync: pdmm0-fsync {
+   rockchip,pins = <2 RK_PC7 2 _pull_none>;
+   };
+
+   pdmm0_sdi0: pdmm0-sdi0 {
+   rockchip,pins = <2 RK_PC3 2 _pull_none>;
+   };
+
+   pdmm0_sdi1: pdmm0-sdi1 {
+   rockchip,pins = <2 RK_PC4 2 _pull_none>;
+   };
+
+   pdmm0_sdi2: pdmm0-sdi2 {
+   rockchip,pins = <2 RK_PC5 2 _pull_none>;
+   };
+
+   pdmm0_sdi3: pdmm0-sdi3 {
+   rockchip,pins = <2 RK_PC6 2 _pull_none>;
+   };
+
+   pdmm0_sleep: pdmm0-sleep {
+   rockchip,pins =
+   <2 RK_PC2 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC3 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC4 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC5 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC6 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC7 RK_FUNC_GPIO 
_input_high>;
+   };
+   };
+
i2s1 {
i2s1_mclk: i2s1-mclk {
rockchip,pins = <2 RK_PB7 1 _pull_none>;
-- 
1.9.1




[PATCH v1 1/2] ASoC: rockchip: add support for pdm controller

2017-06-13 Thread Sugar Zhang
The Pulse Density Modulation Interface Controller (PDMC) is
a PDM interface controller and decoder that support PDM format.
It integrates a clock generator driving the PDM microphone
and embeds filters which decimate the incoming bit stream to
obtain most common audio rates.

Signed-off-by: Sugar Zhang 
---

 .../devicetree/bindings/sound/rockchip,pdm.txt |  39 ++
 sound/soc/rockchip/Kconfig |   9 +
 sound/soc/rockchip/Makefile|   2 +
 sound/soc/rockchip/rockchip_pdm.c  | 516 +
 sound/soc/rockchip/rockchip_pdm.h  |  83 
 5 files changed, 649 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,pdm.txt
 create mode 100644 sound/soc/rockchip/rockchip_pdm.c
 create mode 100644 sound/soc/rockchip/rockchip_pdm.h

diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt 
b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
new file mode 100644
index 000..921729d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt
@@ -0,0 +1,39 @@
+* Rockchip PDM controller
+
+Required properties:
+
+- compatible: "rockchip,pdm"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- dmas: DMA specifiers for rx dma. See the DMA client binding,
+   Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in 
clock-names.
+- clock-names: should contain following:
+   - "pdm_hclk": clock for PDM BUS
+   - "pdm_clk" : clock for PDM controller
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-N: One property must exist for each entry in
+pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
+for details of the property values.
+
+Example for rk3328 PDM controller:
+
+pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = <_pdm>, <_gates28 0>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   #dma-cells = <1>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_fsync
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_sleep>;
+   status = "disabled";
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index e3ca1e9..c844878 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -15,6 +15,15 @@ config SND_SOC_ROCKCHIP_I2S
  Rockchip I2S device. The device supports upto maximum of
  8 channels each for play and record.
 
+config SND_SOC_ROCKCHIP_PDM
+   tristate "Rockchip PDM Controller Driver"
+   depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   help
+ Say Y or M if you want to add support for PDM driver for
+ Rockchip PDM Controller. The Controller supports up to maximum of
+ 8 channels record.
+
 config SND_SOC_ROCKCHIP_SPDIF
tristate "Rockchip SPDIF Device Driver"
depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index 991f91b..105f0e1 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -1,8 +1,10 @@
 # ROCKCHIP Platform Support
 snd-soc-rockchip-i2s-objs := rockchip_i2s.o
+snd-soc-rockchip-pdm-objs := rockchip_pdm.o
 snd-soc-rockchip-spdif-objs := rockchip_spdif.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
diff --git a/sound/soc/rockchip/rockchip_pdm.c 
b/sound/soc/rockchip/rockchip_pdm.c
new file mode 100644
index 000..c5ddeed
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -0,0 +1,516 @@
+/*
+ * Rockchip PDM ALSA SoC Digital Audio Interface(DAI)  driver
+ *
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rockchip_pdm.h"

[PATCH v1 2/2] arm64: dts: rk3328: add pdm node

2017-06-13 Thread Sugar Zhang
This patch add pdm controller device node for rk3328.

Signed-off-by: Sugar Zhang 

---

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 55 
 1 file changed, 55 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 7e69f1f..2435044 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -156,6 +156,25 @@
clock-output-names = "xin24m";
};
 
+   pdm: pdm@ff04 {
+   compatible = "rockchip,pdm";
+   reg = <0x0 0xff04 0x0 0x1000>;
+   clocks = < SCLK_PDM>, < HCLK_PDM>;
+   clock-names = "pdm_clk", "pdm_hclk";
+   dmas = < 16>;
+   #dma-cells = <1>;
+   dma-names = "rx";
+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_clk
+_fsync
+_sdi0
+_sdi1
+_sdi2
+_sdi3>;
+   pinctrl-1 = <_sleep>;
+   status = "disabled";
+   };
+
grf: syscon@ff10 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff10 0x0 0x1000>;
@@ -701,6 +720,42 @@
};
};
 
+   pdm-0 {
+   pdmm0_clk: pdmm0-clk {
+   rockchip,pins = <2 RK_PC2 2 _pull_none>;
+   };
+
+   pdmm0_fsync: pdmm0-fsync {
+   rockchip,pins = <2 RK_PC7 2 _pull_none>;
+   };
+
+   pdmm0_sdi0: pdmm0-sdi0 {
+   rockchip,pins = <2 RK_PC3 2 _pull_none>;
+   };
+
+   pdmm0_sdi1: pdmm0-sdi1 {
+   rockchip,pins = <2 RK_PC4 2 _pull_none>;
+   };
+
+   pdmm0_sdi2: pdmm0-sdi2 {
+   rockchip,pins = <2 RK_PC5 2 _pull_none>;
+   };
+
+   pdmm0_sdi3: pdmm0-sdi3 {
+   rockchip,pins = <2 RK_PC6 2 _pull_none>;
+   };
+
+   pdmm0_sleep: pdmm0-sleep {
+   rockchip,pins =
+   <2 RK_PC2 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC3 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC4 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC5 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC6 RK_FUNC_GPIO 
_input_high>,
+   <2 RK_PC7 RK_FUNC_GPIO 
_input_high>;
+   };
+   };
+
i2s1 {
i2s1_mclk: i2s1-mclk {
rockchip,pins = <2 RK_PB7 1 _pull_none>;
-- 
1.9.1




[PATCH] ARM: dts: rk322x: fix i2s1 pinctrl error

2017-06-09 Thread Sugar Zhang
Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 arch/arm/boot/dts/rk322x.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index 48a0c1c..cc6a27d 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -621,9 +621,9 @@
<0 12 RK_FUNC_1 
_pull_none>,
<0 13 RK_FUNC_1 
_pull_none>,
<0 14 RK_FUNC_1 
_pull_none>,
-   <1 2 RK_FUNC_1 _pull_none>,
-   <1 4 RK_FUNC_1 _pull_none>,
-   <1 5 RK_FUNC_1 _pull_none>;
+   <1 2 RK_FUNC_2 _pull_none>,
+   <1 4 RK_FUNC_2 _pull_none>,
+   <1 5 RK_FUNC_2 _pull_none>;
};
};
 
-- 
1.9.1




[PATCH] ARM: dts: rk322x: fix i2s1 pinctrl error

2017-06-09 Thread Sugar Zhang
Signed-off-by: Sugar Zhang 
---

 arch/arm/boot/dts/rk322x.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index 48a0c1c..cc6a27d 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -621,9 +621,9 @@
<0 12 RK_FUNC_1 
_pull_none>,
<0 13 RK_FUNC_1 
_pull_none>,
<0 14 RK_FUNC_1 
_pull_none>,
-   <1 2 RK_FUNC_1 _pull_none>,
-   <1 4 RK_FUNC_1 _pull_none>,
-   <1 5 RK_FUNC_1 _pull_none>;
+   <1 2 RK_FUNC_2 _pull_none>,
+   <1 4 RK_FUNC_2 _pull_none>,
+   <1 5 RK_FUNC_2 _pull_none>;
};
};
 
-- 
1.9.1




[PATCH v1 2/4] ASoC: rockchip: i2s: add support for i2s bclk fs configuration

2017-06-09 Thread Sugar Zhang
this patch add support for i2s bclk fs configuration, we can
configure bclk_fs by devicetree as required.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 Documentation/devicetree/bindings/sound/rockchip-i2s.txt | 2 ++
 sound/soc/rockchip/rockchip_i2s.c| 9 -
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 206aba1..de3cbbe 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,7 @@ Required properties:
- "i2s_clk" : clock for I2S controller
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
+- rockchip,bclk-fs: configure the i2s bclk fs.
 
 Required properties for controller which support multi channels
 playback/capture:
@@ -41,4 +42,5 @@ i2s@ff89 {
clocks = < HCLK_I2S0>, < SCLK_I2S0>;
rockchip,playback-channels = <8>;
rockchip,capture-channels = <2>;
+   rockchip,bclk-fs = <128>;
 };
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index f548433..220232b 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -51,6 +51,7 @@ struct rk_i2s_dev {
bool rx_start;
bool is_master_mode;
const struct rk_i2s_pins *pins;
+   unsigned int bclk_fs;
 };
 
 static int i2s_runtime_suspend(struct device *dev)
@@ -254,7 +255,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
 
if (i2s->is_master_mode) {
mclk_rate = clk_get_rate(i2s->mclk);
-   bclk_rate = 2 * 32 * params_rate(params);
+   bclk_rate = i2s->bclk_fs * params_rate(params);
if (bclk_rate && mclk_rate % bclk_rate)
return -EINVAL;
 
@@ -633,6 +634,12 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
soc_dai->capture.channels_max = val;
}
 
+   i2s->bclk_fs = 64;
+   if (!of_property_read_u32(node, "rockchip,bclk-fs", )) {
+   if ((val >= 32) && (val % 2 == 0))
+   i2s->bclk_fs = val;
+   }
+
ret = devm_snd_soc_register_component(>dev,
  _i2s_component,
  soc_dai, 1);
-- 
1.9.1




[PATCH v1 2/4] ASoC: rockchip: i2s: add support for i2s bclk fs configuration

2017-06-09 Thread Sugar Zhang
this patch add support for i2s bclk fs configuration, we can
configure bclk_fs by devicetree as required.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip-i2s.txt | 2 ++
 sound/soc/rockchip/rockchip_i2s.c| 9 -
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 206aba1..de3cbbe 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,7 @@ Required properties:
- "i2s_clk" : clock for I2S controller
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
+- rockchip,bclk-fs: configure the i2s bclk fs.
 
 Required properties for controller which support multi channels
 playback/capture:
@@ -41,4 +42,5 @@ i2s@ff89 {
clocks = < HCLK_I2S0>, < SCLK_I2S0>;
rockchip,playback-channels = <8>;
rockchip,capture-channels = <2>;
+   rockchip,bclk-fs = <128>;
 };
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index f548433..220232b 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -51,6 +51,7 @@ struct rk_i2s_dev {
bool rx_start;
bool is_master_mode;
const struct rk_i2s_pins *pins;
+   unsigned int bclk_fs;
 };
 
 static int i2s_runtime_suspend(struct device *dev)
@@ -254,7 +255,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
 
if (i2s->is_master_mode) {
mclk_rate = clk_get_rate(i2s->mclk);
-   bclk_rate = 2 * 32 * params_rate(params);
+   bclk_rate = i2s->bclk_fs * params_rate(params);
if (bclk_rate && mclk_rate % bclk_rate)
return -EINVAL;
 
@@ -633,6 +634,12 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
soc_dai->capture.channels_max = val;
}
 
+   i2s->bclk_fs = 64;
+   if (!of_property_read_u32(node, "rockchip,bclk-fs", )) {
+   if ((val >= 32) && (val % 2 == 0))
+   i2s->bclk_fs = val;
+   }
+
ret = devm_snd_soc_register_component(>dev,
  _i2s_component,
  soc_dai, 1);
-- 
1.9.1




[PATCH v1 4/4] ASoC: rockchip: i2s: fixup clk div

2017-06-09 Thread Sugar Zhang
we found mclk maybe not precise as required because of PLL,
but it still can be used and no side effect. for example, if we
require mclk 11289600, but get 11289598, it doesn't matter.
so using DIV_ROUND_CLOSEST to fix it.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

 sound/soc/rockchip/rockchip_i2s.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2a15a00..b56e00d 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -282,10 +282,10 @@ static int rockchip_i2s_hw_params(struct 
snd_pcm_substream *substream,
if (i2s->is_master_mode) {
mclk_rate = clk_get_rate(i2s->mclk);
bclk_rate = i2s->bclk_fs * params_rate(params);
-   if (bclk_rate && mclk_rate % bclk_rate)
+   if (!bclk_rate)
return -EINVAL;
 
-   div_bclk = mclk_rate / bclk_rate;
+   div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
div_lrck = bclk_rate / params_rate(params);
regmap_update_bits(i2s->regmap, I2S_CKR,
   I2S_CKR_MDIV_MASK,
-- 
1.9.1




[PATCH v1 4/4] ASoC: rockchip: i2s: fixup clk div

2017-06-09 Thread Sugar Zhang
we found mclk maybe not precise as required because of PLL,
but it still can be used and no side effect. for example, if we
require mclk 11289600, but get 11289598, it doesn't matter.
so using DIV_ROUND_CLOSEST to fix it.

Signed-off-by: Sugar Zhang 

---

 sound/soc/rockchip/rockchip_i2s.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2a15a00..b56e00d 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -282,10 +282,10 @@ static int rockchip_i2s_hw_params(struct 
snd_pcm_substream *substream,
if (i2s->is_master_mode) {
mclk_rate = clk_get_rate(i2s->mclk);
bclk_rate = i2s->bclk_fs * params_rate(params);
-   if (bclk_rate && mclk_rate % bclk_rate)
+   if (!bclk_rate)
return -EINVAL;
 
-   div_bclk = mclk_rate / bclk_rate;
+   div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
div_lrck = bclk_rate / params_rate(params);
regmap_update_bits(i2s->regmap, I2S_CKR,
   I2S_CKR_MDIV_MASK,
-- 
1.9.1




[PATCH v1 0/4] Patches to fix some problem for rockchip i2s

2017-06-09 Thread Sugar Zhang
These patches to fix some problem for rockchip i2s.


Sugar Zhang (3):
  ASoC: rockchip: i2s: add a delay before i2s clear
  ASoC: rockchip: i2s: add support for i2s bclk fs configuration
  ASoC: rockchip: i2s: fixup clk div

zhangjun (1):
  ASoC: rockchip: i2s: add other configurable formats

 .../devicetree/bindings/sound/rockchip-i2s.txt |  2 +
 sound/soc/rockchip/rockchip_i2s.c  | 45 +++---
 sound/soc/rockchip/rockchip_i2s.h  |  3 ++
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
1.9.1




[PATCH v1 0/4] Patches to fix some problem for rockchip i2s

2017-06-09 Thread Sugar Zhang
These patches to fix some problem for rockchip i2s.


Sugar Zhang (3):
  ASoC: rockchip: i2s: add a delay before i2s clear
  ASoC: rockchip: i2s: add support for i2s bclk fs configuration
  ASoC: rockchip: i2s: fixup clk div

zhangjun (1):
  ASoC: rockchip: i2s: add other configurable formats

 .../devicetree/bindings/sound/rockchip-i2s.txt |  2 +
 sound/soc/rockchip/rockchip_i2s.c  | 45 +++---
 sound/soc/rockchip/rockchip_i2s.h  |  3 ++
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
1.9.1




[PATCH v1 1/4] ASoC: rockchip: i2s: add a delay before i2s clear

2017-06-09 Thread Sugar Zhang
in order to guarantee i2s lrck signal integrity, when i2s stop,
need at least one lrck cycle to ensure signal integrity.

the max delay time is when lrck is 8khz, the delay time is
125us(1/8khz), using udelay(150) with a 25us margin.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 sound/soc/rockchip/rockchip_i2s.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 974915c..f548433 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -116,6 +116,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
   I2S_XFER_TXS_STOP |
   I2S_XFER_RXS_STOP);
 
+   udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR,
   I2S_CLR_TXC | I2S_CLR_RXC,
   I2S_CLR_TXC | I2S_CLR_RXC);
@@ -162,6 +163,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int 
on)
   I2S_XFER_TXS_STOP |
   I2S_XFER_RXS_STOP);
 
+   udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR,
   I2S_CLR_TXC | I2S_CLR_RXC,
   I2S_CLR_TXC | I2S_CLR_RXC);
-- 
1.9.1




[PATCH v1 1/4] ASoC: rockchip: i2s: add a delay before i2s clear

2017-06-09 Thread Sugar Zhang
in order to guarantee i2s lrck signal integrity, when i2s stop,
need at least one lrck cycle to ensure signal integrity.

the max delay time is when lrck is 8khz, the delay time is
125us(1/8khz), using udelay(150) with a 25us margin.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_i2s.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 974915c..f548433 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -116,6 +116,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
   I2S_XFER_TXS_STOP |
   I2S_XFER_RXS_STOP);
 
+   udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR,
   I2S_CLR_TXC | I2S_CLR_RXC,
   I2S_CLR_TXC | I2S_CLR_RXC);
@@ -162,6 +163,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int 
on)
   I2S_XFER_TXS_STOP |
   I2S_XFER_RXS_STOP);
 
+   udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR,
   I2S_CLR_TXC | I2S_CLR_RXC,
   I2S_CLR_TXC | I2S_CLR_RXC);
-- 
1.9.1




[PATCH v1 3/4] ASoC: rockchip: i2s: add other configurable formats

2017-06-09 Thread Sugar Zhang
From: zhangjun <zhang...@rock-chips.com>

simple-audio-card,bitclock-inversion = <1> : bclk falling edge taken
simple-audio-card,format = "dsp_a" : pcm no delay mode
simple-audio-card,format = "dsp_b" : pcm late 1 mode

Signed-off-by: zhangjun <zhang...@rock-chips.com>
Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 sound/soc/rockchip/rockchip_i2s.c | 30 --
 sound/soc/rockchip/rockchip_i2s.h |  3 +++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 220232b..2a15a00 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -207,7 +207,21 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
 
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
 
-   mask = I2S_TXCR_IBM_MASK;
+   mask = I2S_CKR_CKP_MASK;
+   switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+   case SND_SOC_DAIFMT_NB_NF:
+   val = I2S_CKR_CKP_NEG;
+   break;
+   case SND_SOC_DAIFMT_IB_NF:
+   val = I2S_CKR_CKP_POS;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
+
+   mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
val = I2S_TXCR_IBM_RSJM;
@@ -218,13 +232,19 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_TXCR_IBM_NORMAL;
break;
+   case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
+   val = I2S_TXCR_TFS_PCM;
+   break;
+   case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+   val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
+   break;
default:
return -EINVAL;
}
 
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
 
-   mask = I2S_RXCR_IBM_MASK;
+   mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
val = I2S_RXCR_IBM_RSJM;
@@ -235,6 +255,12 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_RXCR_IBM_NORMAL;
break;
+   case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
+   val = I2S_RXCR_TFS_PCM;
+   break;
+   case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+   val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
+   break;
default:
return -EINVAL;
}
diff --git a/sound/soc/rockchip/rockchip_i2s.h 
b/sound/soc/rockchip/rockchip_i2s.h
index 31f11fd..a7b8527 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -41,6 +41,7 @@
 #define I2S_TXCR_TFS_SHIFT 5
 #define I2S_TXCR_TFS_I2S   (0 << I2S_TXCR_TFS_SHIFT)
 #define I2S_TXCR_TFS_PCM   (1 << I2S_TXCR_TFS_SHIFT)
+#define I2S_TXCR_TFS_MASK  (1 << I2S_TXCR_TFS_SHIFT)
 #define I2S_TXCR_VDW_SHIFT 0
 #define I2S_TXCR_VDW(x)((x - 1) << I2S_TXCR_VDW_SHIFT)
 #define I2S_TXCR_VDW_MASK  (0x1f << I2S_TXCR_VDW_SHIFT)
@@ -70,6 +71,7 @@
 #define I2S_RXCR_TFS_SHIFT 5
 #define I2S_RXCR_TFS_I2S   (0 << I2S_RXCR_TFS_SHIFT)
 #define I2S_RXCR_TFS_PCM   (1 << I2S_RXCR_TFS_SHIFT)
+#define I2S_RXCR_TFS_MASK  (1 << I2S_RXCR_TFS_SHIFT)
 #define I2S_RXCR_VDW_SHIFT 0
 #define I2S_RXCR_VDW(x)((x - 1) << I2S_RXCR_VDW_SHIFT)
 #define I2S_RXCR_VDW_MASK  (0x1f << I2S_RXCR_VDW_SHIFT)
@@ -91,6 +93,7 @@
 #define I2S_CKR_CKP_SHIFT  26
 #define I2S_CKR_CKP_NEG(0 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_CKP_POS(1 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_MASK   (1 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_RLP_SHIFT  25
 #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT)
 #define I2S_CKR_RLP_OPPSITE(1 << I2S_CKR_RLP_SHIFT)
-- 
1.9.1




[PATCH v1 3/4] ASoC: rockchip: i2s: add other configurable formats

2017-06-09 Thread Sugar Zhang
From: zhangjun 

simple-audio-card,bitclock-inversion = <1> : bclk falling edge taken
simple-audio-card,format = "dsp_a" : pcm no delay mode
simple-audio-card,format = "dsp_b" : pcm late 1 mode

Signed-off-by: zhangjun 
Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_i2s.c | 30 --
 sound/soc/rockchip/rockchip_i2s.h |  3 +++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 220232b..2a15a00 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -207,7 +207,21 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
 
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
 
-   mask = I2S_TXCR_IBM_MASK;
+   mask = I2S_CKR_CKP_MASK;
+   switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+   case SND_SOC_DAIFMT_NB_NF:
+   val = I2S_CKR_CKP_NEG;
+   break;
+   case SND_SOC_DAIFMT_IB_NF:
+   val = I2S_CKR_CKP_POS;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
+
+   mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
val = I2S_TXCR_IBM_RSJM;
@@ -218,13 +232,19 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_TXCR_IBM_NORMAL;
break;
+   case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
+   val = I2S_TXCR_TFS_PCM;
+   break;
+   case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+   val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
+   break;
default:
return -EINVAL;
}
 
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
 
-   mask = I2S_RXCR_IBM_MASK;
+   mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
val = I2S_RXCR_IBM_RSJM;
@@ -235,6 +255,12 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai 
*cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_RXCR_IBM_NORMAL;
break;
+   case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
+   val = I2S_RXCR_TFS_PCM;
+   break;
+   case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+   val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
+   break;
default:
return -EINVAL;
}
diff --git a/sound/soc/rockchip/rockchip_i2s.h 
b/sound/soc/rockchip/rockchip_i2s.h
index 31f11fd..a7b8527 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -41,6 +41,7 @@
 #define I2S_TXCR_TFS_SHIFT 5
 #define I2S_TXCR_TFS_I2S   (0 << I2S_TXCR_TFS_SHIFT)
 #define I2S_TXCR_TFS_PCM   (1 << I2S_TXCR_TFS_SHIFT)
+#define I2S_TXCR_TFS_MASK  (1 << I2S_TXCR_TFS_SHIFT)
 #define I2S_TXCR_VDW_SHIFT 0
 #define I2S_TXCR_VDW(x)((x - 1) << I2S_TXCR_VDW_SHIFT)
 #define I2S_TXCR_VDW_MASK  (0x1f << I2S_TXCR_VDW_SHIFT)
@@ -70,6 +71,7 @@
 #define I2S_RXCR_TFS_SHIFT 5
 #define I2S_RXCR_TFS_I2S   (0 << I2S_RXCR_TFS_SHIFT)
 #define I2S_RXCR_TFS_PCM   (1 << I2S_RXCR_TFS_SHIFT)
+#define I2S_RXCR_TFS_MASK  (1 << I2S_RXCR_TFS_SHIFT)
 #define I2S_RXCR_VDW_SHIFT 0
 #define I2S_RXCR_VDW(x)((x - 1) << I2S_RXCR_VDW_SHIFT)
 #define I2S_RXCR_VDW_MASK  (0x1f << I2S_RXCR_VDW_SHIFT)
@@ -91,6 +93,7 @@
 #define I2S_CKR_CKP_SHIFT  26
 #define I2S_CKR_CKP_NEG(0 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_CKP_POS(1 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_MASK   (1 << I2S_CKR_CKP_SHIFT)
 #define I2S_CKR_RLP_SHIFT  25
 #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT)
 #define I2S_CKR_RLP_OPPSITE(1 << I2S_CKR_RLP_SHIFT)
-- 
1.9.1




[PATCH v1 1/2] ASoC: rockchip: add bindings for spdif controller

2017-06-09 Thread Sugar Zhang
this patch add compatible for rk3228/rk3328 spdif,

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 Documentation/devicetree/bindings/sound/rockchip-spdif.txt | 2 ++
 sound/soc/rockchip/rockchip_spdif.c| 4 
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt 
b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
index 1104642..4706b96 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
@@ -9,7 +9,9 @@ Required properties:
 - compatible: should be one of the following:
- "rockchip,rk3066-spdif"
- "rockchip,rk3188-spdif"
+   - "rockchip,rk3228-spdif"
- "rockchip,rk3288-spdif"
+   - "rockchip,rk3328-spdif"
- "rockchip,rk3366-spdif"
- "rockchip,rk3368-spdif"
- "rockchip,rk3399-spdif"
diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index fa8101d..ee5055d 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -49,8 +49,12 @@ struct rk_spdif_dev {
  .data = (void *)RK_SPDIF_RK3066 },
{ .compatible = "rockchip,rk3188-spdif",
  .data = (void *)RK_SPDIF_RK3188 },
+   { .compatible = "rockchip,rk3228-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3288-spdif",
  .data = (void *)RK_SPDIF_RK3288 },
+   { .compatible = "rockchip,rk3328-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3366-spdif",
  .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3368-spdif",
-- 
1.9.1




[PATCH v1 1/2] ASoC: rockchip: add bindings for spdif controller

2017-06-09 Thread Sugar Zhang
this patch add compatible for rk3228/rk3328 spdif,

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip-spdif.txt | 2 ++
 sound/soc/rockchip/rockchip_spdif.c| 4 
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt 
b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
index 1104642..4706b96 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
@@ -9,7 +9,9 @@ Required properties:
 - compatible: should be one of the following:
- "rockchip,rk3066-spdif"
- "rockchip,rk3188-spdif"
+   - "rockchip,rk3228-spdif"
- "rockchip,rk3288-spdif"
+   - "rockchip,rk3328-spdif"
- "rockchip,rk3366-spdif"
- "rockchip,rk3368-spdif"
- "rockchip,rk3399-spdif"
diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index fa8101d..ee5055d 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -49,8 +49,12 @@ struct rk_spdif_dev {
  .data = (void *)RK_SPDIF_RK3066 },
{ .compatible = "rockchip,rk3188-spdif",
  .data = (void *)RK_SPDIF_RK3188 },
+   { .compatible = "rockchip,rk3228-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3288-spdif",
  .data = (void *)RK_SPDIF_RK3288 },
+   { .compatible = "rockchip,rk3328-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3366-spdif",
  .data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3368-spdif",
-- 
1.9.1




[PATCH v1 0/2] Patches to add support spdif for rk322x

2017-06-09 Thread Sugar Zhang
These patches to add support spdif for rk322x socs.


Sugar Zhang (2):
  ASoC: rockchip: add bindings for spdif controller
  ARM: dts: rk322x: add spdif node

 .../devicetree/bindings/sound/rockchip-spdif.txt |  2 ++
 arch/arm/boot/dts/rk322x.dtsi| 20 
 sound/soc/rockchip/rockchip_spdif.c  |  4 
 3 files changed, 26 insertions(+)

-- 
1.9.1




[PATCH v1 0/2] Patches to add support spdif for rk322x

2017-06-09 Thread Sugar Zhang
These patches to add support spdif for rk322x socs.


Sugar Zhang (2):
  ASoC: rockchip: add bindings for spdif controller
  ARM: dts: rk322x: add spdif node

 .../devicetree/bindings/sound/rockchip-spdif.txt |  2 ++
 arch/arm/boot/dts/rk322x.dtsi| 20 
 sound/soc/rockchip/rockchip_spdif.c  |  4 
 3 files changed, 26 insertions(+)

-- 
1.9.1




[PATCH v1 2/2] ARM: dts: rk322x: add spdif node

2017-06-09 Thread Sugar Zhang
This patch add spdif node for rk322x.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

 arch/arm/boot/dts/rk322x.dtsi | 20 
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index 48a0c1c..56f0842 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -168,6 +168,20 @@
status = "disabled";
};
 
+   spdif: spdif@100d {
+   compatible = "rockchip,rk3228-spdif";
+   reg = <0x100d 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   #dma-cells = <1>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s2: i2s2@100e {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100e 0x4000>;
@@ -651,6 +665,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <3 31 RK_FUNC_2 
_pull_none>;
+   };
+   };
+
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 24 RK_FUNC_GPIO 
_pull_none>;
-- 
1.9.1




[PATCH v1 2/2] ARM: dts: rk322x: add spdif node

2017-06-09 Thread Sugar Zhang
This patch add spdif node for rk322x.

Signed-off-by: Sugar Zhang 

---

 arch/arm/boot/dts/rk322x.dtsi | 20 
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index 48a0c1c..56f0842 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -168,6 +168,20 @@
status = "disabled";
};
 
+   spdif: spdif@100d {
+   compatible = "rockchip,rk3228-spdif";
+   reg = <0x100d 0x1000>;
+   interrupts = ;
+   clocks = < SCLK_SPDIF>, < HCLK_SPDIF_8CH>;
+   clock-names = "mclk", "hclk";
+   dmas = < 10>;
+   #dma-cells = <1>;
+   dma-names = "tx";
+   pinctrl-names = "default";
+   pinctrl-0 = <_tx>;
+   status = "disabled";
+   };
+
i2s2: i2s2@100e {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100e 0x4000>;
@@ -651,6 +665,12 @@
};
};
 
+   spdif {
+   spdif_tx: spdif-tx {
+   rockchip,pins = <3 31 RK_FUNC_2 
_pull_none>;
+   };
+   };
+
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 24 RK_FUNC_GPIO 
_pull_none>;
-- 
1.9.1




Re: [PATCH 0/2] Free running cyclic transfer implementation for pl330

2017-04-17 Thread sugar

Hi Alexander,

I have tested this series on rk3399 evb board and works well.

Tested-by: Sugar Zhang <sugar.zh...@rock-chips.com>

在 4/14/2017 22:35, Alexander Kochetkov 写道:

Hello!

This series contain free running cyclic transfer implementation for pl330.
It affect ALL chips using pl330 (not only rockchip) and
allow to run cyclic transfers without CPU intervention. As a result
it fix sound clicks (observed and not yet observed) because
sound clicks must be heard under heavy system load due to the way
how cyclic transfers implemented now for pl330.

My previous series[1] doesn't get enough attention (no one except me
tested it). And it don't get upstream:


8-03-2016, 6:03, Vinod Koul <vinod.k...@intel.com> *:
Overall this series looks okay, but can someone test this. I would not like

pl330 to be broken again

Now I was asked about the series[1] again by guys from Rockchip,
so I send rebased against 4.10.10 version. Hope, someone might test it
and confirm that patches work fine.

Regards,
Alexander.

Alexander Kochetkov (2):
  dmaengine: pl330: make cyclic transfer free runnable
  dmaengine: pl330: don't emit code for one iteration loop

 drivers/dma/pl330.c |  200 +--
 1 file changed, 98 insertions(+), 102 deletions(-)





Re: [PATCH 0/2] Free running cyclic transfer implementation for pl330

2017-04-17 Thread sugar

Hi Alexander,

I have tested this series on rk3399 evb board and works well.

Tested-by: Sugar Zhang 

在 4/14/2017 22:35, Alexander Kochetkov 写道:

Hello!

This series contain free running cyclic transfer implementation for pl330.
It affect ALL chips using pl330 (not only rockchip) and
allow to run cyclic transfers without CPU intervention. As a result
it fix sound clicks (observed and not yet observed) because
sound clicks must be heard under heavy system load due to the way
how cyclic transfers implemented now for pl330.

My previous series[1] doesn't get enough attention (no one except me
tested it). And it don't get upstream:


8-03-2016, 6:03, Vinod Koul  *:
Overall this series looks okay, but can someone test this. I would not like

pl330 to be broken again

Now I was asked about the series[1] again by guys from Rockchip,
so I send rebased against 4.10.10 version. Hope, someone might test it
and confirm that patches work fine.

Regards,
Alexander.

Alexander Kochetkov (2):
  dmaengine: pl330: make cyclic transfer free runnable
  dmaengine: pl330: don't emit code for one iteration loop

 drivers/dma/pl330.c |  200 +--
 1 file changed, 98 insertions(+), 102 deletions(-)





[PATCH v3] ASoC: rockchip: spdif: restore register during runtime_suspend/resume cycle

2016-09-07 Thread Sugar Zhang
when step into runtime_suspend, spdif pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

Changes in v3:
- remove unneeded initialization

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_spdif.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 4ca2657..fa8101d 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -65,6 +65,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
 
+   regcache_cache_only(spdif->regmap, true);
clk_disable_unprepare(spdif->mclk);
clk_disable_unprepare(spdif->hclk);
 
@@ -88,7 +89,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct 
device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(spdif->regmap, false);
+   regcache_mark_dirty(spdif->regmap);
+
+   ret = regcache_sync(spdif->regmap);
+   if (ret) {
+   clk_disable_unprepare(spdif->mclk);
+   clk_disable_unprepare(spdif->hclk);
+   }
+
+   return ret;
 }
 
 static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
-- 
1.9.1




[PATCH v3] ASoC: rockchip: spdif: restore register during runtime_suspend/resume cycle

2016-09-07 Thread Sugar Zhang
when step into runtime_suspend, spdif pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang 

---

Changes in v3:
- remove unneeded initialization

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_spdif.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 4ca2657..fa8101d 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -65,6 +65,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
 
+   regcache_cache_only(spdif->regmap, true);
clk_disable_unprepare(spdif->mclk);
clk_disable_unprepare(spdif->hclk);
 
@@ -88,7 +89,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct 
device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(spdif->regmap, false);
+   regcache_mark_dirty(spdif->regmap);
+
+   ret = regcache_sync(spdif->regmap);
+   if (ret) {
+   clk_disable_unprepare(spdif->mclk);
+   clk_disable_unprepare(spdif->hclk);
+   }
+
+   return ret;
 }
 
 static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
-- 
1.9.1




[PATCH v3] ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle

2016-09-07 Thread Sugar Zhang
when step into runtime_suspend, i2s pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

Changes in v3:
- remove unneeded initialization

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_i2s.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 652e8c5..974915c 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -57,6 +57,7 @@ static int i2s_runtime_suspend(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
 
+   regcache_cache_only(i2s->regmap, true);
clk_disable_unprepare(i2s->mclk);
 
return 0;
@@ -73,7 +74,14 @@ static int i2s_runtime_resume(struct device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(i2s->regmap, false);
+   regcache_mark_dirty(i2s->regmap);
+
+   ret = regcache_sync(i2s->regmap);
+   if (ret)
+   clk_disable_unprepare(i2s->mclk);
+
+   return ret;
 }
 
 static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
-- 
1.9.1




[PATCH v3] ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle

2016-09-07 Thread Sugar Zhang
when step into runtime_suspend, i2s pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang 

---

Changes in v3:
- remove unneeded initialization

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_i2s.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 652e8c5..974915c 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -57,6 +57,7 @@ static int i2s_runtime_suspend(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
 
+   regcache_cache_only(i2s->regmap, true);
clk_disable_unprepare(i2s->mclk);
 
return 0;
@@ -73,7 +74,14 @@ static int i2s_runtime_resume(struct device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(i2s->regmap, false);
+   regcache_mark_dirty(i2s->regmap);
+
+   ret = regcache_sync(i2s->regmap);
+   if (ret)
+   clk_disable_unprepare(i2s->mclk);
+
+   return ret;
 }
 
 static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
-- 
1.9.1




[PATCH v2] ASoC: rockchip: spdif: restore register during runtime_suspend/resume cycle

2016-09-05 Thread Sugar Zhang
when step into runtime_suspend, spdif pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_spdif.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 4ca2657..0eb8d49 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -65,6 +65,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
 
+   regcache_cache_only(spdif->regmap, true);
clk_disable_unprepare(spdif->mclk);
clk_disable_unprepare(spdif->hclk);
 
@@ -74,7 +75,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 static int __maybe_unused rk_spdif_runtime_resume(struct device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
-   int ret;
+   int ret = 0;
 
ret = clk_prepare_enable(spdif->mclk);
if (ret) {
@@ -88,7 +89,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct 
device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(spdif->regmap, false);
+   regcache_mark_dirty(spdif->regmap);
+
+   ret = regcache_sync(spdif->regmap);
+   if (ret) {
+   clk_disable_unprepare(spdif->mclk);
+   clk_disable_unprepare(spdif->hclk);
+   }
+
+   return ret;
 }
 
 static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
-- 
1.9.1




[PATCH v2] ASoC: rockchip: spdif: restore register during runtime_suspend/resume cycle

2016-09-05 Thread Sugar Zhang
when step into runtime_suspend, spdif pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang 

---

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_spdif.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 4ca2657..0eb8d49 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -65,6 +65,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
 
+   regcache_cache_only(spdif->regmap, true);
clk_disable_unprepare(spdif->mclk);
clk_disable_unprepare(spdif->hclk);
 
@@ -74,7 +75,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct 
device *dev)
 static int __maybe_unused rk_spdif_runtime_resume(struct device *dev)
 {
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
-   int ret;
+   int ret = 0;
 
ret = clk_prepare_enable(spdif->mclk);
if (ret) {
@@ -88,7 +89,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct 
device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(spdif->regmap, false);
+   regcache_mark_dirty(spdif->regmap);
+
+   ret = regcache_sync(spdif->regmap);
+   if (ret) {
+   clk_disable_unprepare(spdif->mclk);
+   clk_disable_unprepare(spdif->hclk);
+   }
+
+   return ret;
 }
 
 static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
-- 
1.9.1




[PATCH v2] ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle

2016-09-05 Thread Sugar Zhang
when step into runtime_suspend, i2s pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>

---

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_i2s.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 652e8c5..98b6822 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -57,6 +57,7 @@ static int i2s_runtime_suspend(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
 
+   regcache_cache_only(i2s->regmap, true);
clk_disable_unprepare(i2s->mclk);
 
return 0;
@@ -65,7 +66,7 @@ static int i2s_runtime_suspend(struct device *dev)
 static int i2s_runtime_resume(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
-   int ret;
+   int ret = 0;
 
ret = clk_prepare_enable(i2s->mclk);
if (ret) {
@@ -73,7 +74,14 @@ static int i2s_runtime_resume(struct device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(i2s->regmap, false);
+   regcache_mark_dirty(i2s->regmap);
+
+   ret = regcache_sync(i2s->regmap);
+   if (ret)
+   clk_disable_unprepare(i2s->mclk);
+
+   return ret;
 }
 
 static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
-- 
1.9.1




[PATCH v2] ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle

2016-09-05 Thread Sugar Zhang
when step into runtime_suspend, i2s pd will be disabled and loss state.
so need to restore register when runtime_resume.

Signed-off-by: Sugar Zhang 

---

Changes in v2:
- remove system suspend/resume and restore register
  in runtime_suspend/resume per Doug Anderson's suggestion

 sound/soc/rockchip/rockchip_i2s.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 652e8c5..98b6822 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -57,6 +57,7 @@ static int i2s_runtime_suspend(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
 
+   regcache_cache_only(i2s->regmap, true);
clk_disable_unprepare(i2s->mclk);
 
return 0;
@@ -65,7 +66,7 @@ static int i2s_runtime_suspend(struct device *dev)
 static int i2s_runtime_resume(struct device *dev)
 {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
-   int ret;
+   int ret = 0;
 
ret = clk_prepare_enable(i2s->mclk);
if (ret) {
@@ -73,7 +74,14 @@ static int i2s_runtime_resume(struct device *dev)
return ret;
}
 
-   return 0;
+   regcache_cache_only(i2s->regmap, false);
+   regcache_mark_dirty(i2s->regmap);
+
+   ret = regcache_sync(i2s->regmap);
+   if (ret)
+   clk_disable_unprepare(i2s->mclk);
+
+   return ret;
 }
 
 static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
-- 
1.9.1




[PATCH] ASoC: rockchip: implement system suspend/resume for spdif

2016-07-04 Thread Sugar Zhang
restore hw registers after power loss during a suspend/resume cycle.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 sound/soc/rockchip/rockchip_spdif.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 100781e..00ae0e5 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -392,9 +392,35 @@ static int rk_spdif_remove(struct platform_device *pdev)
return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_spdif_suspend(struct device *dev)
+{
+   struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+
+   regcache_mark_dirty(spdif->regmap);
+
+   return 0;
+}
+
+static int rockchip_spdif_resume(struct device *dev)
+{
+   struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+   int ret;
+
+   ret = pm_runtime_get_sync(dev);
+   if (ret < 0)
+   return ret;
+   ret = regcache_sync(spdif->regmap);
+   pm_runtime_put(dev);
+
+   return ret;
+}
+#endif
+
 static const struct dev_pm_ops rk_spdif_pm_ops = {
SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume,
   NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(rockchip_spdif_suspend, rockchip_spdif_resume)
 };
 
 static struct platform_driver rk_spdif_driver = {
-- 
1.9.1




[PATCH] ASoC: rockchip: implement system suspend/resume for spdif

2016-07-04 Thread Sugar Zhang
restore hw registers after power loss during a suspend/resume cycle.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_spdif.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 100781e..00ae0e5 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -392,9 +392,35 @@ static int rk_spdif_remove(struct platform_device *pdev)
return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_spdif_suspend(struct device *dev)
+{
+   struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+
+   regcache_mark_dirty(spdif->regmap);
+
+   return 0;
+}
+
+static int rockchip_spdif_resume(struct device *dev)
+{
+   struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+   int ret;
+
+   ret = pm_runtime_get_sync(dev);
+   if (ret < 0)
+   return ret;
+   ret = regcache_sync(spdif->regmap);
+   pm_runtime_put(dev);
+
+   return ret;
+}
+#endif
+
 static const struct dev_pm_ops rk_spdif_pm_ops = {
SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume,
   NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(rockchip_spdif_suspend, rockchip_spdif_resume)
 };
 
 static struct platform_driver rk_spdif_driver = {
-- 
1.9.1




[PATCH] ASoC: rockchip: implement system suspend/resume for i2s

2016-07-04 Thread Sugar Zhang
restore hw registers after power loss during a suspend/resume cycle.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 sound/soc/rockchip/rockchip_i2s.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 574c6af..53970ac 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -614,9 +614,35 @@ static const struct of_device_id rockchip_i2s_match[] = {
{},
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_i2s_suspend(struct device *dev)
+{
+   struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+
+   regcache_mark_dirty(i2s->regmap);
+
+   return 0;
+}
+
+static int rockchip_i2s_resume(struct device *dev)
+{
+   struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+   int ret;
+
+   ret = pm_runtime_get_sync(dev);
+   if (ret < 0)
+   return ret;
+   ret = regcache_sync(i2s->regmap);
+   pm_runtime_put(dev);
+
+   return ret;
+}
+#endif
+
 static const struct dev_pm_ops rockchip_i2s_pm_ops = {
SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
   NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_suspend, rockchip_i2s_resume)
 };
 
 static struct platform_driver rockchip_i2s_driver = {
-- 
1.9.1




[PATCH] ASoC: rockchip: implement system suspend/resume for i2s

2016-07-04 Thread Sugar Zhang
restore hw registers after power loss during a suspend/resume cycle.

Signed-off-by: Sugar Zhang 
---

 sound/soc/rockchip/rockchip_i2s.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 574c6af..53970ac 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -614,9 +614,35 @@ static const struct of_device_id rockchip_i2s_match[] = {
{},
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_i2s_suspend(struct device *dev)
+{
+   struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+
+   regcache_mark_dirty(i2s->regmap);
+
+   return 0;
+}
+
+static int rockchip_i2s_resume(struct device *dev)
+{
+   struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+   int ret;
+
+   ret = pm_runtime_get_sync(dev);
+   if (ret < 0)
+   return ret;
+   ret = regcache_sync(i2s->regmap);
+   pm_runtime_put(dev);
+
+   return ret;
+}
+#endif
+
 static const struct dev_pm_ops rockchip_i2s_pm_ops = {
SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
   NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_suspend, rockchip_i2s_resume)
 };
 
 static struct platform_driver rockchip_i2s_driver = {
-- 
1.9.1




Re: [PATCH 1/2] ASoC: rockchip: i2s: separate capture and playback

2016-05-02 Thread sugar

Hi John,

On 4/30/2016 15:00, John Keeping Wrote:

Hi Enric,

On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:

2015-12-09 11:32 GMT+01:00 John Keeping :

If we only clear the tx/rx state when both are disabled it is not
possible to start/stop one multiple times while the other is running.
Since the two are independently controlled, treat them as such and
remove the false dependency between capture and playback.

Signed-off-by: John Keeping 
---
  sound/soc/rockchip/rockchip_i2s.c | 72 +--
  1 file changed, 32 insertions(+), 40 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 83b1b9c..acc6225 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);

 regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+  I2S_XFER_TXS_START,
+  I2S_XFER_TXS_START);

 i2s->tx_start = true;
 } else {
@@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
 regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE, 
I2S_DMACR_TDE_DISABLE);

-   if (!i2s->rx_start) {
-   regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START |
-  I2S_XFER_RXS_START,
-  I2S_XFER_TXS_STOP |
-  I2S_XFER_RXS_STOP);
+   regmap_update_bits(i2s->regmap, I2S_XFER,
+  I2S_XFER_TXS_START,
+  I2S_XFER_TXS_STOP);

-   regmap_update_bits(i2s->regmap, I2S_CLR,
-  I2S_CLR_TXC | I2S_CLR_RXC,
-  I2S_CLR_TXC | I2S_CLR_RXC);
+   regmap_update_bits(i2s->regmap, I2S_CLR,
+  I2S_CLR_TXC,
+  I2S_CLR_TXC);

-   regmap_read(i2s->regmap, I2S_CLR, );
+   regmap_read(i2s->regmap, I2S_CLR, );

-   /* Should wait for clear operation to finish */
-   while (val) {
-   regmap_read(i2s->regmap, I2S_CLR, );
-   retry--;
-   if (!retry) {
-   dev_warn(i2s->dev, "fail to clear\n");
-   break;
-   }
+   /* Should wait for clear operation to finish */
+   while (val & I2S_CLR_TXC) {
+   regmap_read(i2s->regmap, I2S_CLR, );
+   retry--;
+   if (!retry) {
+   dev_warn(i2s->dev, "fail to clear\n");
+   break;
 }
 }
 }
@@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int 
on)
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);

 regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+  I2S_XFER_RXS_START,
+  I2S_XFER_RXS_START);

 i2s->rx_start = true;
 } else {
@@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, 
int on)
 regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE, 
I2S_DMACR_RDE_DISABLE);

-   if (!i2s->tx_start) {
-   regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START |
-  I2S_XFER_RXS_START,
-  I2S_XFER_TXS_STOP |
-  I2S_XFER_RXS_STOP);
+   regmap_update_bits(i2s->regmap, I2S_XFER,
+  I2S_XFER_RXS_START,
+  I2S_XFER_RXS_STOP);

-   regmap_update_bits(i2s->regmap, I2S_CLR,
-  I2S_CLR_TXC | I2S_CLR_RXC,
-  I2S_CLR_TXC | I2S_CLR_RXC);
+   

Re: [PATCH 1/2] ASoC: rockchip: i2s: separate capture and playback

2016-05-02 Thread sugar

Hi John,

On 4/30/2016 15:00, John Keeping Wrote:

Hi Enric,

On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:

2015-12-09 11:32 GMT+01:00 John Keeping :

If we only clear the tx/rx state when both are disabled it is not
possible to start/stop one multiple times while the other is running.
Since the two are independently controlled, treat them as such and
remove the false dependency between capture and playback.

Signed-off-by: John Keeping 
---
  sound/soc/rockchip/rockchip_i2s.c | 72 +--
  1 file changed, 32 insertions(+), 40 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 83b1b9c..acc6225 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);

 regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+  I2S_XFER_TXS_START,
+  I2S_XFER_TXS_START);

 i2s->tx_start = true;
 } else {
@@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int 
on)
 regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE, 
I2S_DMACR_TDE_DISABLE);

-   if (!i2s->rx_start) {
-   regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START |
-  I2S_XFER_RXS_START,
-  I2S_XFER_TXS_STOP |
-  I2S_XFER_RXS_STOP);
+   regmap_update_bits(i2s->regmap, I2S_XFER,
+  I2S_XFER_TXS_START,
+  I2S_XFER_TXS_STOP);

-   regmap_update_bits(i2s->regmap, I2S_CLR,
-  I2S_CLR_TXC | I2S_CLR_RXC,
-  I2S_CLR_TXC | I2S_CLR_RXC);
+   regmap_update_bits(i2s->regmap, I2S_CLR,
+  I2S_CLR_TXC,
+  I2S_CLR_TXC);

-   regmap_read(i2s->regmap, I2S_CLR, );
+   regmap_read(i2s->regmap, I2S_CLR, );

-   /* Should wait for clear operation to finish */
-   while (val) {
-   regmap_read(i2s->regmap, I2S_CLR, );
-   retry--;
-   if (!retry) {
-   dev_warn(i2s->dev, "fail to clear\n");
-   break;
-   }
+   /* Should wait for clear operation to finish */
+   while (val & I2S_CLR_TXC) {
+   regmap_read(i2s->regmap, I2S_CLR, );
+   retry--;
+   if (!retry) {
+   dev_warn(i2s->dev, "fail to clear\n");
+   break;
 }
 }
 }
@@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int 
on)
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);

 regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
-  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+  I2S_XFER_RXS_START,
+  I2S_XFER_RXS_START);

 i2s->rx_start = true;
 } else {
@@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, 
int on)
 regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE, 
I2S_DMACR_RDE_DISABLE);

-   if (!i2s->tx_start) {
-   regmap_update_bits(i2s->regmap, I2S_XFER,
-  I2S_XFER_TXS_START |
-  I2S_XFER_RXS_START,
-  I2S_XFER_TXS_STOP |
-  I2S_XFER_RXS_STOP);
+   regmap_update_bits(i2s->regmap, I2S_XFER,
+  I2S_XFER_RXS_START,
+  I2S_XFER_RXS_STOP);

-   regmap_update_bits(i2s->regmap, I2S_CLR,
-  I2S_CLR_TXC | I2S_CLR_RXC,
-  I2S_CLR_TXC | I2S_CLR_RXC);
+   regmap_update_bits(i2s->regmap, I2S_CLR,
+

[PATCH v2] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-11 Thread Sugar Zhang
There are 3 i2s sdio pins, which iomux mode is as follows:

 - sdi3_sdo1
 - sdi2_sdo2
 - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

Changes in v2:
- fix a typo error.
as suggested by Heiko:
- use the general grf-binding without any offset
- keep the actual offset in the driver on a per-soc basis.

 .../devicetree/bindings/sound/rockchip-i2s.txt |  5 ++
 sound/soc/rockchip/rockchip_i2s.c  | 67 +++---
 sound/soc/rockchip/rockchip_i2s.h  |  7 +++
 3 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..4ea29aa 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
 
+Required properties for controller which support multi channels
+playback/capture:
+
+- rockchip,grf: the phandle of the syscon node for GRF register.
+
 Example for rk3288 I2S controller:
 
 i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e204..d4f7eac 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -11,8 +11,10 @@
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +25,11 @@
 
 #define DRV_NAME "rockchip-i2s"
 
+struct rk_i2s_pins {
+   u32 reg_offset;
+   u32 shift;
+};
+
 struct rk_i2s_dev {
struct device *dev;
 
@@ -33,8 +40,10 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data;
 
struct regmap *regmap;
+   struct regmap *grf;
 
bool is_master_mode;
+   const struct rk_i2s_pins *pins;
 };
 
 static int i2s_runtime_suspend(struct device *dev)
@@ -277,6 +286,30 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
   val);
 
+   if (!IS_ERR(i2s->grf) && i2s->pins) {
+   regmap_read(i2s->regmap, I2S_TXCR, );
+   val &= I2S_TXCR_CSR_MASK;
+
+   switch (val) {
+   case I2S_CHN_4:
+   val = I2S_IO_4CH_OUT_6CH_IN;
+   break;
+   case I2S_CHN_6:
+   val = I2S_IO_6CH_OUT_4CH_IN;
+   break;
+   case I2S_CHN_8:
+   val = I2S_IO_8CH_OUT_2CH_IN;
+   break;
+   default:
+   val = I2S_IO_2CH_OUT_8CH_IN;
+   break;
+   }
+
+   val <<= i2s->pins->shift;
+   val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16;
+   regmap_write(i2s->grf, i2s->pins->reg_offset, val);
+   }
+
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
   I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
@@ -462,9 +495,23 @@ static const struct regmap_config 
rockchip_i2s_regmap_config = {
.cache_type = REGCACHE_FLAT,
 };
 
+static const struct rk_i2s_pins rk3399_i2s_pins = {
+   .reg_offset = 0xe220,
+   .shift = 11,
+};
+
+static const struct of_device_id rockchip_i2s_match[] = {
+   { .compatible = "rockchip,rk3066-i2s", },
+   { .compatible = "rockchip,rk3188-i2s", },
+   { .compatible = "rockchip,rk3288-i2s", },
+   { .compatible = "rockchip,rk3399-i2s", .data = _i2s_pins },
+   {},
+};
+
 static int rockchip_i2s_probe(struct platform_device *pdev)
 {
struct device_node *node = pdev->dev.of_node;
+   const struct of_device_id *of_id;
struct rk_i2s_dev *i2s;
struct snd_soc_dai_driver *soc_dai;
struct resource *res;
@@ -478,6 +525,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return -ENOMEM;
}
 
+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   of_id = of_match_device(rockchip_i2s_match, >dev);
+   if (!of_id || !of_id->data)
+   return -EINVAL;
+
+   i2s->pins = of_id->data;
+   }
+
/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i

[PATCH v2] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-11 Thread Sugar Zhang
There are 3 i2s sdio pins, which iomux mode is as follows:

 - sdi3_sdo1
 - sdi2_sdo2
 - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang 
---

Changes in v2:
- fix a typo error.
as suggested by Heiko:
- use the general grf-binding without any offset
- keep the actual offset in the driver on a per-soc basis.

 .../devicetree/bindings/sound/rockchip-i2s.txt |  5 ++
 sound/soc/rockchip/rockchip_i2s.c  | 67 +++---
 sound/soc/rockchip/rockchip_i2s.h  |  7 +++
 3 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..4ea29aa 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
 
+Required properties for controller which support multi channels
+playback/capture:
+
+- rockchip,grf: the phandle of the syscon node for GRF register.
+
 Example for rk3288 I2S controller:
 
 i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e204..d4f7eac 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -11,8 +11,10 @@
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,6 +25,11 @@
 
 #define DRV_NAME "rockchip-i2s"
 
+struct rk_i2s_pins {
+   u32 reg_offset;
+   u32 shift;
+};
+
 struct rk_i2s_dev {
struct device *dev;
 
@@ -33,8 +40,10 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data;
 
struct regmap *regmap;
+   struct regmap *grf;
 
bool is_master_mode;
+   const struct rk_i2s_pins *pins;
 };
 
 static int i2s_runtime_suspend(struct device *dev)
@@ -277,6 +286,30 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
   val);
 
+   if (!IS_ERR(i2s->grf) && i2s->pins) {
+   regmap_read(i2s->regmap, I2S_TXCR, );
+   val &= I2S_TXCR_CSR_MASK;
+
+   switch (val) {
+   case I2S_CHN_4:
+   val = I2S_IO_4CH_OUT_6CH_IN;
+   break;
+   case I2S_CHN_6:
+   val = I2S_IO_6CH_OUT_4CH_IN;
+   break;
+   case I2S_CHN_8:
+   val = I2S_IO_8CH_OUT_2CH_IN;
+   break;
+   default:
+   val = I2S_IO_2CH_OUT_8CH_IN;
+   break;
+   }
+
+   val <<= i2s->pins->shift;
+   val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16;
+   regmap_write(i2s->grf, i2s->pins->reg_offset, val);
+   }
+
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
   I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
@@ -462,9 +495,23 @@ static const struct regmap_config 
rockchip_i2s_regmap_config = {
.cache_type = REGCACHE_FLAT,
 };
 
+static const struct rk_i2s_pins rk3399_i2s_pins = {
+   .reg_offset = 0xe220,
+   .shift = 11,
+};
+
+static const struct of_device_id rockchip_i2s_match[] = {
+   { .compatible = "rockchip,rk3066-i2s", },
+   { .compatible = "rockchip,rk3188-i2s", },
+   { .compatible = "rockchip,rk3288-i2s", },
+   { .compatible = "rockchip,rk3399-i2s", .data = _i2s_pins },
+   {},
+};
+
 static int rockchip_i2s_probe(struct platform_device *pdev)
 {
struct device_node *node = pdev->dev.of_node;
+   const struct of_device_id *of_id;
struct rk_i2s_dev *i2s;
struct snd_soc_dai_driver *soc_dai;
struct resource *res;
@@ -478,6 +525,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return -ENOMEM;
}
 
+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   of_id = of_match_device(rockchip_i2s_match, >dev);
+   if (!of_id || !of_id->data)
+   return -EINVAL;
+
+   i2s->pins = of_id->data;
+   }
+
/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
@@ -517,7 +575,6 @@ static int rockc

Re: [PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-10 Thread sugar

Hi Heiko,

Got it, thanks for your advice, these will be done in next version.

On 4/9/2016 01:14, Heiko Stuebner Wrote:

Hi,

Am Mittwoch, 6. April 2016, 16:38:22 schrieb Sugar Zhang:

There are 3 i2s sdio pins, which iomux mode is as follows:

  - sdi3_sdo1
  - sdi2_sdo2
  - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

  .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
  sound/soc/rockchip/rockchip_i2s.c  | 39
+- sound/soc/rockchip/rockchip_i2s.h
|  8 +
  3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt index
6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
  - rockchip,playback-channels: max playback channels, if not set, 8
channels default. - rockchip,capture-channels: max capture channels, if
not set, 2 channels default.

+Required properties for controller which support multi channels
playback/capture: +
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon
node for GRF register, +  and the offset of the GRF for control register.


I think I'd like it more to use the generic grf-binding we always use
everwhere else (just the phandle without any offset) and keep the actual
offset in the driver on a per-soc basis.

That way rockchip,grf stays consistent over all users.

We already have the per-soc compatible values, so it should a easy to add a
.data element with the necessary offset-information.


+
  Example for rk3288 I2S controller:

  i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c
b/sound/soc/rockchip/rockchip_i2s.c index 2f8e204..bc72780 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c


[...]


@@ -478,6 +504,18 @@ static int rockchip_i2s_probe(struct platform_device
*pdev) return -ENOMEM;
}

+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   ret = of_property_read_u32_index(node, "rockchip,grf",
+1, >iocfg_reg);
+   if (ret) {
+   dev_err(>dev, "Can't get iocfg_reg offset\n");
+   return ret;
+   }
+   }
+


as said in the binding part, please use the generic grf handling and get the
io-offset from per-soc devicetree data in the driver itself.



/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
@@ -517,7 +555,6 @@ static int rockchip_i2s_probe(struct platform_device
*pdev) i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4;

-   i2s->dev = >dev;
dev_set_drvdata(>dev, i2s);

pm_runtime_enable(>dev);
diff --git a/sound/soc/rockchip/rockchip_i2s.h
b/sound/soc/rockchip/rockchip_i2s.h index dc6e2c7..9a6aabf 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -236,4 +236,12 @@ enum {
  #define I2S_TXDR  (0x0024)
  #define I2S_RXDR  (0x0028)

+/* io direction cfg register */
+#define I2S_IO_DIRECTION_SHIFT 11


this setting is sitting in GRF_SOC_CON8 on the rk3399. That is part of the
very volatile register set where settings move around a lot for each soc.

So if we're having the io-offset in per-soc data, we can easily put the
shift into it as well.


+#define I2S_IO_DIRECTION_MASK  (7 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_8CH_OUT_2CH_IN  (0 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_6CH_OUT_4CH_IN  (1 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_4CH_OUT_6CH_IN  (3 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_2CH_OUT_8CH_IN  (7 << I2S_IO_DIRECTION_SHIFT)


Keep the settings without the shift here and do the shift dynamically with
the per-soc setting when changing the setting.


Thanks
Heiko

___
Linux-rockchip mailing list
linux-rockc...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip







Re: [PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-10 Thread sugar

Hi Heiko,

Got it, thanks for your advice, these will be done in next version.

On 4/9/2016 01:14, Heiko Stuebner Wrote:

Hi,

Am Mittwoch, 6. April 2016, 16:38:22 schrieb Sugar Zhang:

There are 3 i2s sdio pins, which iomux mode is as follows:

  - sdi3_sdo1
  - sdi2_sdo2
  - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang 
---

  .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
  sound/soc/rockchip/rockchip_i2s.c  | 39
+- sound/soc/rockchip/rockchip_i2s.h
|  8 +
  3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt index
6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
  - rockchip,playback-channels: max playback channels, if not set, 8
channels default. - rockchip,capture-channels: max capture channels, if
not set, 2 channels default.

+Required properties for controller which support multi channels
playback/capture: +
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon
node for GRF register, +  and the offset of the GRF for control register.


I think I'd like it more to use the generic grf-binding we always use
everwhere else (just the phandle without any offset) and keep the actual
offset in the driver on a per-soc basis.

That way rockchip,grf stays consistent over all users.

We already have the per-soc compatible values, so it should a easy to add a
.data element with the necessary offset-information.


+
  Example for rk3288 I2S controller:

  i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c
b/sound/soc/rockchip/rockchip_i2s.c index 2f8e204..bc72780 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c


[...]


@@ -478,6 +504,18 @@ static int rockchip_i2s_probe(struct platform_device
*pdev) return -ENOMEM;
}

+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   ret = of_property_read_u32_index(node, "rockchip,grf",
+1, >iocfg_reg);
+   if (ret) {
+   dev_err(>dev, "Can't get iocfg_reg offset\n");
+   return ret;
+   }
+   }
+


as said in the binding part, please use the generic grf handling and get the
io-offset from per-soc devicetree data in the driver itself.



/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
@@ -517,7 +555,6 @@ static int rockchip_i2s_probe(struct platform_device
*pdev) i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4;

-   i2s->dev = >dev;
dev_set_drvdata(>dev, i2s);

pm_runtime_enable(>dev);
diff --git a/sound/soc/rockchip/rockchip_i2s.h
b/sound/soc/rockchip/rockchip_i2s.h index dc6e2c7..9a6aabf 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -236,4 +236,12 @@ enum {
  #define I2S_TXDR  (0x0024)
  #define I2S_RXDR  (0x0028)

+/* io direction cfg register */
+#define I2S_IO_DIRECTION_SHIFT 11


this setting is sitting in GRF_SOC_CON8 on the rk3399. That is part of the
very volatile register set where settings move around a lot for each soc.

So if we're having the io-offset in per-soc data, we can easily put the
shift into it as well.


+#define I2S_IO_DIRECTION_MASK  (7 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_8CH_OUT_2CH_IN  (0 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_6CH_OUT_4CH_IN  (1 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_4CH_OUT_6CH_IN  (3 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_2CH_OUT_8CH_IN  (7 << I2S_IO_DIRECTION_SHIFT)


Keep the settings without the shift here and do the shift dynamically with
the per-soc setting when changing the setting.


Thanks
Heiko

___
Linux-rockchip mailing list
linux-rockc...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip







Re: [PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-08 Thread sugar

Hi Rob,

On 4/8/2016 01:58, Rob Herring Wrote:

On Wed, Apr 06, 2016 at 04:38:22PM +0800, Sugar Zhang wrote:

There are 3 i2s sdio pins, which iomux mode is as follows:


s/i2s sdio/I2S\/SDIO muxed/



  - sdi3_sdo1
  - sdi2_sdo2
  - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.


Why not a pinctrl binding here? If you want SDIO mode, then you need
similar code in the SDIO driver (or just rely on default mode).


here, i2s_sdio means i2s_sdi/i2s_sdo, not means SDIO bus interface.
for example:

gpio3d[6] iomux select:
2'b 00: gpio
2'b 01: i2s0_sdi3sdo1
2'b 10: xxx
2'b 11: xxx

we configure the i2s_sdi3sdo1 mode via the pinctrl, and then need another
grf register to configure it is used for i2s0_sdi3 or i2s0_sdo1.



Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

  .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
  sound/soc/rockchip/rockchip_i2s.c  | 39 +-
  sound/soc/rockchip/rockchip_i2s.h  |  8 +
  3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
  - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
  - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.

+Required properties for controller which support multi channels 
playback/capture:
+
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon node 
for GRF register,


Wrap your lines at less than 80 chars.


Ok, will fix.



+  and the offset of the GRF for control register.
+
  Example for rk3288 I2S controller:

  i2s@ff89 {


___
Linux-rockchip mailing list
linux-rockc...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip







Re: [PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-08 Thread sugar

Hi Rob,

On 4/8/2016 01:58, Rob Herring Wrote:

On Wed, Apr 06, 2016 at 04:38:22PM +0800, Sugar Zhang wrote:

There are 3 i2s sdio pins, which iomux mode is as follows:


s/i2s sdio/I2S\/SDIO muxed/



  - sdi3_sdo1
  - sdi2_sdo2
  - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.


Why not a pinctrl binding here? If you want SDIO mode, then you need
similar code in the SDIO driver (or just rely on default mode).


here, i2s_sdio means i2s_sdi/i2s_sdo, not means SDIO bus interface.
for example:

gpio3d[6] iomux select:
2'b 00: gpio
2'b 01: i2s0_sdi3sdo1
2'b 10: xxx
2'b 11: xxx

we configure the i2s_sdi3sdo1 mode via the pinctrl, and then need another
grf register to configure it is used for i2s0_sdi3 or i2s0_sdo1.



Signed-off-by: Sugar Zhang 
---

  .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
  sound/soc/rockchip/rockchip_i2s.c  | 39 +-
  sound/soc/rockchip/rockchip_i2s.h  |  8 +
  3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
  - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
  - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.

+Required properties for controller which support multi channels 
playback/capture:
+
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon node 
for GRF register,


Wrap your lines at less than 80 chars.


Ok, will fix.



+  and the offset of the GRF for control register.
+
  Example for rk3288 I2S controller:

  i2s@ff89 {


___
Linux-rockchip mailing list
linux-rockc...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip







[PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-06 Thread Sugar Zhang
There are 3 i2s sdio pins, which iomux mode is as follows:

 - sdi3_sdo1
 - sdi2_sdo2
 - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
 sound/soc/rockchip/rockchip_i2s.c  | 39 +-
 sound/soc/rockchip/rockchip_i2s.h  |  8 +
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
 
+Required properties for controller which support multi channels 
playback/capture:
+
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon node 
for GRF register,
+  and the offset of the GRF for control register.
+
 Example for rk3288 I2S controller:
 
 i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e204..bc72780 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -11,6 +11,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,6 +34,8 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data;
 
struct regmap *regmap;
+   struct regmap *grf;
+   u32 iocfg_reg;
 
bool is_master_mode;
 };
@@ -277,6 +280,29 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
   val);
 
+   if (!IS_ERR(i2s->grf)) {
+   regmap_read(i2s->regmap, I2S_TXCR, );
+   val &= I2S_TXCR_CSR_MASK;
+
+   switch (val) {
+   case I2S_CHN_4:
+   val = I2S_IO_4CH_OUT_6CH_IN;
+   break;
+   case I2S_CHN_6:
+   val = I2S_IO_6CH_OUT_4CH_IN;
+   break;
+   case I2S_CHN_8:
+   val = I2S_IO_8CH_OUT_2CH_IN;
+   break;
+   default:
+   val = I2S_IO_2CH_OUT_8CH_IN;
+   break;
+   }
+
+   regmap_write(i2s->grf, i2s->iocfg_reg,
+I2S_IO_DIRECTION_MASK << 16 | val);
+   }
+
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
   I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
@@ -478,6 +504,18 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return -ENOMEM;
}
 
+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   ret = of_property_read_u32_index(node, "rockchip,grf",
+1, >iocfg_reg);
+   if (ret) {
+   dev_err(>dev, "Can't get iocfg_reg offset\n");
+   return ret;
+   }
+   }
+
/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
@@ -517,7 +555,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4;
 
-   i2s->dev = >dev;
dev_set_drvdata(>dev, i2s);
 
pm_runtime_enable(>dev);
diff --git a/sound/soc/rockchip/rockchip_i2s.h 
b/sound/soc/rockchip/rockchip_i2s.h
index dc6e2c7..9a6aabf 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -236,4 +236,12 @@ enum {
 #define I2S_TXDR   (0x0024)
 #define I2S_RXDR   (0x0028)
 
+/* io direction cfg register */
+#define I2S_IO_DIRECTION_SHIFT 11
+#define I2S_IO_DIRECTION_MASK  (7 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_8CH_OUT_2CH_IN  (0 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_6CH_OUT_4CH_IN  (1 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_4CH_OUT_6CH_IN  (3 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_2CH_OUT_8CH_IN  (7 << I2S_IO_DIRECTION_SHIFT)
+
 #endif /* _ROCKCHIP_IIS_H */
-- 
1.9.1




[PATCH] ASoC: rockchip: i2s: configure the sdio pins' iomux mode

2016-04-06 Thread Sugar Zhang
There are 3 i2s sdio pins, which iomux mode is as follows:

 - sdi3_sdo1
 - sdi2_sdo2
 - sdi1_sdo3

we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.

Signed-off-by: Sugar Zhang 
---

 .../devicetree/bindings/sound/rockchip-i2s.txt |  5 +++
 sound/soc/rockchip/rockchip_i2s.c  | 39 +-
 sound/soc/rockchip/rockchip_i2s.h  |  8 +
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt 
b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 6e86d8a..ad72a7d 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -23,6 +23,11 @@ Required properties:
 - rockchip,playback-channels: max playback channels, if not set, 8 channels 
default.
 - rockchip,capture-channels: max capture channels, if not set, 2 channels 
default.
 
+Required properties for controller which support multi channels 
playback/capture:
+
+- rockchip,grf: Should be phandle/offset pair. the phandle of the syscon node 
for GRF register,
+  and the offset of the GRF for control register.
+
 Example for rk3288 I2S controller:
 
 i2s@ff89 {
diff --git a/sound/soc/rockchip/rockchip_i2s.c 
b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e204..bc72780 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -11,6 +11,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,6 +34,8 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data;
 
struct regmap *regmap;
+   struct regmap *grf;
+   u32 iocfg_reg;
 
bool is_master_mode;
 };
@@ -277,6 +280,29 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream 
*substream,
   I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
   val);
 
+   if (!IS_ERR(i2s->grf)) {
+   regmap_read(i2s->regmap, I2S_TXCR, );
+   val &= I2S_TXCR_CSR_MASK;
+
+   switch (val) {
+   case I2S_CHN_4:
+   val = I2S_IO_4CH_OUT_6CH_IN;
+   break;
+   case I2S_CHN_6:
+   val = I2S_IO_6CH_OUT_4CH_IN;
+   break;
+   case I2S_CHN_8:
+   val = I2S_IO_8CH_OUT_2CH_IN;
+   break;
+   default:
+   val = I2S_IO_2CH_OUT_8CH_IN;
+   break;
+   }
+
+   regmap_write(i2s->grf, i2s->iocfg_reg,
+I2S_IO_DIRECTION_MASK << 16 | val);
+   }
+
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
   I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
@@ -478,6 +504,18 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return -ENOMEM;
}
 
+   i2s->dev = >dev;
+
+   i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
+   if (!IS_ERR(i2s->grf)) {
+   ret = of_property_read_u32_index(node, "rockchip,grf",
+1, >iocfg_reg);
+   if (ret) {
+   dev_err(>dev, "Can't get iocfg_reg offset\n");
+   return ret;
+   }
+   }
+
/* try to prepare related clocks */
i2s->hclk = devm_clk_get(>dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
@@ -517,7 +555,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4;
 
-   i2s->dev = >dev;
dev_set_drvdata(>dev, i2s);
 
pm_runtime_enable(>dev);
diff --git a/sound/soc/rockchip/rockchip_i2s.h 
b/sound/soc/rockchip/rockchip_i2s.h
index dc6e2c7..9a6aabf 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -236,4 +236,12 @@ enum {
 #define I2S_TXDR   (0x0024)
 #define I2S_RXDR   (0x0028)
 
+/* io direction cfg register */
+#define I2S_IO_DIRECTION_SHIFT 11
+#define I2S_IO_DIRECTION_MASK  (7 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_8CH_OUT_2CH_IN  (0 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_6CH_OUT_4CH_IN  (1 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_4CH_OUT_6CH_IN  (3 << I2S_IO_DIRECTION_SHIFT)
+#define I2S_IO_2CH_OUT_8CH_IN  (7 << I2S_IO_DIRECTION_SHIFT)
+
 #endif /* _ROCKCHIP_IIS_H */
-- 
1.9.1




[PATCH] ASoC: rt5640: Correct the digital interface data select

2016-03-19 Thread Sugar Zhang
this patch corrects the interface adc/dac control register definition
according to datasheet.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 sound/soc/codecs/rt5640.c |  2 +-
 sound/soc/codecs/rt5640.h | 36 ++--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 11d032c..48dbb2f 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -359,7 +359,7 @@ static const DECLARE_TLV_DB_RANGE(bst_tlv,
 
 /* Interface data select */
 static const char * const rt5640_data_select[] = {
-   "Normal", "left copy to right", "right copy to left", "Swap"};
+   "Normal", "Swap", "left copy to right", "right copy to left"};
 
 static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 83a7150..f84231e 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -442,39 +442,39 @@
 #define RT5640_IF1_DAC_SEL_MASK(0x3 << 14)
 #define RT5640_IF1_DAC_SEL_SFT 14
 #define RT5640_IF1_DAC_SEL_NOR (0x0 << 14)
-#define RT5640_IF1_DAC_SEL_L2R (0x1 << 14)
-#define RT5640_IF1_DAC_SEL_R2L (0x2 << 14)
-#define RT5640_IF1_DAC_SEL_SWAP(0x3 << 14)
+#define RT5640_IF1_DAC_SEL_SWAP(0x1 << 14)
+#define RT5640_IF1_DAC_SEL_L2R (0x2 << 14)
+#define RT5640_IF1_DAC_SEL_R2L (0x3 << 14)
 #define RT5640_IF1_ADC_SEL_MASK(0x3 << 12)
 #define RT5640_IF1_ADC_SEL_SFT 12
 #define RT5640_IF1_ADC_SEL_NOR (0x0 << 12)
-#define RT5640_IF1_ADC_SEL_L2R (0x1 << 12)
-#define RT5640_IF1_ADC_SEL_R2L (0x2 << 12)
-#define RT5640_IF1_ADC_SEL_SWAP(0x3 << 12)
+#define RT5640_IF1_ADC_SEL_SWAP(0x1 << 12)
+#define RT5640_IF1_ADC_SEL_L2R (0x2 << 12)
+#define RT5640_IF1_ADC_SEL_R2L (0x3 << 12)
 #define RT5640_IF2_DAC_SEL_MASK(0x3 << 10)
 #define RT5640_IF2_DAC_SEL_SFT 10
 #define RT5640_IF2_DAC_SEL_NOR (0x0 << 10)
-#define RT5640_IF2_DAC_SEL_L2R (0x1 << 10)
-#define RT5640_IF2_DAC_SEL_R2L (0x2 << 10)
-#define RT5640_IF2_DAC_SEL_SWAP(0x3 << 10)
+#define RT5640_IF2_DAC_SEL_SWAP(0x1 << 10)
+#define RT5640_IF2_DAC_SEL_L2R (0x2 << 10)
+#define RT5640_IF2_DAC_SEL_R2L (0x3 << 10)
 #define RT5640_IF2_ADC_SEL_MASK(0x3 << 8)
 #define RT5640_IF2_ADC_SEL_SFT 8
 #define RT5640_IF2_ADC_SEL_NOR (0x0 << 8)
-#define RT5640_IF2_ADC_SEL_L2R (0x1 << 8)
-#define RT5640_IF2_ADC_SEL_R2L (0x2 << 8)
-#define RT5640_IF2_ADC_SEL_SWAP(0x3 << 8)
+#define RT5640_IF2_ADC_SEL_SWAP(0x1 << 8)
+#define RT5640_IF2_ADC_SEL_L2R (0x2 << 8)
+#define RT5640_IF2_ADC_SEL_R2L (0x3 << 8)
 #define RT5640_IF3_DAC_SEL_MASK(0x3 << 6)
 #define RT5640_IF3_DAC_SEL_SFT 6
 #define RT5640_IF3_DAC_SEL_NOR (0x0 << 6)
-#define RT5640_IF3_DAC_SEL_L2R (0x1 << 6)
-#define RT5640_IF3_DAC_SEL_R2L (0x2 << 6)
-#define RT5640_IF3_DAC_SEL_SWAP(0x3 << 6)
+#define RT5640_IF3_DAC_SEL_SWAP(0x1 << 6)
+#define RT5640_IF3_DAC_SEL_L2R (0x2 << 6)
+#define RT5640_IF3_DAC_SEL_R2L (0x3 << 6)
 #define RT5640_IF3_ADC_SEL_MASK(0x3 << 4)
 #define RT5640_IF3_ADC_SEL_SFT 4
 #define RT5640_IF3_ADC_SEL_NOR (0x0 << 4)
-#define RT5640_IF3_ADC_SEL_L2R (0x1 << 4)
-#define RT5640_IF3_ADC_SEL_R2L (0x2 << 4)
-#define RT5640_IF3_ADC_SEL_SWAP(0x3 << 4)
+#define RT5640_IF3_ADC_SEL_SWAP(0x1 << 4)
+#define RT5640_IF3_ADC_SEL_L2R (0x2 << 4)
+#define RT5640_IF3_ADC_SEL_R2L (0x3 << 4)
 
 /* REC Left Mixer Control 1 (0x3b) */
 #define RT5640_G_HP_L_RM_L_MASK(0x7 << 13)
-- 
1.9.1




[PATCH] ASoC: rt5640: Correct the digital interface data select

2016-03-19 Thread Sugar Zhang
this patch corrects the interface adc/dac control register definition
according to datasheet.

Signed-off-by: Sugar Zhang 
---

 sound/soc/codecs/rt5640.c |  2 +-
 sound/soc/codecs/rt5640.h | 36 ++--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 11d032c..48dbb2f 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -359,7 +359,7 @@ static const DECLARE_TLV_DB_RANGE(bst_tlv,
 
 /* Interface data select */
 static const char * const rt5640_data_select[] = {
-   "Normal", "left copy to right", "right copy to left", "Swap"};
+   "Normal", "Swap", "left copy to right", "right copy to left"};
 
 static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 83a7150..f84231e 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -442,39 +442,39 @@
 #define RT5640_IF1_DAC_SEL_MASK(0x3 << 14)
 #define RT5640_IF1_DAC_SEL_SFT 14
 #define RT5640_IF1_DAC_SEL_NOR (0x0 << 14)
-#define RT5640_IF1_DAC_SEL_L2R (0x1 << 14)
-#define RT5640_IF1_DAC_SEL_R2L (0x2 << 14)
-#define RT5640_IF1_DAC_SEL_SWAP(0x3 << 14)
+#define RT5640_IF1_DAC_SEL_SWAP(0x1 << 14)
+#define RT5640_IF1_DAC_SEL_L2R (0x2 << 14)
+#define RT5640_IF1_DAC_SEL_R2L (0x3 << 14)
 #define RT5640_IF1_ADC_SEL_MASK(0x3 << 12)
 #define RT5640_IF1_ADC_SEL_SFT 12
 #define RT5640_IF1_ADC_SEL_NOR (0x0 << 12)
-#define RT5640_IF1_ADC_SEL_L2R (0x1 << 12)
-#define RT5640_IF1_ADC_SEL_R2L (0x2 << 12)
-#define RT5640_IF1_ADC_SEL_SWAP(0x3 << 12)
+#define RT5640_IF1_ADC_SEL_SWAP(0x1 << 12)
+#define RT5640_IF1_ADC_SEL_L2R (0x2 << 12)
+#define RT5640_IF1_ADC_SEL_R2L (0x3 << 12)
 #define RT5640_IF2_DAC_SEL_MASK(0x3 << 10)
 #define RT5640_IF2_DAC_SEL_SFT 10
 #define RT5640_IF2_DAC_SEL_NOR (0x0 << 10)
-#define RT5640_IF2_DAC_SEL_L2R (0x1 << 10)
-#define RT5640_IF2_DAC_SEL_R2L (0x2 << 10)
-#define RT5640_IF2_DAC_SEL_SWAP(0x3 << 10)
+#define RT5640_IF2_DAC_SEL_SWAP(0x1 << 10)
+#define RT5640_IF2_DAC_SEL_L2R (0x2 << 10)
+#define RT5640_IF2_DAC_SEL_R2L (0x3 << 10)
 #define RT5640_IF2_ADC_SEL_MASK(0x3 << 8)
 #define RT5640_IF2_ADC_SEL_SFT 8
 #define RT5640_IF2_ADC_SEL_NOR (0x0 << 8)
-#define RT5640_IF2_ADC_SEL_L2R (0x1 << 8)
-#define RT5640_IF2_ADC_SEL_R2L (0x2 << 8)
-#define RT5640_IF2_ADC_SEL_SWAP(0x3 << 8)
+#define RT5640_IF2_ADC_SEL_SWAP(0x1 << 8)
+#define RT5640_IF2_ADC_SEL_L2R (0x2 << 8)
+#define RT5640_IF2_ADC_SEL_R2L (0x3 << 8)
 #define RT5640_IF3_DAC_SEL_MASK(0x3 << 6)
 #define RT5640_IF3_DAC_SEL_SFT 6
 #define RT5640_IF3_DAC_SEL_NOR (0x0 << 6)
-#define RT5640_IF3_DAC_SEL_L2R (0x1 << 6)
-#define RT5640_IF3_DAC_SEL_R2L (0x2 << 6)
-#define RT5640_IF3_DAC_SEL_SWAP(0x3 << 6)
+#define RT5640_IF3_DAC_SEL_SWAP(0x1 << 6)
+#define RT5640_IF3_DAC_SEL_L2R (0x2 << 6)
+#define RT5640_IF3_DAC_SEL_R2L (0x3 << 6)
 #define RT5640_IF3_ADC_SEL_MASK(0x3 << 4)
 #define RT5640_IF3_ADC_SEL_SFT 4
 #define RT5640_IF3_ADC_SEL_NOR (0x0 << 4)
-#define RT5640_IF3_ADC_SEL_L2R (0x1 << 4)
-#define RT5640_IF3_ADC_SEL_R2L (0x2 << 4)
-#define RT5640_IF3_ADC_SEL_SWAP(0x3 << 4)
+#define RT5640_IF3_ADC_SEL_SWAP(0x1 << 4)
+#define RT5640_IF3_ADC_SEL_L2R (0x2 << 4)
+#define RT5640_IF3_ADC_SEL_R2L (0x3 << 4)
 
 /* REC Left Mixer Control 1 (0x3b) */
 #define RT5640_G_HP_L_RM_L_MASK(0x7 << 13)
-- 
1.9.1




[PATCH] ASoC: rockchip: add bindings for spdif controller

2016-03-04 Thread Sugar Zhang
this patch add compatible for rk3366/rk3368/rk3399 spdif,
these three spdifs share the same type.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 Documentation/devicetree/bindings/sound/rockchip-spdif.txt |  8 ++--
 sound/soc/rockchip/rockchip_spdif.c| 13 ++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt 
b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
index e64dbde..1104642 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
@@ -7,8 +7,12 @@ a fibre cable.
 Required properties:
 
 - compatible: should be one of the following:
-   - "rockchip,rk3288-spdif", "rockchip,rk3188-spdif" or
- "rockchip,rk3066-spdif"
+   - "rockchip,rk3066-spdif"
+   - "rockchip,rk3188-spdif"
+   - "rockchip,rk3288-spdif"
+   - "rockchip,rk3366-spdif"
+   - "rockchip,rk3368-spdif"
+   - "rockchip,rk3399-spdif"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: should contain the SPDIF interrupt.
diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 5a806da..c589f6f 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -28,6 +28,7 @@ enum rk_spdif_type {
RK_SPDIF_RK3066,
RK_SPDIF_RK3188,
RK_SPDIF_RK3288,
+   RK_SPDIF_RK3366,
 };
 
 #define RK3288_GRF_SOC_CON2 0x24c
@@ -45,11 +46,17 @@ struct rk_spdif_dev {
 
 static const struct of_device_id rk_spdif_match[] = {
{ .compatible = "rockchip,rk3066-spdif",
- .data = (void *) RK_SPDIF_RK3066 },
+ .data = (void *)RK_SPDIF_RK3066 },
{ .compatible = "rockchip,rk3188-spdif",
- .data = (void *) RK_SPDIF_RK3188 },
+ .data = (void *)RK_SPDIF_RK3188 },
{ .compatible = "rockchip,rk3288-spdif",
- .data = (void *) RK_SPDIF_RK3288 },
+ .data = (void *)RK_SPDIF_RK3288 },
+   { .compatible = "rockchip,rk3366-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
+   { .compatible = "rockchip,rk3368-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
+   { .compatible = "rockchip,rk3399-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{},
 };
 MODULE_DEVICE_TABLE(of, rk_spdif_match);
-- 
1.9.1




[PATCH] ASoC: rockchip: add bindings for spdif controller

2016-03-04 Thread Sugar Zhang
this patch add compatible for rk3366/rk3368/rk3399 spdif,
these three spdifs share the same type.

Signed-off-by: Sugar Zhang 
---

 Documentation/devicetree/bindings/sound/rockchip-spdif.txt |  8 ++--
 sound/soc/rockchip/rockchip_spdif.c| 13 ++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt 
b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
index e64dbde..1104642 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
@@ -7,8 +7,12 @@ a fibre cable.
 Required properties:
 
 - compatible: should be one of the following:
-   - "rockchip,rk3288-spdif", "rockchip,rk3188-spdif" or
- "rockchip,rk3066-spdif"
+   - "rockchip,rk3066-spdif"
+   - "rockchip,rk3188-spdif"
+   - "rockchip,rk3288-spdif"
+   - "rockchip,rk3366-spdif"
+   - "rockchip,rk3368-spdif"
+   - "rockchip,rk3399-spdif"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: should contain the SPDIF interrupt.
diff --git a/sound/soc/rockchip/rockchip_spdif.c 
b/sound/soc/rockchip/rockchip_spdif.c
index 5a806da..c589f6f 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -28,6 +28,7 @@ enum rk_spdif_type {
RK_SPDIF_RK3066,
RK_SPDIF_RK3188,
RK_SPDIF_RK3288,
+   RK_SPDIF_RK3366,
 };
 
 #define RK3288_GRF_SOC_CON2 0x24c
@@ -45,11 +46,17 @@ struct rk_spdif_dev {
 
 static const struct of_device_id rk_spdif_match[] = {
{ .compatible = "rockchip,rk3066-spdif",
- .data = (void *) RK_SPDIF_RK3066 },
+ .data = (void *)RK_SPDIF_RK3066 },
{ .compatible = "rockchip,rk3188-spdif",
- .data = (void *) RK_SPDIF_RK3188 },
+ .data = (void *)RK_SPDIF_RK3188 },
{ .compatible = "rockchip,rk3288-spdif",
- .data = (void *) RK_SPDIF_RK3288 },
+ .data = (void *)RK_SPDIF_RK3288 },
+   { .compatible = "rockchip,rk3366-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
+   { .compatible = "rockchip,rk3368-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
+   { .compatible = "rockchip,rk3399-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{},
 };
 MODULE_DEVICE_TABLE(of, rk_spdif_match);
-- 
1.9.1




[PATCH] ASoC: rt5640: add master clock handling for rt5640

2016-02-22 Thread Sugar Zhang
enable/disable master clock when codec is active or not.

Signed-off-by: Sugar Zhang <sugar.zh...@rock-chips.com>
---

 Documentation/devicetree/bindings/sound/rt5640.txt |  3 +++
 sound/soc/codecs/rt5640.c  | 31 ++
 sound/soc/codecs/rt5640.h  |  2 ++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt 
b/Documentation/devicetree/bindings/sound/rt5640.txt
index 9e62f6e..57fe646 100644
--- a/Documentation/devicetree/bindings/sound/rt5640.txt
+++ b/Documentation/devicetree/bindings/sound/rt5640.txt
@@ -12,6 +12,9 @@ Required properties:
 
 Optional properties:
 
+- clocks: The phandle of the master clock to the CODEC
+- clock-names: Should be "mclk"
+
 - realtek,in1-differential
 - realtek,in2-differential
 - realtek,in3-differential
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 11d032c..6cd84fb 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1949,7 +1949,33 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, 
int pll_id, int source,
 static int rt5640_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
 {
+   struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+   int ret;
+
switch (level) {
+   case SND_SOC_BIAS_ON:
+   break;
+
+   case SND_SOC_BIAS_PREPARE:
+   /*
+* SND_SOC_BIAS_PREPARE is called while preparing for a
+* transition to ON or away from ON. If current bias_level
+* is SND_SOC_BIAS_ON, then it is preparing for a transition
+* away from ON. Disable the clock in that case, otherwise
+* enable it.
+*/
+   if (IS_ERR(rt5640->mclk))
+   break;
+
+   if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
+   clk_disable_unprepare(rt5640->mclk);
+   } else {
+   ret = clk_prepare_enable(rt5640->mclk);
+   if (ret)
+   return ret;
+   }
+   break;
+
case SND_SOC_BIAS_STANDBY:
if (SND_SOC_BIAS_OFF == snd_soc_codec_get_bias_level(codec)) {
snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
@@ -2088,6 +2114,11 @@ static int rt5640_probe(struct snd_soc_codec *codec)
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
 
+   /* Check if MCLK provided */
+   rt5640->mclk = devm_clk_get(codec->dev, "mclk");
+   if (PTR_ERR(rt5640->mclk) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
+
rt5640->codec = codec;
 
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 83a7150..1761c3a9 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -12,6 +12,7 @@
 #ifndef _RT5640_H
 #define _RT5640_H
 
+#include 
 #include 
 
 /* Info */
@@ -2097,6 +2098,7 @@ struct rt5640_priv {
struct snd_soc_codec *codec;
struct rt5640_platform_data pdata;
struct regmap *regmap;
+   struct clk *mclk;
 
int sysclk;
int sysclk_src;
-- 
1.9.1




  1   2   >