#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 AFE_TDM_CON1 0x0548
#define AFE_TDM_CON2 0x054c
-#define AFE_BASE_END_OFFSET 8
#define AFE_IRQ_STATUS_BITS 0xff
/* AUDIO_TOP_CON0 (0x0000) */
AFE_DAC_CON0,
};
-struct mt8173_afe {
- /* address for ioremap audio hardware register */
- void __iomem *base_addr;
- struct device *dev;
- struct regmap *regmap;
- struct mt8173_afe_memif memif[MT8173_AFE_MEMIF_NUM];
+struct mt8173_afe_private {
struct clk *clocks[MT8173_CLK_NUM];
- unsigned int backup_regs[ARRAY_SIZE(mt8173_afe_backup_list)];
- bool suspended;
};
static const struct snd_pcm_hardware mt8173_afe_hardware = {
.fifo_size = 0,
};
-static snd_pcm_uframes_t mt8173_afe_pcm_pointer
- (struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
- struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
- unsigned int hw_ptr;
- int ret;
-
- ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur, &hw_ptr);
- if (ret || hw_ptr == 0) {
- dev_err(afe->dev, "%s hw_ptr err\n", __func__);
- hw_ptr = memif->phys_buf_addr;
- }
-
- return bytes_to_frames(substream->runtime,
- hw_ptr - memif->phys_buf_addr);
-}
-
-static const struct snd_pcm_ops mt8173_afe_pcm_ops = {
- .ioctl = snd_pcm_lib_ioctl,
- .pointer = mt8173_afe_pcm_pointer,
-};
-
-static int mt8173_afe_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- size_t size;
- struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
-
- size = mt8173_afe_hardware.buffer_bytes_max;
-
- return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- card->dev, size, size);
-}
-
-static void mt8173_afe_pcm_free(struct snd_pcm *pcm)
-{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static const struct snd_soc_platform_driver mt8173_afe_pcm_platform = {
- .ops = &mt8173_afe_pcm_ops,
- .pcm_new = mt8173_afe_pcm_new,
- .pcm_free = mt8173_afe_pcm_free,
-};
-
struct mt8173_afe_rate {
unsigned int rate;
unsigned int regvalue;
return -EINVAL;
}
-static int mt8173_afe_set_i2s(struct mt8173_afe *afe, unsigned int rate)
+static int mt8173_afe_set_i2s(struct mtk_base_afe *afe, unsigned int rate)
{
unsigned int val;
int fs = mt8173_afe_i2s_fs(rate);
return 0;
}
-static void mt8173_afe_set_i2s_enable(struct mt8173_afe *afe, bool enable)
+static void mt8173_afe_set_i2s_enable(struct mtk_base_afe *afe, bool enable)
{
unsigned int val;
regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable);
}
-static int mt8173_afe_dais_enable_clks(struct mt8173_afe *afe,
+static int mt8173_afe_dais_enable_clks(struct mtk_base_afe *afe,
struct clk *m_ck, struct clk *b_ck)
{
int ret;
return 0;
}
-static int mt8173_afe_dais_set_clks(struct mt8173_afe *afe,
+static int mt8173_afe_dais_set_clks(struct mtk_base_afe *afe,
struct clk *m_ck, unsigned int mck_rate,
struct clk *b_ck, unsigned int bck_rate)
{
return 0;
}
-static void mt8173_afe_dais_disable_clks(struct mt8173_afe *afe,
+static void mt8173_afe_dais_disable_clks(struct mtk_base_afe *afe,
struct clk *m_ck, struct clk *b_ck)
{
if (m_ck)
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
if (dai->active)
return 0;
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
if (dai->active)
return;
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime * const runtime = substream->runtime;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
int ret;
- mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S1_M],
+ mt8173_afe_dais_set_clks(afe, afe_priv->clocks[MT8173_CLK_I2S1_M],
runtime->rate * 256, NULL, 0);
- mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S2_M],
+ mt8173_afe_dais_set_clks(afe, afe_priv->clocks[MT8173_CLK_I2S2_M],
runtime->rate * 256, NULL, 0);
/* config I2S */
ret = mt8173_afe_set_i2s(afe, substream->runtime->rate);
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
if (dai->active)
return 0;
- mt8173_afe_dais_enable_clks(afe, afe->clocks[MT8173_CLK_I2S3_M],
- afe->clocks[MT8173_CLK_I2S3_B]);
+ mt8173_afe_dais_enable_clks(afe, afe_priv->clocks[MT8173_CLK_I2S3_M],
+ afe_priv->clocks[MT8173_CLK_I2S3_B]);
return 0;
}
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
if (dai->active)
return;
- mt8173_afe_dais_disable_clks(afe, afe->clocks[MT8173_CLK_I2S3_M],
- afe->clocks[MT8173_CLK_I2S3_B]);
+ mt8173_afe_dais_disable_clks(afe, afe_priv->clocks[MT8173_CLK_I2S3_M],
+ afe_priv->clocks[MT8173_CLK_I2S3_B]);
}
static int mt8173_afe_hdmi_prepare(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime * const runtime = substream->runtime;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
+
unsigned int val;
- mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S3_M],
+ mt8173_afe_dais_set_clks(afe, afe_priv->clocks[MT8173_CLK_I2S3_M],
runtime->rate * 128,
- afe->clocks[MT8173_CLK_I2S3_B],
+ afe_priv->clocks[MT8173_CLK_I2S3_B],
runtime->rate * runtime->channels * 32);
val = AFE_TDM_CON1_BCK_INV |
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
dev_info(afe->dev, "%s cmd=%d %s\n", __func__, cmd, dai->name);
/* set connections: O30~O37: L/R/LS/RS/C/LFE/CH7/CH8 */
regmap_write(afe->regmap, AFE_HDMI_CONN0,
- AFE_HDMI_CONN0_O30_I30 | AFE_HDMI_CONN0_O31_I31 |
- AFE_HDMI_CONN0_O32_I34 | AFE_HDMI_CONN0_O33_I35 |
- AFE_HDMI_CONN0_O34_I32 | AFE_HDMI_CONN0_O35_I33 |
- AFE_HDMI_CONN0_O36_I36 | AFE_HDMI_CONN0_O37_I37);
+ AFE_HDMI_CONN0_O30_I30 |
+ AFE_HDMI_CONN0_O31_I31 |
+ AFE_HDMI_CONN0_O32_I34 |
+ AFE_HDMI_CONN0_O33_I35 |
+ AFE_HDMI_CONN0_O34_I32 |
+ AFE_HDMI_CONN0_O35_I33 |
+ AFE_HDMI_CONN0_O36_I36 |
+ AFE_HDMI_CONN0_O37_I37);
/* enable Out control */
regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1);
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF,
AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF);
-
return 0;
default:
return -EINVAL;
}
}
-static int mt8173_afe_dais_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
- int ret;
-
- memif->substream = substream;
-
- snd_soc_set_runtime_hwparams(substream, &mt8173_afe_hardware);
-
- /*
- * Capture cannot use ping-pong buffer since hw_ptr at IRQ may be
- * smaller than period_size due to AFE's internal buffer.
- * This easily leads to overrun when avail_min is period_size.
- * One more period can hold the possible unread buffer.
- */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- ret = snd_pcm_hw_constraint_minmax(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS,
- 3,
- mt8173_afe_hardware.periods_max);
- if (ret < 0) {
- dev_err(afe->dev, "hw_constraint_minmax failed\n");
- return ret;
- }
- }
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
- return ret;
-}
-
-static void mt8173_afe_dais_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int mt8173_memif_fs(struct snd_pcm_substream *substream,
+ unsigned int rate)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
- struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
-
- memif->substream = NULL;
-}
-
-static int mt8173_afe_dais_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
- struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
- int msb_at_bit33 = 0;
- int ret;
-
- dev_dbg(afe->dev,
- "%s period = %u, rate= %u, channels=%u\n",
- __func__, params_period_size(params), params_rate(params),
- params_channels(params));
-
- ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
- if (ret < 0)
- return ret;
+ struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+ struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
+ int fs;
- msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0;
- memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
- memif->buffer_size = substream->runtime->dma_bytes;
-
- /* start */
- regmap_write(afe->regmap,
- memif->data->reg_ofs_base, memif->phys_buf_addr);
- /* end */
- regmap_write(afe->regmap,
- memif->data->reg_ofs_base + AFE_BASE_END_OFFSET,
- memif->phys_buf_addr + memif->buffer_size - 1);
-
- /* set MSB to 33-bit */
- regmap_update_bits(afe->regmap, AFE_MEMIF_MSB,
- 1 << memif->data->msb_shift,
- msb_at_bit33 << memif->data->msb_shift);
-
- /* set channel */
- if (memif->data->mono_shift >= 0) {
- unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
-
- regmap_update_bits(afe->regmap, AFE_DAC_CON1,
- 1 << memif->data->mono_shift,
- mono << memif->data->mono_shift);
- }
-
- /* set rate */
- if (memif->data->fs_shift < 0)
- return 0;
if (memif->data->id == MT8173_AFE_MEMIF_DAI ||
memif->data->id == MT8173_AFE_MEMIF_MOD_DAI) {
- unsigned int val;
-
- switch (params_rate(params)) {
+ switch (rate) {
case 8000:
- val = 0;
+ fs = 0;
break;
case 16000:
- val = 1;
+ fs = 1;
break;
case 32000:
- val = 2;
+ fs = 2;
break;
default:
return -EINVAL;
}
-
- if (memif->data->id == MT8173_AFE_MEMIF_DAI)
- regmap_update_bits(afe->regmap, AFE_DAC_CON0,
- 0x3 << memif->data->fs_shift,
- val << memif->data->fs_shift);
- else
- regmap_update_bits(afe->regmap, AFE_DAC_CON1,
- 0x3 << memif->data->fs_shift,
- val << memif->data->fs_shift);
-
} else {
- int fs = mt8173_afe_i2s_fs(params_rate(params));
-
- if (fs < 0)
- return -EINVAL;
-
- regmap_update_bits(afe->regmap, AFE_DAC_CON1,
- 0xf << memif->data->fs_shift,
- fs << memif->data->fs_shift);
+ fs = mt8173_afe_i2s_fs(rate);
}
-
- return 0;
+ return fs;
}
-static int mt8173_afe_dais_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int mt8173_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
{
- return snd_pcm_lib_free_pages(substream);
+ return mt8173_afe_i2s_fs(rate);
}
-static int mt8173_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime * const runtime = substream->runtime;
- struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
- struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
- unsigned int counter = runtime->period_size;
-
- dev_info(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- if (memif->data->enable_shift >= 0)
- regmap_update_bits(afe->regmap, AFE_DAC_CON0,
- 1 << memif->data->enable_shift,
- 1 << memif->data->enable_shift);
-
- /* set irq counter */
- regmap_update_bits(afe->regmap,
- memif->data->irq_reg_cnt,
- 0x3ffff << memif->data->irq_cnt_shift,
- counter << memif->data->irq_cnt_shift);
-
- /* set irq fs */
- if (memif->data->irq_fs_shift >= 0) {
- int fs = mt8173_afe_i2s_fs(runtime->rate);
-
- if (fs < 0)
- return -EINVAL;
-
- regmap_update_bits(afe->regmap,
- AFE_IRQ_MCU_CON,
- 0xf << memif->data->irq_fs_shift,
- fs << memif->data->irq_fs_shift);
- }
- /* enable interrupt */
- regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON,
- 1 << memif->data->irq_en_shift,
- 1 << memif->data->irq_en_shift);
-
- return 0;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- if (memif->data->enable_shift >= 0)
- regmap_update_bits(afe->regmap, AFE_DAC_CON0,
- 1 << memif->data->enable_shift, 0);
- /* disable interrupt */
- regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON,
- 1 << memif->data->irq_en_shift,
- 0 << memif->data->irq_en_shift);
- /* and clear pending IRQ */
- regmap_write(afe->regmap, AFE_IRQ_CLR,
- 1 << memif->data->irq_clr_shift);
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-/* FE DAIs */
-static const struct snd_soc_dai_ops mt8173_afe_dai_ops = {
- .startup = mt8173_afe_dais_startup,
- .shutdown = mt8173_afe_dais_shutdown,
- .hw_params = mt8173_afe_dais_hw_params,
- .hw_free = mt8173_afe_dais_hw_free,
- .trigger = mt8173_afe_dais_trigger,
-};
-
/* BE DAIs */
static const struct snd_soc_dai_ops mt8173_afe_i2s_ops = {
.startup = mt8173_afe_i2s_startup,
.shutdown = mt8173_afe_hdmi_shutdown,
.prepare = mt8173_afe_hdmi_prepare,
.trigger = mt8173_afe_hdmi_trigger,
-
};
-static int mt8173_afe_runtime_suspend(struct device *dev);
-static int mt8173_afe_runtime_resume(struct device *dev);
-
-static int mt8173_afe_dai_suspend(struct snd_soc_dai *dai)
-{
- struct mt8173_afe *afe = snd_soc_dai_get_drvdata(dai);
- int i;
-
- dev_dbg(afe->dev, "%s\n", __func__);
- if (pm_runtime_status_suspended(afe->dev) || afe->suspended)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(mt8173_afe_backup_list); i++)
- regmap_read(afe->regmap, mt8173_afe_backup_list[i],
- &afe->backup_regs[i]);
-
- afe->suspended = true;
- mt8173_afe_runtime_suspend(afe->dev);
- return 0;
-}
-
-static int mt8173_afe_dai_resume(struct snd_soc_dai *dai)
-{
- struct mt8173_afe *afe = snd_soc_dai_get_drvdata(dai);
- int i = 0;
-
- dev_dbg(afe->dev, "%s\n", __func__);
- if (pm_runtime_status_suspended(afe->dev) || !afe->suspended)
- return 0;
-
- mt8173_afe_runtime_resume(afe->dev);
-
- for (i = 0; i < ARRAY_SIZE(mt8173_afe_backup_list); i++)
- regmap_write(afe->regmap, mt8173_afe_backup_list[i],
- afe->backup_regs[i]);
-
- afe->suspended = false;
- return 0;
-}
-
static struct snd_soc_dai_driver mt8173_afe_pcm_dais[] = {
/* FE DAIs: memory intefaces to CPU */
{
.name = "DL1", /* downlink 1 */
.id = MT8173_AFE_MEMIF_DL1,
- .suspend = mt8173_afe_dai_suspend,
- .resume = mt8173_afe_dai_resume,
+ .suspend = mtk_afe_dai_suspend,
+ .resume = mtk_afe_dai_resume,
.playback = {
.stream_name = "DL1",
.channels_min = 1,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- .ops = &mt8173_afe_dai_ops,
+ .ops = &mtk_afe_fe_ops,
}, {
.name = "VUL", /* voice uplink */
.id = MT8173_AFE_MEMIF_VUL,
- .suspend = mt8173_afe_dai_suspend,
- .resume = mt8173_afe_dai_resume,
+ .suspend = mtk_afe_dai_suspend,
+ .resume = mtk_afe_dai_resume,
.capture = {
.stream_name = "VUL",
.channels_min = 1,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- .ops = &mt8173_afe_dai_ops,
+ .ops = &mtk_afe_fe_ops,
}, {
/* BE DAIs */
.name = "I2S",
{
.name = "HDMI",
.id = MT8173_AFE_MEMIF_HDMI,
- .suspend = mt8173_afe_dai_suspend,
- .resume = mt8173_afe_dai_resume,
+ .suspend = mtk_afe_dai_suspend,
+ .resume = mtk_afe_dai_resume,
.playback = {
.stream_name = "HDMI",
.channels_min = 2,
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- .ops = &mt8173_afe_dai_ops,
+ .ops = &mtk_afe_fe_ops,
}, {
/* BE DAIs */
.name = "HDMIO",
[MT8173_CLK_BCK1] = "bck1",
};
-static const struct mt8173_afe_memif_data memif_data[MT8173_AFE_MEMIF_NUM] = {
+static const struct mtk_base_memif_data memif_data[MT8173_AFE_MEMIF_NUM] = {
{
.name = "DL1",
.id = MT8173_AFE_MEMIF_DL1,
.reg_ofs_base = AFE_DL1_BASE,
.reg_ofs_cur = AFE_DL1_CUR,
+ .fs_reg = AFE_DAC_CON1,
.fs_shift = 0,
+ .fs_maskbit = 0xf,
+ .mono_reg = AFE_DAC_CON1,
.mono_shift = 21,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 1,
- .irq_reg_cnt = AFE_IRQ_CNT1,
- .irq_cnt_shift = 0,
- .irq_en_shift = 0,
- .irq_fs_shift = 4,
- .irq_clr_shift = 0,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 0,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "DL2",
.id = MT8173_AFE_MEMIF_DL2,
.reg_ofs_base = AFE_DL2_BASE,
.reg_ofs_cur = AFE_DL2_CUR,
+ .fs_reg = AFE_DAC_CON1,
.fs_shift = 4,
+ .fs_maskbit = 0xf,
+ .mono_reg = AFE_DAC_CON1,
.mono_shift = 22,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 2,
- .irq_reg_cnt = AFE_IRQ_CNT1,
- .irq_cnt_shift = 20,
- .irq_en_shift = 2,
- .irq_fs_shift = 16,
- .irq_clr_shift = 2,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 1,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "VUL",
.id = MT8173_AFE_MEMIF_VUL,
.reg_ofs_base = AFE_VUL_BASE,
.reg_ofs_cur = AFE_VUL_CUR,
+ .fs_reg = AFE_DAC_CON1,
.fs_shift = 16,
+ .fs_maskbit = 0xf,
+ .mono_reg = AFE_DAC_CON1,
.mono_shift = 27,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 3,
- .irq_reg_cnt = AFE_IRQ_CNT2,
- .irq_cnt_shift = 0,
- .irq_en_shift = 1,
- .irq_fs_shift = 8,
- .irq_clr_shift = 1,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 6,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "DAI",
.id = MT8173_AFE_MEMIF_DAI,
.reg_ofs_base = AFE_DAI_BASE,
.reg_ofs_cur = AFE_DAI_CUR,
+ .fs_reg = AFE_DAC_CON0,
.fs_shift = 24,
+ .fs_maskbit = 0x3,
+ .mono_reg = -1,
.mono_shift = -1,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 4,
- .irq_reg_cnt = AFE_IRQ_CNT2,
- .irq_cnt_shift = 20,
- .irq_en_shift = 3,
- .irq_fs_shift = 20,
- .irq_clr_shift = 3,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 5,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "AWB",
.id = MT8173_AFE_MEMIF_AWB,
.reg_ofs_base = AFE_AWB_BASE,
.reg_ofs_cur = AFE_AWB_CUR,
+ .fs_reg = AFE_DAC_CON1,
.fs_shift = 12,
+ .fs_maskbit = 0xf,
+ .mono_reg = AFE_DAC_CON1,
.mono_shift = 24,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 6,
- .irq_reg_cnt = AFE_IRQ_CNT7,
- .irq_cnt_shift = 0,
- .irq_en_shift = 14,
- .irq_fs_shift = 24,
- .irq_clr_shift = 6,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 3,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "MOD_DAI",
.id = MT8173_AFE_MEMIF_MOD_DAI,
.reg_ofs_base = AFE_MOD_PCM_BASE,
.reg_ofs_cur = AFE_MOD_PCM_CUR,
+ .fs_reg = AFE_DAC_CON1,
.fs_shift = 30,
+ .fs_maskbit = 0x3,
+ .mono_reg = AFE_DAC_CON1,
.mono_shift = 30,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = AFE_DAC_CON0,
.enable_shift = 7,
- .irq_reg_cnt = AFE_IRQ_CNT2,
- .irq_cnt_shift = 20,
- .irq_en_shift = 3,
- .irq_fs_shift = 20,
- .irq_clr_shift = 3,
+ .msb_reg = AFE_MEMIF_MSB,
.msb_shift = 4,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
}, {
.name = "HDMI",
.id = MT8173_AFE_MEMIF_HDMI,
.reg_ofs_base = AFE_HDMI_OUT_BASE,
.reg_ofs_cur = AFE_HDMI_OUT_CUR,
+ .fs_reg = -1,
.fs_shift = -1,
+ .fs_maskbit = -1,
+ .mono_reg = -1,
.mono_shift = -1,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .enable_reg = -1,
.enable_shift = -1,
- .irq_reg_cnt = AFE_IRQ_CNT5,
+ .msb_reg = AFE_MEMIF_MSB,
+ .msb_shift = 8,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ },
+};
+
+static const struct mtk_base_irq_data irq_data[MT8173_AFE_IRQ_NUM] = {
+ {
+ .id = MT8173_AFE_IRQ_DL1,
+ .irq_cnt_reg = AFE_IRQ_CNT1,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 0,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 4,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 0,
+ }, {
+ .id = MT8173_AFE_IRQ_DL2,
+ .irq_cnt_reg = AFE_IRQ_CNT1,
+ .irq_cnt_shift = 20,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 2,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 16,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 2,
+
+ }, {
+ .id = MT8173_AFE_IRQ_VUL,
+ .irq_cnt_reg = AFE_IRQ_CNT2,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 1,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 8,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 1,
+ }, {
+ .id = MT8173_AFE_IRQ_DAI,
+ .irq_cnt_reg = AFE_IRQ_CNT2,
+ .irq_cnt_shift = 20,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 3,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 20,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 3,
+ }, {
+ .id = MT8173_AFE_IRQ_AWB,
+ .irq_cnt_reg = AFE_IRQ_CNT7,
.irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 14,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 6,
+ }, {
+ .id = MT8173_AFE_IRQ_DAI,
+ .irq_cnt_reg = AFE_IRQ_CNT2,
+ .irq_cnt_shift = 20,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
+ .irq_en_shift = 3,
+ .irq_fs_reg = AFE_IRQ_MCU_CON,
+ .irq_fs_shift = 20,
+ .irq_fs_maskbit = 0xf,
+ .irq_clr_reg = AFE_IRQ_CLR,
+ .irq_clr_shift = 3,
+ }, {
+ .id = MT8173_AFE_IRQ_HDMI,
+ .irq_cnt_reg = AFE_IRQ_CNT5,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0x3ffff,
+ .irq_en_reg = AFE_IRQ_MCU_CON,
.irq_en_shift = 12,
+ .irq_fs_reg = -1,
.irq_fs_shift = -1,
+ .irq_fs_maskbit = -1,
+ .irq_clr_reg = AFE_IRQ_CLR,
.irq_clr_shift = 4,
- .msb_shift = 8,
},
};
static irqreturn_t mt8173_afe_irq_handler(int irq, void *dev_id)
{
- struct mt8173_afe *afe = dev_id;
+ struct mtk_base_afe *afe = dev_id;
unsigned int reg_value;
int i, ret;
}
for (i = 0; i < MT8173_AFE_MEMIF_NUM; i++) {
- struct mt8173_afe_memif *memif = &afe->memif[i];
+ struct mtk_base_afe_memif *memif = &afe->memif[i];
+ struct mtk_base_afe_irq *irq;
- if (!(reg_value & (1 << memif->data->irq_clr_shift)))
+ if (memif->irq_usage < 0)
+ continue;
+
+ irq = &afe->irqs[memif->irq_usage];
+
+ if (!(reg_value & (1 << irq->irq_data->irq_clr_shift)))
continue;
snd_pcm_period_elapsed(memif->substream);
err_irq:
/* clear irq */
- regmap_write(afe->regmap, AFE_IRQ_CLR, reg_value & AFE_IRQ_STATUS_BITS);
+ regmap_write(afe->regmap, AFE_IRQ_CLR,
+ reg_value & AFE_IRQ_STATUS_BITS);
return IRQ_HANDLED;
}
static int mt8173_afe_runtime_suspend(struct device *dev)
{
- struct mt8173_afe *afe = dev_get_drvdata(dev);
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
/* disable AFE */
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
/* disable AFE clk */
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S1_M]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S2_M]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK0]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK1]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
- clk_disable_unprepare(afe->clocks[MT8173_CLK_INFRASYS_AUD]);
+
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_I2S1_M]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_I2S2_M]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_BCK0]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_BCK1]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_INFRASYS_AUD]);
return 0;
}
static int mt8173_afe_runtime_resume(struct device *dev)
{
- struct mt8173_afe *afe = dev_get_drvdata(dev);
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
int ret;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_INFRASYS_AUD]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_INFRASYS_AUD]);
if (ret)
return ret;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
if (ret)
goto err_infra;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_TOP_PDN_AUD]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD]);
if (ret)
goto err_top_aud_bus;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_BCK0]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_BCK0]);
if (ret)
goto err_top_aud;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_BCK1]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_BCK1]);
if (ret)
goto err_bck0;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_I2S1_M]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_I2S1_M]);
if (ret)
goto err_i2s1_m;
- ret = clk_prepare_enable(afe->clocks[MT8173_CLK_I2S2_M]);
+ ret = clk_prepare_enable(afe_priv->clocks[MT8173_CLK_I2S2_M]);
if (ret)
goto err_i2s2_m;
/* enable AFE */
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
return 0;
+
err_i2s1_m:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S1_M]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_I2S1_M]);
err_i2s2_m:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S2_M]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_I2S2_M]);
err_bck0:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK0]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_BCK0]);
err_top_aud:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD]);
err_top_aud_bus:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]);
err_infra:
- clk_disable_unprepare(afe->clocks[MT8173_CLK_INFRASYS_AUD]);
+ clk_disable_unprepare(afe_priv->clocks[MT8173_CLK_INFRASYS_AUD]);
return ret;
}
-static int mt8173_afe_init_audio_clk(struct mt8173_afe *afe)
+static int mt8173_afe_init_audio_clk(struct mtk_base_afe *afe)
{
size_t i;
+ struct mt8173_afe_private *afe_priv = afe->platform_priv;
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
- afe->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
- if (IS_ERR(afe->clocks[i])) {
+ afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
+ if (IS_ERR(afe_priv->clocks[i])) {
dev_err(afe->dev, "%s devm_clk_get %s fail\n",
__func__, aud_clks[i]);
- return PTR_ERR(afe->clocks[i]);
+ return PTR_ERR(afe_priv->clocks[i]);
}
}
- clk_set_rate(afe->clocks[MT8173_CLK_BCK0], 22579200); /* 22M */
- clk_set_rate(afe->clocks[MT8173_CLK_BCK1], 24576000); /* 24M */
+ clk_set_rate(afe_priv->clocks[MT8173_CLK_BCK0], 22579200); /* 22M */
+ clk_set_rate(afe_priv->clocks[MT8173_CLK_BCK1], 24576000); /* 24M */
return 0;
}
{
int ret, i;
unsigned int irq_id;
- struct mt8173_afe *afe;
+ struct mtk_base_afe *afe;
+ struct mt8173_afe_private *afe_priv;
struct resource *res;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
if (!afe)
return -ENOMEM;
+ afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
+ GFP_KERNEL);
+ afe_priv = afe->platform_priv;
+ if (!afe_priv)
+ return -ENOMEM;
+
afe->dev = &pdev->dev;
irq_id = platform_get_irq(pdev, 0);
return ret;
}
- for (i = 0; i < MT8173_AFE_MEMIF_NUM; i++)
+ /* memif % irq initialize*/
+ afe->memif_size = MT8173_AFE_MEMIF_NUM;
+ afe->memif = devm_kcalloc(afe->dev, afe->memif_size,
+ sizeof(*afe->memif), GFP_KERNEL);
+ if (!afe->memif)
+ return -ENOMEM;
+
+ afe->irqs_size = MT8173_AFE_IRQ_NUM;
+ afe->irqs = devm_kcalloc(afe->dev, afe->irqs_size,
+ sizeof(*afe->irqs), GFP_KERNEL);
+ if (!afe->irqs)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->irqs_size; i++) {
afe->memif[i].data = &memif_data[i];
+ afe->irqs[i].irq_data = &irq_data[i];
+ afe->irqs[i].irq_occupyed = true;
+ afe->memif[i].irq_usage = i;
+ afe->memif[i].const_irq = 1;
+ }
+
+ afe->mtk_afe_hardware = &mt8173_afe_hardware;
+ afe->memif_fs = mt8173_memif_fs;
+ afe->irq_fs = mt8173_irq_fs;
platform_set_drvdata(pdev, afe);
goto err_pm_disable;
}
- ret = snd_soc_register_platform(&pdev->dev, &mt8173_afe_pcm_platform);
+ afe->reg_back_up_list = mt8173_afe_backup_list;
+ afe->reg_back_up_list_num = ARRAY_SIZE(mt8173_afe_backup_list);
+ afe->runtime_resume = mt8173_afe_runtime_resume;
+ afe->runtime_suspend = mt8173_afe_runtime_suspend;
+
+ ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform);
if (ret)
goto err_pm_disable;