// SPDX-License-Identifier: GPL-2.0
/*
* Mediatek 8173 ALSA SoC AFE platform driver
*
* Copyright (c) 2015 MediaTek Inc.
* Author: Koro Chen <koro.chen@mediatek.com>
* Sascha Hauer <s.hauer@pengutronix.de>
* Hidalgo Huang <hidalgo.huang@mediatek.com>
* Ir Lian <ir.lian@mediatek.com>
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include "mt8173-afe-common.h"
#include "../common/mtk-base-afe.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-afe-fe-dai.h"
/*****************************************************************************
* R E G I S T E R D E F I N I T I O N
*****************************************************************************/
#define AUDIO_TOP_CON0 0x0000
#define AUDIO_TOP_CON1 0x0004
#define AFE_DAC_CON0 0x0010
#define AFE_DAC_CON1 0x0014
#define AFE_I2S_CON1 0x0034
#define AFE_I2S_CON2 0x0038
#define AFE_CONN_24BIT 0x006c
#define AFE_MEMIF_MSB 0x00cc
#define AFE_CONN1 0x0024
#define AFE_CONN2 0x0028
#define AFE_CONN3 0x002c
#define AFE_CONN7 0x0460
#define AFE_CONN8 0x0464
#define AFE_HDMI_CONN0 0x0390
/* Memory interface */
#define AFE_DL1_BASE 0x0040
#define AFE_DL1_CUR 0x0044
#define AFE_DL1_END 0x0048
#define AFE_DL2_BASE 0x0050
#define AFE_DL2_CUR 0x0054
#define AFE_AWB_BASE 0x0070
#define AFE_AWB_CUR 0x007c
#define AFE_VUL_BASE 0x0080
#define AFE_VUL_CUR 0x008c
#define AFE_VUL_END 0x0088
#define AFE_DAI_BASE 0x0090
#define AFE_DAI_CUR 0x009c
#define AFE_MOD_PCM_BASE 0x0330
#define AFE_MOD_PCM_CUR 0x033c
#define AFE_HDMI_OUT_BASE 0x0374
#define AFE_HDMI_OUT_CUR 0x0378
#define AFE_HDMI_OUT_END 0x037c
#define AFE_ADDA_TOP_CON0 0x0120
#define AFE_ADDA2_TOP_CON0 0x0600
#define AFE_HDMI_OUT_CON0 0x0370
#define AFE_IRQ_MCU_CON 0x03a0
#define AFE_IRQ_STATUS 0x03a4
#define AFE_IRQ_CLR 0x03a8
#define AFE_IRQ_CNT1 0x03ac
#define AFE_IRQ_CNT2 0x03b0
#define AFE_IRQ_MCU_EN 0x03b4
#define AFE_IRQ_CNT5 0x03bc
#define AFE_IRQ_CNT7 0x03dc
#define AFE_TDM_CON1 0x0548
#define AFE_TDM_CON2 0x054c
#define AFE_IRQ_STATUS_BITS 0xff
/* AUDIO_TOP_CON0 (0x0000) */
#define AUD_TCON0_PDN_SPDF (0x1 << 21)
#define AUD_TCON0_PDN_HDMI (0x1 << 20)
#define AUD_TCON0_PDN_24M (0x1 << 9)
#define AUD_TCON0_PDN_22M (0x1 << 8)
#define AUD_TCON0_PDN_AFE (0x1 << 2)
/* AFE_I2S_CON1 (0x0034) */
#define AFE_I2S_CON1_LOW_JITTER_CLK (0x1 << 12)
#define AFE_I2S_CON1_RATE(x) (((x) & 0xf) << 8)
#define AFE_I2S_CON1_FORMAT_I2S (0x1 << 3)
#define AFE_I2S_CON1_EN (0x1 << 0)
/* AFE_I2S_CON2 (0x0038) */
#define AFE_I2S_CON2_LOW_JITTER_CLK (0x1 << 12)
#define AFE_I2S_CON2_RATE(x) (((x) & 0xf) << 8)
#define AFE_I2S_CON2_FORMAT_I2S (0x1 << 3)
#define AFE_I2S_CON2_EN (0x1 << 0)
/* AFE_CONN_24BIT (0x006c) */
#define AFE_CONN_24BIT_O04 (0x1 << 4)
#define AFE_CONN_24BIT_O03 (0x1 << 3)
/* AFE_HDMI_CONN0 (0x0390) */
#define AFE_HDMI_CONN0_O37_I37 (0x7 << 21)
#define AFE_HDMI_CONN0_O36_I36 (0x6 << 18)
#define AFE_HDMI_CONN0_O35_I33 (0x3 << 15)
#define AFE_HDMI_CONN0_O34_I32 (0x2 << 12)
#define AFE_HDMI_CONN0_O33_I35 (0x5 << 9)
#define AFE_HDMI_CONN0_O32_I34 (0x4 << 6)
#define AFE_HDMI_CONN0_O31_I31 (0x1 << 3)
#define AFE_HDMI_CONN0_O30_I30 (0x0 << 0)
/* AFE_TDM_CON1 (0x0548) */
#define AFE_TDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 24)
#define AFE_TDM_CON1_32_BCK_CYCLES (0x2 << 12)
#define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8)
#define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4)
#define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3)
#define AFE_TDM_CON1_LRCK_INV (0x1 << 2)
#define AFE_TDM_CON1_BCK_INV (0x1 << 1)
#define AFE_TDM_CON1_EN (0x1 << 0)
enum afe_tdm_ch_start {
AFE_TDM_CH_START_O30_O31 = 0,
AFE_TDM_CH_START_O32_O33,
AFE_TDM_CH_START_O34_O35,
AFE_TDM_CH_START_O36_O37,
AFE_TDM_CH_ZERO,
};
static const unsigned int mt8173_afe_backup_list[] = {
AUDIO_TOP_CON0,
AFE_CONN1,
AFE_CONN2,
AFE_CONN7,
AFE_CONN8,
AFE_DAC_CON1,
AFE_DL1_BASE,
AFE_DL1_END,
AFE_VUL_BASE,
AFE_VUL_END,
AFE_HDMI_OUT_BASE,
AFE_HDMI_OUT_END,
AFE_HDMI_CONN0,
AFE_DAC_CON0,
};
struct mt8173_afe_private {
struct clk *clocks[MT8173_CLK_NUM];
};
static const struct snd_pcm_hardware mt8173_afe_hardware = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.buffer_bytes_max = 256 * 1024,
.period_bytes_min = 512,
.period_bytes_max = 128 * 1024,
.periods_min = 2,
.periods_max = 256,
.fifo_size = 0,
};
struct mt8173_afe_rate {
unsigned int rate;
unsigned int regvalue;
};
static const struct mt8173_afe_rate mt8173_afe_i2s_rates[] = {
{ .rate = 8000, .regvalue = 0 },
{ .rate = 11025, .regvalue = 1 },
{ .rate = 12000, .regvalue