aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-06-05 16:51:55 +0200
committerTakashi Iwai <tiwai@suse.de>2018-06-05 16:51:55 +0200
commitd4d5a1cd298e67cb68cca8dc7dd1ea3942cce3ff (patch)
tree282417771a28cb3d88fdd3246d9b778f1e3e8fd3 /sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
parentALSA: usb-audio: remove redundant check on err (diff)
parentMerge branch 'asoc-4.17' into asoc-4.18 merge window (diff)
downloadlinux-dev-d4d5a1cd298e67cb68cca8dc7dd1ea3942cce3ff.tar.xz
linux-dev-d4d5a1cd298e67cb68cca8dc7dd1ea3942cce3ff.zip
Merge tag 'asoc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.18 This is a very big update, mainly due to a huge set of new drivers some of which are individually very large. We also have a lot of fixes for the topology stuff, several of the users have stepped up and fixed some the serious issues there, and continued progress on the transition away from CODEC specific drivers to generic component drivers. - Many fixes for the topology code, including fixes for the half done v4 ABI compatibility from Guenter Roeck and other ABI fixes from Kirill Marinushkin. - Lots of cleanup for Intel platforms based on Realtek CODECs from Hans de Goode. - More followups on removing legacy CODEC things and transitioning to components from Morimoto-san. - Conversion of OMAP DMA to the new, more standard SDMA-PCM driver. - A series of fixes and updates to the rather elderly Cirrus Logic SoC drivers from Alexander Sverdlin. - Qualcomm DSP support from Srinivas Kandagatla. - New drivers for Analog SSM2305, Atmel I2S controllers, Mediatek MT6351, MT6797 and MT7622, Qualcomm DSPs, Realtek RT1305, RT1306 and RT5668 and TI TSCS454
Diffstat (limited to 'sound/soc/mediatek/mt2701/mt2701-afe-pcm.c')
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c349
1 files changed, 130 insertions, 219 deletions
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index 73cce33fa439..828d11c30c6a 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -1,18 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Mediatek ALSA SoC AFE platform driver for 2701
*
* Copyright (c) 2016 MediaTek Inc.
* Author: Garlic Tseng <garlic.tseng@mediatek.com>
- * Ir Lian <ir.lian@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.
+ * Ir Lian <ir.lian@mediatek.com>
+ * Ryder Lee <ryder.lee@mediatek.com>
*/
#include <linux/delay.h>
@@ -20,6 +13,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include "mt2701-afe-common.h"
@@ -36,7 +30,7 @@ static const struct snd_pcm_hardware mt2701_afe_hardware = {
.period_bytes_max = 1024 * 256,
.periods_min = 4,
.periods_max = 1024,
- .buffer_bytes_max = 1024 * 1024 * 16,
+ .buffer_bytes_max = 1024 * 1024,
.fifo_size = 0,
};
@@ -68,9 +62,10 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = {
static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num)
{
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
int val = num - MT2701_IO_I2S;
- if (val < 0 || val >= MT2701_I2S_NUM) {
+ if (val < 0 || val >= afe_priv->soc->i2s_num) {
dev_err(afe->dev, "%s, num not available, num %d, val %d\n",
__func__, num, val);
return -EINVAL;
@@ -92,44 +87,26 @@ static int mt2701_afe_i2s_fs(unsigned int sample_rate)
static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
+ bool mode = afe_priv->soc->has_one_heart_mode;
if (i2s_num < 0)
return i2s_num;
- return mt2701_afe_enable_mclk(afe, i2s_num);
+ return mt2701_afe_enable_mclk(afe, mode ? 1 : i2s_num);
}
-static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai,
- int i2s_num,
- int dir_invert)
+static int mt2701_afe_i2s_path_disable(struct mtk_base_afe *afe,
+ struct mt2701_i2s_path *i2s_path,
+ int stream_dir)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
- struct mt2701_afe_private *afe_priv = afe->platform_priv;
- struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
- const struct mt2701_i2s_data *i2s_data;
- int stream_dir = substream->stream;
-
- if (dir_invert) {
- if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
- stream_dir = SNDRV_PCM_STREAM_CAPTURE;
- else
- stream_dir = SNDRV_PCM_STREAM_PLAYBACK;
- }
- i2s_data = i2s_path->i2s_data[stream_dir];
+ const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir];
- i2s_path->on[stream_dir]--;
- if (i2s_path->on[stream_dir] < 0) {
- dev_warn(afe->dev, "i2s_path->on: %d, dir: %d\n",
- i2s_path->on[stream_dir], stream_dir);
+ if (--i2s_path->on[stream_dir] < 0)
i2s_path->on[stream_dir] = 0;
- }
+
if (i2s_path->on[stream_dir])
return 0;
@@ -137,7 +114,7 @@ static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,
ASYS_I2S_CON_I2S_EN, 0);
- mt2701_afe_disable_i2s(afe, i2s_num, stream_dir);
+ mt2701_afe_disable_i2s(afe, i2s_path, stream_dir);
return 0;
}
@@ -145,12 +122,11 @@ static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt2701_afe_private *afe_priv = afe->platform_priv;
int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
struct mt2701_i2s_path *i2s_path;
+ bool mode = afe_priv->soc->has_one_heart_mode;
if (i2s_num < 0)
return;
@@ -160,50 +136,33 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
if (i2s_path->occupied[substream->stream])
i2s_path->occupied[substream->stream] = 0;
else
- goto I2S_UNSTART;
+ goto exit;
- mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 0);
+ mt2701_afe_i2s_path_disable(afe, i2s_path, substream->stream);
/* need to disable i2s-out path when disable i2s-in */
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 1);
+ mt2701_afe_i2s_path_disable(afe, i2s_path, !substream->stream);
-I2S_UNSTART:
+exit:
/* disable mclk */
- mt2701_afe_disable_mclk(afe, i2s_num);
+ mt2701_afe_disable_mclk(afe, mode ? 1 : i2s_num);
}
-static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai,
- int i2s_num,
- int dir_invert)
+static int mt2701_i2s_path_enable(struct mtk_base_afe *afe,
+ struct mt2701_i2s_path *i2s_path,
+ int stream_dir, int rate)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir];
struct mt2701_afe_private *afe_priv = afe->platform_priv;
- struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
- const struct mt2701_i2s_data *i2s_data;
- struct snd_pcm_runtime * const runtime = substream->runtime;
int reg, fs, w_len = 1; /* now we support bck 64bits only */
- int stream_dir = substream->stream;
- unsigned int mask = 0, val = 0;
-
- if (dir_invert) {
- if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
- stream_dir = SNDRV_PCM_STREAM_CAPTURE;
- else
- stream_dir = SNDRV_PCM_STREAM_PLAYBACK;
- }
- i2s_data = i2s_path->i2s_data[stream_dir];
+ unsigned int mask, val;
/* no need to enable if already done */
- i2s_path->on[stream_dir]++;
-
- if (i2s_path->on[stream_dir] != 1)
+ if (++i2s_path->on[stream_dir] != 1)
return 0;
- fs = mt2701_afe_i2s_fs(runtime->rate);
+ fs = mt2701_afe_i2s_fs(rate);
mask = ASYS_I2S_CON_FS |
ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */
@@ -217,22 +176,24 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) {
mask |= ASYS_I2S_IN_PHASE_FIX;
val |= ASYS_I2S_IN_PHASE_FIX;
+ reg = ASMI_TIMING_CON1;
+ } else {
+ if (afe_priv->soc->has_one_heart_mode) {
+ mask |= ASYS_I2S_CON_ONE_HEART_MODE;
+ val |= ASYS_I2S_CON_ONE_HEART_MODE;
+ }
+ reg = ASMO_TIMING_CON1;
}
regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val);
- if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
- reg = ASMO_TIMING_CON1;
- else
- reg = ASMI_TIMING_CON1;
-
regmap_update_bits(afe->regmap, reg,
i2s_data->i2s_asrc_fs_mask
<< i2s_data->i2s_asrc_fs_shift,
fs << i2s_data->i2s_asrc_fs_shift);
/* enable i2s */
- mt2701_afe_enable_i2s(afe, i2s_num, stream_dir);
+ mt2701_afe_enable_i2s(afe, i2s_path, stream_dir);
/* reset i2s hw status before enable */
regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,
@@ -249,45 +210,33 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- int clk_domain;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt2701_afe_private *afe_priv = afe->platform_priv;
- int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
+ int ret, i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
struct mt2701_i2s_path *i2s_path;
- int mclk_rate;
+ bool mode = afe_priv->soc->has_one_heart_mode;
if (i2s_num < 0)
return i2s_num;
i2s_path = &afe_priv->i2s_path[i2s_num];
- mclk_rate = i2s_path->mclk_rate;
if (i2s_path->occupied[substream->stream])
return -EBUSY;
+
+ ret = mt2701_mclk_configuration(afe, mode ? 1 : i2s_num);
+ if (ret)
+ return ret;
+
i2s_path->occupied[substream->stream] = 1;
- if (MT2701_PLL_DOMAIN_0_RATE % mclk_rate == 0) {
- clk_domain = 0;
- } else if (MT2701_PLL_DOMAIN_1_RATE % mclk_rate == 0) {
- clk_domain = 1;
- } else {
- dev_err(dai->dev, "%s() bad mclk rate %d\n",
- __func__, mclk_rate);
- return -EINVAL;
- }
- mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate);
+ /* need to enable i2s-out path when enable i2s-in */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ mt2701_i2s_path_enable(afe, i2s_path, !substream->stream,
+ substream->runtime->rate);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
- } else {
- /* need to enable i2s-out path when enable i2s-in */
- /* prepare for another direction "out" */
- mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 1);
- /* prepare for "in" */
- mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
- }
+ mt2701_i2s_path_enable(afe, i2s_path, substream->stream,
+ substream->runtime->rate);
return 0;
}
@@ -295,30 +244,29 @@ static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream,
static int mt2701_afe_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt2701_afe_private *afe_priv = afe->platform_priv;
int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
+ bool mode = afe_priv->soc->has_one_heart_mode;
if (i2s_num < 0)
return i2s_num;
/* mclk */
if (dir == SND_SOC_CLOCK_IN) {
- dev_warn(dai->dev,
- "%s() warning: mt2701 doesn't support mclk input\n",
- __func__);
+ dev_warn(dai->dev, "The SoCs doesn't support mclk input\n");
return -EINVAL;
}
- afe_priv->i2s_path[i2s_num].mclk_rate = freq;
+
+ afe_priv->i2s_path[mode ? 1 : i2s_num].mclk_rate = freq;
+
return 0;
}
static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt2701_afe_private *afe_priv = afe->platform_priv;
int ret;
@@ -327,6 +275,7 @@ static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,
return ret;
afe_priv->mrg_enable[substream->stream] = 1;
+
return 0;
}
@@ -334,17 +283,14 @@ static int mt2701_btmrg_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 snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int stream_fs;
u32 val, msk;
stream_fs = params_rate(params);
- if ((stream_fs != 8000) && (stream_fs != 16000)) {
- dev_err(afe->dev, "%s() btmgr not support this stream_fs %d\n",
- __func__, stream_fs);
+ if (stream_fs != 8000 && stream_fs != 16000) {
+ dev_err(afe->dev, "unsupported rate %d\n", stream_fs);
return -EINVAL;
}
@@ -378,9 +324,7 @@ static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream,
static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mt2701_afe_private *afe_priv = afe->platform_priv;
/* if the other direction stream is not occupied */
@@ -393,28 +337,26 @@ static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,
AFE_MRGIF_CON_MRG_I2S_EN, 0);
mt2701_disable_btmrg_clk(afe);
}
+
afe_priv->mrg_enable[substream->stream] = 0;
}
static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
- int stream_dir = substream->stream;
- int memif_num = rtd->cpu_dai->id;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mtk_base_afe_memif *memif_tmp;
+ int stream_dir = substream->stream;
/* can't run single DL & DLM at the same time */
if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) {
memif_tmp = &afe->memif[MT2701_MEMIF_DLM];
if (memif_tmp->substream) {
- dev_warn(afe->dev, "%s memif is not available, stream_dir %d, memif_num %d\n",
- __func__, stream_dir, memif_num);
+ dev_warn(afe->dev, "memif is not available");
return -EBUSY;
}
}
+
return mtk_afe_fe_startup(substream, dai);
}
@@ -422,27 +364,23 @@ static int mt2701_simple_fe_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 snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int stream_dir = substream->stream;
/* single DL use PAIR_INTERLEAVE */
- if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
regmap_update_bits(afe->regmap,
AFE_MEMIF_PBUF_SIZE,
AFE_MEMIF_PBUF_SIZE_DLM_MASK,
AFE_MEMIF_PBUF_SIZE_PAIR_INTERLEAVE);
- }
+
return mtk_afe_fe_hw_params(substream, params, dai);
}
static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mtk_base_afe_memif *memif_tmp;
const struct mtk_base_memif_data *memif_data;
int i;
@@ -468,9 +406,7 @@ static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream,
static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
const struct mtk_base_memif_data *memif_data;
int i;
@@ -481,6 +417,7 @@ static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream,
1 << memif_data->agent_disable_shift,
1 << memif_data->agent_disable_shift);
}
+
return mtk_afe_fe_shutdown(substream, dai);
}
@@ -488,9 +425,7 @@ static int mt2701_dlm_fe_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 snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
int channels = params_channels(params);
regmap_update_bits(afe->regmap,
@@ -512,9 +447,7 @@ static int mt2701_dlm_fe_hw_params(struct snd_pcm_substream *substream,
static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
- struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mtk_base_afe_memif *memif_tmp = &afe->memif[MT2701_MEMIF_DL1];
switch (cmd) {
@@ -547,6 +480,7 @@ static int mt2701_memif_fs(struct snd_pcm_substream *substream,
fs = mt2701_afe_i2s_fs(rate);
else
fs = (rate == 16000 ? 1 : 0);
+
return fs;
}
@@ -1024,7 +958,17 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
{ "O31", "I35 Switch", "I35" },
};
+static int mt2701_afe_pcm_probe(struct snd_soc_component *component)
+{
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+
+ snd_soc_component_init_regmap(component, afe->regmap);
+
+ return 0;
+}
+
static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = {
+ .probe = mt2701_afe_pcm_probe,
.name = "mt2701-afe-pcm-dai",
.dapm_widgets = mt2701_afe_pcm_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt2701_afe_pcm_widgets),
@@ -1324,63 +1268,24 @@ static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = {
}
};
-static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = {
+static const struct mt2701_i2s_data mt2701_i2s_data[][2] = {
{
- {
- .i2s_ctrl_reg = ASYS_I2SO1_CON,
- .i2s_asrc_fs_shift = 0,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
- {
- .i2s_ctrl_reg = ASYS_I2SIN1_CON,
- .i2s_asrc_fs_shift = 0,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
+ { ASYS_I2SO1_CON, 0, 0x1f },
+ { ASYS_I2SIN1_CON, 0, 0x1f },
},
{
- {
- .i2s_ctrl_reg = ASYS_I2SO2_CON,
- .i2s_asrc_fs_shift = 5,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
- {
- .i2s_ctrl_reg = ASYS_I2SIN2_CON,
- .i2s_asrc_fs_shift = 5,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
+ { ASYS_I2SO2_CON, 5, 0x1f },
+ { ASYS_I2SIN2_CON, 5, 0x1f },
},
{
- {
- .i2s_ctrl_reg = ASYS_I2SO3_CON,
- .i2s_asrc_fs_shift = 10,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
- {
- .i2s_ctrl_reg = ASYS_I2SIN3_CON,
- .i2s_asrc_fs_shift = 10,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
+ { ASYS_I2SO3_CON, 10, 0x1f },
+ { ASYS_I2SIN3_CON, 10, 0x1f },
},
{
- {
- .i2s_ctrl_reg = ASYS_I2SO4_CON,
- .i2s_asrc_fs_shift = 15,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
- {
- .i2s_ctrl_reg = ASYS_I2SIN4_CON,
- .i2s_asrc_fs_shift = 15,
- .i2s_asrc_fs_mask = 0x1f,
-
- },
+ { ASYS_I2SO4_CON, 15, 0x1f },
+ { ASYS_I2SIN4_CON, 15, 0x1f },
},
+ /* TODO - extend control registers supported by newer SoCs */
};
static irqreturn_t mt2701_asys_isr(int irq_id, void *dev)
@@ -1398,10 +1303,12 @@ static irqreturn_t mt2701_asys_isr(int irq_id, void *dev)
memif = &afe->memif[id];
if (memif->irq_usage < 0)
continue;
+
irq = &afe->irqs[memif->irq_usage];
- if (status & 1 << (irq->irq_data->irq_clr_shift))
+ if (status & 1 << irq->irq_data->irq_clr_shift)
snd_pcm_period_elapsed(memif->substream);
}
+
return IRQ_HANDLED;
}
@@ -1419,22 +1326,6 @@ static int mt2701_afe_runtime_resume(struct device *dev)
return mt2701_afe_enable_clock(afe);
}
-static int mt2701_afe_add_component(struct mtk_base_afe *afe)
-{
- struct snd_soc_component *component;
-
- component = kzalloc(sizeof(*component), GFP_KERNEL);
- if (!component)
- return -ENOMEM;
-
- component->regmap = afe->regmap;
-
- return snd_soc_add_component(afe->dev, component,
- &mt2701_afe_pcm_dai_component,
- mt2701_afe_pcm_dais,
- ARRAY_SIZE(mt2701_afe_pcm_dais));
-}
-
static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
@@ -1452,9 +1343,16 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
return -ENOMEM;
afe_priv = afe->platform_priv;
+ afe_priv->soc = of_device_get_match_data(&pdev->dev);
afe->dev = &pdev->dev;
dev = afe->dev;
+ afe_priv->i2s_path = devm_kzalloc(dev, afe_priv->soc->i2s_num *
+ sizeof(struct mt2701_i2s_path),
+ GFP_KERNEL);
+ if (!afe_priv->i2s_path)
+ return -ENOMEM;
+
irq_id = platform_get_irq_byname(pdev, "asys");
if (irq_id < 0) {
dev_err(dev, "unable to get ASYS IRQ\n");
@@ -1499,11 +1397,11 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
afe->irqs[i].irq_data = &irq_data[i];
/* I2S initialize */
- for (i = 0; i < MT2701_I2S_NUM; i++) {
- afe_priv->i2s_path[i].i2s_data[I2S_OUT]
- = &mt2701_i2s_data[i][I2S_OUT];
- afe_priv->i2s_path[i].i2s_data[I2S_IN]
- = &mt2701_i2s_data[i][I2S_IN];
+ for (i = 0; i < afe_priv->soc->i2s_num; i++) {
+ afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_PLAYBACK] =
+ &mt2701_i2s_data[i][SNDRV_PCM_STREAM_PLAYBACK];
+ afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_CAPTURE] =
+ &mt2701_i2s_data[i][SNDRV_PCM_STREAM_CAPTURE];
}
afe->mtk_afe_hardware = &mt2701_afe_hardware;
@@ -1538,7 +1436,10 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
goto err_platform;
}
- ret = mt2701_afe_add_component(afe);
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &mt2701_afe_pcm_dai_component,
+ mt2701_afe_pcm_dais,
+ ARRAY_SIZE(mt2701_afe_pcm_dais));
if (ret) {
dev_warn(dev, "err_dai_component\n");
goto err_platform;
@@ -1564,8 +1465,18 @@ static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev)
return 0;
}
+static const struct mt2701_soc_variants mt2701_soc_v1 = {
+ .i2s_num = 4,
+};
+
+static const struct mt2701_soc_variants mt2701_soc_v2 = {
+ .has_one_heart_mode = true,
+ .i2s_num = 4,
+};
+
static const struct of_device_id mt2701_afe_pcm_dt_match[] = {
- { .compatible = "mediatek,mt2701-audio", },
+ { .compatible = "mediatek,mt2701-audio", .data = &mt2701_soc_v1 },
+ { .compatible = "mediatek,mt7622-audio", .data = &mt2701_soc_v2 },
{},
};
MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match);