MIPS: TXx9: Add ACLC support

Add platform support for ACLC of TXx9 SoCs.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 369d863..7f91012 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -876,3 +876,39 @@
 	}
 #endif
 }
+
+void __init txx9_aclc_init(unsigned long baseaddr, int irq,
+			   unsigned int dmac_id,
+			   unsigned int dma_chan_out,
+			   unsigned int dma_chan_in)
+{
+#if defined(CONFIG_SND_SOC_TXX9ACLC) || \
+	defined(CONFIG_SND_SOC_TXX9ACLC_MODULE)
+	unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS;
+	struct resource res[] = {
+		{
+			.start = baseaddr,
+			.end = baseaddr + 0x100 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_out,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_in,
+			.flags = IORESOURCE_DMA,
+		}
+	};
+	struct platform_device *pdev =
+		platform_device_alloc("txx9aclc-ac97", -1);
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+#endif
+}
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c
index 6b681cd..3418b2a 100644
--- a/arch/mips/txx9/generic/setup_tx4927.c
+++ b/arch/mips/txx9/generic/setup_tx4927.c
@@ -265,6 +265,49 @@
 		       TXX9_IRQ_BASE + TX4927_IR_DMA(0), &plat_data);
 }
 
+void __init tx4927_aclc_init(unsigned int dma_chan_out,
+			     unsigned int dma_chan_in)
+{
+	u64 pcfg = __raw_readq(&tx4927_ccfgptr->pcfg);
+	__u64 dmasel_mask = 0, dmasel = 0;
+	unsigned long flags;
+
+	if (!(pcfg & TX4927_PCFG_SEL2))
+		return;
+	/* setup DMASEL (playback:ACLC ch0, capture:ACLC ch1) */
+	switch (dma_chan_out) {
+	case 0:
+		dmasel_mask |= TX4927_PCFG_DMASEL0_MASK;
+		dmasel |= TX4927_PCFG_DMASEL0_ACL0;
+		break;
+	case 2:
+		dmasel_mask |= TX4927_PCFG_DMASEL2_MASK;
+		dmasel |= TX4927_PCFG_DMASEL2_ACL0;
+		break;
+	default:
+		return;
+	}
+	switch (dma_chan_in) {
+	case 1:
+		dmasel_mask |= TX4927_PCFG_DMASEL1_MASK;
+		dmasel |= TX4927_PCFG_DMASEL1_ACL1;
+		break;
+	case 3:
+		dmasel_mask |= TX4927_PCFG_DMASEL3_MASK;
+		dmasel |= TX4927_PCFG_DMASEL3_ACL1;
+		break;
+	default:
+		return;
+	}
+	local_irq_save(flags);
+	txx9_clear64(&tx4927_ccfgptr->pcfg, dmasel_mask);
+	txx9_set64(&tx4927_ccfgptr->pcfg, dmasel);
+	local_irq_restore(flags);
+	txx9_aclc_init(TX4927_ACLC_REG & 0xfffffffffULL,
+		       TXX9_IRQ_BASE + TX4927_IR_ACLC,
+		       0, dma_chan_out, dma_chan_in);
+}
+
 static void __init tx4927_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c
index b2b8529..4dfdb52 100644
--- a/arch/mips/txx9/generic/setup_tx4938.c
+++ b/arch/mips/txx9/generic/setup_tx4938.c
@@ -414,6 +414,17 @@
 	}
 }
 
+void __init tx4938_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg);
+
+	if ((pcfg & TX4938_PCFG_SEL2) &&
+	    !(pcfg & TX4938_PCFG_ETH0_SEL))
+		txx9_aclc_init(TX4938_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4938_IR_ACLC,
+			       1, 0, 1);
+}
+
 static void __init tx4938_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index 98effef..7139686 100644
--- a/arch/mips/txx9/generic/setup_tx4939.c
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -485,6 +485,15 @@
 	}
 }
 
+void __init tx4939_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_ACLC)
+		txx9_aclc_init(TX4939_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4939_IR_ACLC, 1, 0, 1);
+}
+
 static void __init tx4939_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;