[alsa-devel] [RESEND RFC PATCH 2/3] ASoC: mediatek: Add AFE connection control

Koro Chen koro.chen at mediatek.com
Fri Apr 10 10:14:08 CEST 2015


This is the AFE inter-connection control APIs.

Signed-off-by: Koro Chen <koro.chen at mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 sound/soc/mediatek/mtk-afe-common.h     | 105 ++++++++
 sound/soc/mediatek/mtk-afe-connection.c | 416 ++++++++++++++++++++++++++++++++
 sound/soc/mediatek/mtk-afe-connection.h |  30 +++
 3 files changed, 551 insertions(+)
 create mode 100644 sound/soc/mediatek/mtk-afe-common.h
 create mode 100644 sound/soc/mediatek/mtk-afe-connection.c
 create mode 100644 sound/soc/mediatek/mtk-afe-connection.h

diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h
new file mode 100644
index 0000000..71b426d
--- /dev/null
+++ b/sound/soc/mediatek/mtk-afe-common.h
@@ -0,0 +1,105 @@
+/*
+ * mtk_afe_common.h  --  Mediatek audio driver common definitions
+ *
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Koro Chen <koro.chen at mediatek.com>
+ *             Sascha Hauer <s.hauer at pengutronix.de>
+ *             Hidalgo Huang <hidalgo.huang at mediatek.com>
+ *             Ir Lian <ir.lian at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_AFE_COMMON_H_
+#define _MTK_AFE_COMMON_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <dt-bindings/sound/mtk-afe.h>
+
+enum {
+	MTK_CLK_INFRASYS_AUD,
+	MTK_CLK_TOP_PDN_AUD,
+	MTK_CLK_TOP_PDN_AUD_BUS,
+	MTK_CLK_I2S0_M,
+	MTK_CLK_I2S1_M,
+	MTK_CLK_I2S2_M,
+	MTK_CLK_I2S3_M,
+	MTK_CLK_I2S3_B,
+	MTK_CLK_BCK0,
+	MTK_CLK_BCK1,
+	MTK_CLK_NUM
+};
+
+struct mtk_afe;
+struct snd_pcm_substream;
+
+struct mtk_afe_io_data {
+	int num;
+	const char *name;
+	int (*startup)(struct mtk_afe *, struct snd_pcm_substream *);
+	void (*shutdown)(struct mtk_afe *, struct snd_pcm_substream *);
+	int (*prepare)(struct mtk_afe *, struct snd_pcm_substream *);
+	int (*start)(struct mtk_afe *, struct snd_pcm_substream *);
+	void (*pause)(struct mtk_afe *, struct snd_pcm_substream *);
+};
+
+struct mtk_afe_io {
+	const struct mtk_afe_io_data *data;
+	struct clk *m_ck;
+	struct clk *b_ck;
+	u32 *connections;
+	int num_connections;
+	int mem[2]; /* playback and capture */
+};
+
+struct mtk_afe_irq_data {
+	int reg_cnt;
+	int cnt_shift;
+	int en_shift;
+	int fs_shift;
+	int clr_shift;
+};
+
+struct mtk_afe_memif_data {
+	int id;
+	const char *name;
+	int reg_ofs_base;
+	int reg_ofs_cur;
+	int fs_shift;
+	int mono_shift;
+	int enable_shift;
+};
+
+struct mtk_afe_memif {
+	unsigned int phys_buf_addr;
+	int buffer_size;
+	unsigned int hw_ptr;		/* Previous IRQ's HW ptr */
+	bool use_sram;
+	struct snd_pcm_substream *substream;
+	const struct mtk_afe_memif_data *data;
+	const struct mtk_afe_irq_data *irqdata;
+};
+
+struct mtk_afe {
+	/* address for ioremap audio hardware register */
+	void __iomem *base_addr;
+	void __iomem *sram_address;
+	u32 sram_phy_address;
+	u32 sram_size;
+	struct device *dev;
+	struct regmap *regmap;
+
+	struct mtk_afe_memif memif[MTK_AFE_MEMIF_NUM];
+	struct mtk_afe_io ios[MTK_AFE_IO_NUM];
+
+	struct clk *clocks[MTK_CLK_NUM];
+};
+#endif
diff --git a/sound/soc/mediatek/mtk-afe-connection.c b/sound/soc/mediatek/mtk-afe-connection.c
new file mode 100644
index 0000000..714e9cd
--- /dev/null
+++ b/sound/soc/mediatek/mtk-afe-connection.c
@@ -0,0 +1,416 @@
+/*
+ * Mediatek AFE audio interconnect support
+ *
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Koro Chen <koro.chen at mediatek.com>
+ *             Sascha Hauer <s.hauer at pengutronix.de>
+ *             Hidalgo Huang <hidalgo.huang at mediatek.com>
+ *             Ir Lian <ir.lian at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "mtk-afe-common.h"
+#include "mtk-afe-connection.h"
+
+#define MTK_AFE_INTERCONN_NUM_INPUT	21
+#define MTK_AFE_INTERCONN_NUM_OUTPUT	23
+
+#define MTK_AFE_HDMI_CONN_INPUT_BASE	30
+#define MTK_AFE_HDMI_CONN_INPUT_MAX	37
+#define MTK_AFE_NUM_HDMI_INPUT		(37 - 30 + 1)
+
+#define MTK_AFE_HDMI_CONN_OUTPUT_BASE	30
+#define MTK_AFE_HDMI_CONN_OUTPUT_MAX	41
+#define MTK_AFE_NUM_HDMI_OUTPUT		(41 - 30 + 1)
+
+struct mtk_afe_connection {
+	short creg, sreg;
+	char cshift, sshift;
+};
+
+/*
+ * The MTK AFE unit has a audio interconnect with MTK_AFE_INTERCONN_NUM_INPUT
+ * inputs and MTK_AFE_INTERCONN_NUM_OUTPUT outputs. Below table holds the
+ * register/bits to set to connect an input with an output.
+ */
+static const struct mtk_afe_connection
+	connections[MTK_AFE_INTERCONN_NUM_INPUT][MTK_AFE_INTERCONN_NUM_OUTPUT] = {
+	[0][0] =   { .creg = 0x020, .cshift =  0, .sreg = 0x020, .sshift = 10},
+	[0][1] =   { .creg = 0x020, .cshift = 16, .sreg = 0x020, .sshift = 26},
+	[0][2] =   { .creg = 0x024, .cshift =  0, .sreg = 0x024, .sshift = 10},
+	[0][3] =   { .creg = 0x024, .cshift = 16, .sreg = 0x024, .sshift = 26},
+	[0][4] =   { .creg = 0x028, .cshift =  0, .sreg = 0x028, .sshift = 10},
+	[0][5] =   { .creg = 0x028, .cshift = 16, .sreg = 0x030, .sshift = 19},
+	[0][7] =   { .creg = 0x05c, .cshift =  2, },
+	[0][9] =   { .creg = 0x05c, .cshift =  8, },
+	[0][10] =  { .creg = 0x05c, .cshift = 12, },
+	[0][13] =  { .creg = 0x448, .cshift =  2, },
+	[0][14] =  { .creg = 0x448, .cshift = 15, },
+	[0][15] =  { .creg = 0x438, .cshift = 16, .sreg = 0x438, .sshift = 31},
+	[0][16] =  { .creg = 0x438, .cshift = 22, .sreg = 0x440, .sshift = 25},
+	[0][19] =  { .creg = 0x464, .cshift =  8, .sreg = 0x464, .sshift =  9},
+	[0][20] =  { .creg = 0x464, .cshift = 24, .sreg = 0x464, .sshift = 25},
+	[1][0] =   { .creg = 0x020, .cshift =  1, .sreg = 0x020, .sshift = 11},
+	[1][1] =   { .creg = 0x020, .cshift = 17, .sreg = 0x020, .sshift = 27},
+	[1][2] =   { .creg = 0x024, .cshift =  1, .sreg = 0x024, .sshift = 11},
+	[1][3] =   { .creg = 0x024, .cshift = 17, .sreg = 0x024, .sshift = 27},
+	[1][4] =   { .creg = 0x028, .cshift =  1, .sreg = 0x028, .sshift = 11},
+	[1][6] =   { .creg = 0x028, .cshift = 22, .sreg = 0x030, .sshift = 20},
+	[1][7] =   { .creg = 0x05c, .cshift =  3, },
+	[1][8] =   { .creg = 0x05c, .cshift =  6, },
+	[1][9] =   { .creg = 0x05c, .cshift =  9, },
+	[1][10] =  { .creg = 0x05c, .cshift = 13, },
+	[1][13] =  { .creg = 0x448, .cshift =  3, },
+	[1][14] =  { .creg = 0x448, .cshift = 16, },
+	[1][15] =  { .creg = 0x438, .cshift = 17, .sreg = 0x440, .sshift = 16},
+	[1][16] =  { .creg = 0x438, .cshift = 23, .sreg = 0x440, .sshift =  4},
+	[1][19] =  { .creg = 0x464, .cshift = 10, .sreg = 0x464, .sshift = 11},
+	[1][20] =  { .creg = 0x464, .cshift = 26, .sreg = 0x464, .sshift = 27},
+	[1][22] =  { .creg = 0x0bc, .cshift =  2, },
+	[2][1] =   { .creg = 0x020, .cshift = 18, },
+	[2][2] =   { .creg = 0x024, .cshift =  2, },
+	[2][3] =   { .creg = 0x024, .cshift = 18, },
+	[2][7] =   { .creg = 0x030, .cshift = 21, },
+	[2][11] =  { .creg = 0x02c, .cshift =  6, },
+	[2][13] =  { .creg = 0x448, .cshift =  4, },
+	[2][14] =  { .creg = 0x448, .cshift = 17, },
+	[3][0] =   { .creg = 0x020, .cshift =  3, },
+	[3][1] =   { .creg = 0x020, .cshift = 19, },
+	[3][2] =   { .creg = 0x024, .cshift =  3, .sreg = 0x030, .sshift = 25},
+	[3][3] =   { .creg = 0x024, .cshift = 19, },
+	[3][4] =   { .creg = 0x028, .cshift =  3, },
+	[3][5] =   { .creg = 0x028, .cshift = 18, },
+	[3][7] =   { .creg = 0x028, .cshift = 26, },
+	[3][9] =   { .creg = 0x02c, .cshift =  0, },
+	[3][13] =  { .creg = 0x448, .cshift =  5, },
+	[3][14] =  { .creg = 0x448, .cshift = 18, },
+	[3][15] =  { .creg = 0x438, .cshift = 19, },
+	[3][16] =  { .creg = 0x438, .cshift = 25, },
+	[3][19] =  { .creg = 0x464, .cshift = 12, },
+	[3][20] =  { .creg = 0x464, .cshift = 28, },
+	[3][21] =  { .creg = 0x05c, .cshift = 31, },
+	[4][0] =   { .creg = 0x020, .cshift =  4, },
+	[4][1] =   { .creg = 0x020, .cshift = 20, },
+	[4][2] =   { .creg = 0x024, .cshift =  4, .sreg = 0x030, .sshift = 26},
+	[4][3] =   { .creg = 0x024, .cshift = 20, },
+	[4][4] =   { .creg = 0x028, .cshift =  4, },
+	[4][6] =   { .creg = 0x028, .cshift = 23, },
+	[4][8] =   { .creg = 0x028, .cshift = 29, },
+	[4][10] =  { .creg = 0x02c, .cshift =  3, },
+	[4][13] =  { .creg = 0x448, .cshift =  6, },
+	[4][14] =  { .creg = 0x448, .cshift = 19, },
+	[4][15] =  { .creg = 0x438, .cshift = 20, },
+	[4][16] =  { .creg = 0x438, .cshift = 26, },
+	[4][19] =  { .creg = 0x464, .cshift = 13, },
+	[4][20] =  { .creg = 0x464, .cshift = 29, },
+	[4][22] =  { .creg = 0x0bc, .cshift =  3, },
+	[5][0] =   { .creg = 0x020, .cshift =  5, .sreg = 0x020, .sshift = 12},
+	[5][1] =   { .creg = 0x020, .cshift = 21, .sreg = 0x020, .sshift = 28},
+	[5][2] =   { .creg = 0x024, .cshift =  5, .sreg = 0x024, .sshift = 12},
+	[5][3] =   { .creg = 0x024, .cshift = 21, .sreg = 0x024, .sshift = 28},
+	[5][4] =   { .creg = 0x028, .cshift =  5, .sreg = 0x028, .sshift = 12},
+	[5][5] =   { .creg = 0x028, .cshift = 19, },
+	[5][7] =   { .creg = 0x028, .cshift = 27, },
+	[5][9] =   { .creg = 0x02c, .cshift =  1, },
+	[5][13] =  { .creg = 0x420, .cshift = 16, },
+	[5][14] =  { .creg = 0x420, .cshift = 20, },
+	[5][19] =  { .creg = 0x464, .cshift = 14, .sreg = 0x464, .sshift = 15},
+	[5][20] =  { .creg = 0x464, .cshift = 31, .sreg = 0x464, .sshift = 30},
+	[6][0] =   { .creg = 0x020, .cshift =  6, .sreg = 0x020, .sshift = 13},
+	[6][1] =   { .creg = 0x020, .cshift = 22, .sreg = 0x020, .sshift = 29},
+	[6][2] =   { .creg = 0x024, .cshift =  6, .sreg = 0x024, .sshift = 13},
+	[6][3] =   { .creg = 0x024, .cshift = 22, .sreg = 0x024, .sshift = 29},
+	[6][4] =   { .creg = 0x028, .cshift =  6, .sreg = 0x028, .sshift = 13},
+	[6][6] =   { .creg = 0x028, .cshift = 24, },
+	[6][8] =   { .creg = 0x028, .cshift = 30, },
+	[6][10] =  { .creg = 0x02c, .cshift =  4, },
+	[6][12] =  { .creg = 0x02c, .cshift =  9, },
+	[6][13] =  { .creg = 0x420, .cshift = 17, },
+	[6][14] =  { .creg = 0x420, .cshift = 21, },
+	[6][19] =  { .creg = 0x464, .cshift = 16, .sreg = 0x464, .sshift = 17},
+	[7][0] =   { .creg = 0x020, .cshift =  7, .sreg = 0x020, .sshift = 14},
+	[7][1] =   { .creg = 0x020, .cshift = 23, .sreg = 0x020, .sshift = 30},
+	[7][2] =   { .creg = 0x024, .cshift =  7, .sreg = 0x024, .sshift = 14},
+	[7][3] =   { .creg = 0x024, .cshift = 23, .sreg = 0x024, .sshift = 30},
+	[7][4] =   { .creg = 0x028, .cshift =  7, .sreg = 0x028, .sshift = 14},
+	[7][5] =   { .creg = 0x028, .cshift = 20, },
+	[7][7] =   { .creg = 0x028, .cshift = 28, },
+	[7][9] =   { .creg = 0x02c, .cshift =  2, },
+	[7][13] =  { .creg = 0x420, .cshift = 18, },
+	[7][14] =  { .creg = 0x420, .cshift = 22, },
+	[7][19] =  { .creg = 0x464, .cshift = 18, .sreg = 0x464, .sshift = 19},
+	[8][0] =   { .creg = 0x020, .cshift =  8, .sreg = 0x020, .sshift = 15},
+	[8][1] =   { .creg = 0x020, .cshift = 24, .sreg = 0x020, .sshift = 31},
+	[8][2] =   { .creg = 0x024, .cshift =  8, .sreg = 0x024, .sshift = 15},
+	[8][3] =   { .creg = 0x024, .cshift = 24, .sreg = 0x024, .sshift = 31},
+	[8][4] =   { .creg = 0x028, .cshift =  8, .sreg = 0x028, .sshift = 15},
+	[8][6] =   { .creg = 0x028, .cshift = 25, },
+	[8][8] =   { .creg = 0x028, .cshift = 31, },
+	[8][10] =  { .creg = 0x02c, .cshift =  5, },
+	[8][12] =  { .creg = 0x02c, .cshift = 10, },
+	[8][13] =  { .creg = 0x420, .cshift = 19, },
+	[8][14] =  { .creg = 0x420, .cshift = 23, },
+	[8][19] =  { .creg = 0x464, .cshift = 20, .sreg = 0x464, .sshift = 21},
+	[9][0] =   { .creg = 0x020, .cshift =  9, },
+	[9][1] =   { .creg = 0x020, .cshift = 25, },
+	[9][2] =   { .creg = 0x024, .cshift =  9, },
+	[9][3] =   { .creg = 0x024, .cshift = 25, },
+	[9][4] =   { .creg = 0x028, .cshift =  9, },
+	[9][5] =   { .creg = 0x028, .cshift = 21, },
+	[9][9] =   { .creg = 0x05c, .cshift = 10, },
+	[9][12] =  { .creg = 0x02c, .cshift = 11, },
+	[9][13] =  { .creg = 0x448, .cshift =  7, },
+	[9][14] =  { .creg = 0x448, .cshift = 20, },
+	[9][15] =  { .creg = 0x438, .cshift = 21, },
+	[9][16] =  { .creg = 0x438, .cshift = 27, },
+	[9][19] =  { .creg = 0x05c, .cshift = 22, },
+	[9][20] =  { .creg = 0x05c, .cshift =  6, },
+	[10][0] =  { .creg = 0x420, .cshift =  0, .sreg = 0x420, .sshift =  1},
+	[10][3] =  { .creg = 0x420, .cshift =  8, .sreg = 0x420, .sshift =  9},
+	[10][5] =  { .creg = 0x420, .cshift = 12, },
+	[10][7] =  { .creg = 0x420, .cshift = 14, },
+	[10][12] = { .creg = 0x448, .cshift =  0, },
+	[10][19] = { .creg = 0x448, .cshift = 28, },
+	[10][21] = { .creg = 0x448, .cshift =  0, },
+	[10][22] = { .creg = 0x44c, .cshift =  0, },
+	[11][1] =  { .creg = 0x420, .cshift =  2, .sreg = 0x420, .sshift =  3},
+	[11][4] =  { .creg = 0x420, .cshift = 10, .sreg = 0x420, .sshift = 11},
+	[11][6] =  { .creg = 0x420, .cshift = 13, },
+	[11][8] =  { .creg = 0x420, .cshift = 15, },
+	[11][12] = { .creg = 0x448, .cshift =  1, },
+	[11][20] = { .creg = 0x448, .cshift = 29, },
+	[11][21] = { .creg = 0x448, .cshift = 31, },
+	[11][22] = { .creg = 0x44c, .cshift =  1, },
+	[12][0] =  { .creg = 0x438, .cshift =  0, .sreg = 0x438, .sshift =  1},
+	[12][3] =  { .creg = 0x438, .cshift =  8, .sreg = 0x438, .sshift =  9},
+	[12][5] =  { .creg = 0x438, .cshift = 12, },
+	[12][7] =  { .creg = 0x438, .cshift = 14, },
+	[12][19] = { .creg = 0x444, .cshift =  2, },
+	[12][21] = { .creg = 0x444, .cshift =  4, },
+	[12][22] = { .creg = 0x444, .cshift =  6, },
+	[13][1] =  { .creg = 0x438, .cshift =  2, .sreg = 0x438, .sshift =  3},
+	[13][4] =  { .creg = 0x438, .cshift = 10, .sreg = 0x438, .sshift = 11},
+	[13][6] =  { .creg = 0x438, .cshift = 13, },
+	[13][8] =  { .creg = 0x438, .cshift = 15, },
+	[13][20] = { .creg = 0x444, .cshift =  3, },
+	[13][21] = { .creg = 0x444, .cshift =  4, },
+	[13][22] = { .creg = 0x444, .cshift =  7, },
+	[15][0] =  { .creg = 0x02c, .cshift = 13, .sreg = 0x02c, .sshift = 15},
+	[15][1] =  { .creg = 0x02c, .cshift = 18, .sreg = 0x02c, .sshift = 20},
+	[15][3] =  { .creg = 0x02c, .cshift = 28, .sreg = 0x02c, .sshift = 30},
+	[15][4] =  { .creg = 0x030, .cshift =  1, .sreg = 0x030, .sshift =  3},
+	[15][5] =  { .creg = 0x030, .cshift =  6, .sreg = 0x030, .sshift =  7},
+	[15][9] =  { .creg = 0x030, .cshift = 10, },
+	[15][13] = { .creg = 0x448, .cshift =  9, },
+	[15][14] = { .creg = 0x448, .cshift = 22, },
+	[15][15] = { .creg = 0x438, .cshift = 29, .sreg = 0x440, .sshift =  0},
+	[15][16] = { .creg = 0x440, .cshift =  2, },
+	[16][0] =  { .creg = 0x02c, .cshift = 14, .sreg = 0x02c, .sshift = 16},
+	[16][1] =  { .creg = 0x02c, .cshift = 19, .sreg = 0x02c, .sshift = 21},
+	[16][2] =  { .creg = 0x02c, .cshift = 24, .sreg = 0x02c, .sshift = 26},
+	[16][3] =  { .creg = 0x02c, .cshift = 29, .sreg = 0x02c, .sshift = 31},
+	[16][4] =  { .creg = 0x030, .cshift =  2, .sreg = 0x030, .sshift =  4},
+	[16][6] =  { .creg = 0x030, .cshift =  8, .sreg = 0x030, .sshift =  9},
+	[16][10] = { .creg = 0x030, .cshift = 11, },
+	[16][13] = { .creg = 0x448, .cshift = 10, },
+	[16][14] = { .creg = 0x448, .cshift = 23, },
+	[16][15] = { .creg = 0x438, .cshift = 30, },
+	[16][16] = { .creg = 0x440, .cshift =  3, .sreg = 0x440, .sshift =  5},
+	[17][0] =  { .creg = 0x460, .cshift =  0, },
+	[17][2] =  { .creg = 0x02c, .cshift = 27, .sreg = 0x0bc, .sshift = 30},
+	[17][3] =  { .creg = 0x05c, .cshift =  0, },
+	[17][5] =  { .creg = 0x460, .cshift = 22, },
+	[17][7] =  { .creg = 0x460, .cshift = 26, },
+	[17][9] =  { .creg = 0x460, .cshift = 30, },
+	[17][11] = { .creg = 0x464, .cshift =  2, },
+	[17][13] = { .creg = 0x448, .cshift = 11, },
+	[17][14] = { .creg = 0x448, .cshift = 24, },
+	[17][15] = { .creg = 0x440, .cshift = 21, },
+	[17][16] = { .creg = 0x440, .cshift = 30, },
+	[17][19] = { .creg = 0x464, .cshift = 22, },
+	[17][21] = { .creg = 0x0bc, .cshift =  0, },
+	[18][1] =  { .creg = 0x460, .cshift =  3, },
+	[18][2] =  { .creg = 0x02c, .cshift = 28, .sreg = 0x0bc, .sshift = 31},
+	[18][4] =  { .creg = 0x05c, .cshift =  1, },
+	[18][6] =  { .creg = 0x460, .cshift = 24, },
+	[18][8] =  { .creg = 0x460, .cshift = 28, },
+	[18][10] = { .creg = 0x464, .cshift =  0, },
+	[18][12] = { .creg = 0x464, .cshift =  4, },
+	[18][13] = { .creg = 0x448, .cshift = 12, },
+	[18][14] = { .creg = 0x448, .cshift = 25, },
+	[18][15] = { .creg = 0x440, .cshift = 22, },
+	[18][16] = { .creg = 0x440, .cshift = 31, },
+	[18][19] = { .creg = 0x464, .cshift = 23, },
+	[18][22] = { .creg = 0x0bc, .cshift =  4, },
+	[19][0] =  { .creg = 0x460, .cshift =  1, .sreg = 0x460, .sshift =  2},
+	[19][2] =  { .creg = 0x460, .cshift = 10, .sreg = 0x460, .sshift = 11},
+	[19][3] =  { .creg = 0x460, .cshift = 14, .sreg = 0x460, .sshift = 16},
+	[19][4] =  { .creg = 0x460, .cshift = 18, .sreg = 0x460, .sshift = 19},
+	[19][5] =  { .creg = 0x460, .cshift = 23, },
+	[19][7] =  { .creg = 0x460, .cshift = 27, },
+	[19][9] =  { .creg = 0x460, .cshift = 31, },
+	[19][11] = { .creg = 0x464, .cshift =  3, },
+	[19][13] = { .creg = 0x448, .cshift = 13, },
+	[19][14] = { .creg = 0x448, .cshift = 26, },
+	[19][15] = { .creg = 0x440, .cshift = 23, },
+	[19][16] = { .creg = 0x444, .cshift =  0, },
+	[19][19] = { .creg = 0x05c, .cshift = 24, },
+	[19][20] = { .creg = 0x05c, .cshift = 28, },
+	[19][21] = { .creg = 0x0bc, .cshift =  1, },
+	[20][1] =  { .creg = 0x460, .cshift =  4, .sreg = 0x460, .sshift =  5},
+	[20][2] =  { .creg = 0x460, .cshift = 12, .sreg = 0x460, .sshift = 13},
+	[20][3] =  { .creg = 0x460, .cshift = 16, .sreg = 0x460, .sshift = 17},
+	[20][4] =  { .creg = 0x460, .cshift = 20, .sreg = 0x460, .sshift = 21},
+	[20][6] =  { .creg = 0x460, .cshift = 25, },
+	[20][8] =  { .creg = 0x460, .cshift = 29, },
+	[20][10] = { .creg = 0x464, .cshift =  1, },
+	[20][12] = { .creg = 0x464, .cshift =  5, },
+	[20][13] = { .creg = 0x448, .cshift = 14, },
+	[20][14] = { .creg = 0x448, .cshift = 27, },
+	[20][15] = { .creg = 0x440, .cshift = 24, },
+	[20][16] = { .creg = 0x444, .cshift =  1, },
+	[20][19] = { .creg = 0x05c, .cshift = 25, },
+	[20][20] = { .creg = 0x05c, .cshift = 29, },
+	[20][22] = { .creg = 0x0bc, .cshift =  5, },
+};
+
+struct mtk_afe_hdmi_connection {
+	short reg;
+	char shift;
+};
+
+static const struct mtk_afe_hdmi_connection
+	hdmi_connections[MTK_AFE_NUM_HDMI_OUTPUT] = {
+	{ .reg = 0x390, .shift = 0 },
+	{ .reg = 0x390, .shift = 3 },
+	{ .reg = 0x390, .shift = 6 },
+	{ .reg = 0x390, .shift = 9 },
+
+	{ .reg = 0x390, .shift = 12 },
+	{ .reg = 0x390, .shift = 15 },
+	{ .reg = 0x390, .shift = 18 },
+	{ .reg = 0x390, .shift = 21 },
+
+	{ .reg = 0x390, .shift = 24 },
+	{ .reg = 0x390, .shift = 27 },
+	{ .reg = 0x398, .shift = 0 },
+	{ .reg = 0x398, .shift = 2 },
+};
+
+static int mtk_afe_interconn_hdmi(struct mtk_afe *afe_info, u32 in,
+				  u32 out)
+{
+	const struct mtk_afe_hdmi_connection *con;
+
+	if (in < MTK_AFE_HDMI_CONN_INPUT_BASE ||
+	    out < MTK_AFE_HDMI_CONN_OUTPUT_BASE)
+		return -EINVAL;
+
+	in -= MTK_AFE_HDMI_CONN_INPUT_BASE;
+	out -= MTK_AFE_HDMI_CONN_OUTPUT_BASE;
+
+	if (out >= MTK_AFE_NUM_HDMI_OUTPUT)
+		return -EINVAL;
+
+	if (in >= MTK_AFE_NUM_HDMI_INPUT)
+		return -EINVAL;
+
+	con = &hdmi_connections[out];
+
+	regmap_update_bits(afe_info->regmap, con->reg,
+			   0x7 << con->shift, in << con->shift);
+	return 0;
+}
+
+static const struct mtk_afe_connection *mtk_afe_get_connection(
+		struct mtk_afe *afe_info, u32 in, u32 out)
+{
+	if (in >= MTK_AFE_INTERCONN_NUM_INPUT ||
+	    out >= MTK_AFE_INTERCONN_NUM_OUTPUT) {
+		dev_err(afe_info->dev,
+			"out of bound mpConnectionTable[%d][%d]\n", in, out);
+		return NULL;
+	}
+
+	if (connections[in][out].creg == 0) {
+		dev_err(afe_info->dev,
+			"No connection between I%02d and O%02d\n", in, out);
+		return NULL;
+	}
+
+	return &connections[in][out];
+}
+
+/*
+ * mtk_afe_interconn_connect - Connect an input with an output
+ * @afe_info:	Context
+ * @in:		Input number, as in the SoC datasheet
+ * @out:	Output number, as in the SoC datasheet
+ * @rightshift:	Apply a rightshift on the input data
+ *
+ * This function connects an input of the audio interconnect with an
+ * output.
+ */
+int mtk_afe_interconn_connect(struct mtk_afe *afe_info, unsigned int in,
+			      unsigned int out, bool rightshift)
+{
+	const struct mtk_afe_connection *con;
+
+	if (in >= MTK_AFE_HDMI_CONN_INPUT_BASE ||
+	    out >= MTK_AFE_HDMI_CONN_OUTPUT_BASE)
+		return mtk_afe_interconn_hdmi(afe_info, in, out);
+
+	con = mtk_afe_get_connection(afe_info, in, out);
+	if (!con)
+		return -EINVAL;
+
+	regmap_update_bits(afe_info->regmap, con->creg,
+			   1 << con->cshift, 1 << con->cshift);
+
+	if (!con->sreg)
+		return 0;
+
+	if (rightshift)
+		regmap_update_bits(afe_info->regmap, con->sreg,
+				   1 << con->sshift, 1 << con->sshift);
+	else
+		regmap_update_bits(afe_info->regmap, con->sreg,
+				   1 << con->sshift, 0);
+
+	return 0;
+}
+
+/*
+ * mtk_afe_interconn_disconnect - Disconnect an input from an output
+ * @afe_info:	Context
+ * @in:		Input number, as in the SoC datasheet
+ * @out:	Output number, as in the SoC datasheet
+ *
+ * This function disconnects an input of the audio interconnect from an
+ * output.
+ */
+int mtk_afe_interconn_disconnect(struct mtk_afe *afe_info, unsigned int in,
+				 unsigned int out)
+{
+	const struct mtk_afe_connection *con;
+
+	con = mtk_afe_get_connection(afe_info, in, out);
+	if (!con)
+		return -EINVAL;
+
+	regmap_update_bits(afe_info->regmap, con->creg, 1 << con->cshift, 0);
+
+	return 0;
+}
diff --git a/sound/soc/mediatek/mtk-afe-connection.h b/sound/soc/mediatek/mtk-afe-connection.h
new file mode 100644
index 0000000..eac2555
--- /dev/null
+++ b/sound/soc/mediatek/mtk-afe-connection.h
@@ -0,0 +1,30 @@
+/*
+ * mtk_afe_connection.h  --  Mediatek AFE connection support
+ *
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Koro Chen <koro.chen at mediatek.com>
+ *             Sascha Hauer <s.hauer at pengutronix.de>
+ *             Hidalgo Huang <hidalgo.huang at mediatek.com>
+ *             Ir Lian <ir.lian at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_AFE_CONNECTION_H_
+#define _MTK_AFE_CONNECTION_H_
+
+struct mtk_afe;
+
+int mtk_afe_interconn_connect(struct mtk_afe *afe_info, unsigned int in,
+			      unsigned int out, bool rightshift);
+int mtk_afe_interconn_disconnect(struct mtk_afe *afe_info, unsigned int in,
+				 unsigned int out);
+
+#endif
-- 
1.8.1.1.dirty



More information about the Alsa-devel mailing list