mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-06 03:45:24 -04:00
Merge tag 'LA.UM.9.14.r1-24700-LAHAINA.QSSI15.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/audio-kernel into android13-5.4-lahaina
"LA.UM.9.14.r1-24700-LAHAINA.QSSI15.0" * tag 'LA.UM.9.14.r1-24700-LAHAINA.QSSI15.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/audio-kernel: Asoc: dsp: Fix to check the list is empty or not dsp: q6lsm: Check size of payload before access Fix for OOB access issue dsp: q6asm increase the locking range ASoC: msm-pcm-q6-v2: Add size check ASoC : Add proper copyright marking. dsp: afe: Add check for num_spks soc: pinctrl-lpi: remove pm ops asoc: msm-compress: Fix compress_pause failure on gki Audio legacy: Integer overflow in msm_lsm_ioctl_compat during audio playback usecase. size = sizeof(p_info_32) + p_info_32.param_size; This overflow issue may result heap overflow during copying the data: memcpy(param_info_rsp, &p_info_32, sizeof(p_info_32)); ASoC : Add macro to differentiate auto code ASoC: msm: get CoPP index based on FE id asoc: codecs: add array bound check soc: Address SWR rate mismatch interrupt asoc : add configuration about SLIMBUS_7_TX asoc: lahaina: add support for aud_ref_clk_sel mux dsp: afe: add support for aud_ref_clk_sel mux ASoC: dsp: Release lock before return ASoC: wcd937x: Add flag to decide RX_MUTE for HPHL and EAR ASoC: bolero: Add check for CMPDR switch ASoC : add support of HDMI controller for rb3gen2 platform asoc: lahaina: fractional sample rate support for TDM asoc: support for fractional sample rate over tdm Revert "asoc: msm-compress : Fix for CTS-on-gsi with gki" audio-kernel:swr: Add dynamic SWRM clk support asoc: codec: make mclk freq configurable in Bolero asoc: lahaina: Add ext clk source support asoc: ext-clk: Add support for configuring ext clk dsp: afe: Enhance and expose API for configuring ext clk dsp: q6voice: Handle mutex lock-unlock asoc: msm-compress : Fix for CTS-on-gsi with gki Change-Id: I21b8e5f5ef608bf298230419123e4ee37c9b0797
This commit is contained in:
commit
bb0f246e35
32 changed files with 1549 additions and 384 deletions
2
techpack/audio/asoc/Kbuild
Executable file → Normal file
2
techpack/audio/asoc/Kbuild
Executable file → Normal file
|
|
@ -139,6 +139,8 @@ COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR)
|
|||
|
||||
############ ASoC Drivers ############
|
||||
|
||||
MACHINE_OBJS += msm-common.o
|
||||
|
||||
# for SM8150 sound card driver
|
||||
ifdef CONFIG_SND_SOC_SM8150
|
||||
MACHINE_OBJS += sm8150.o
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ struct audio_ext_clk_priv {
|
|||
const char *clk_name;
|
||||
uint32_t lpass_core_hwvote_client_handle;
|
||||
uint32_t lpass_audio_hwvote_client_handle;
|
||||
bool supports_ext_mclk;
|
||||
uint32_t ext_mclk_freq;
|
||||
};
|
||||
|
||||
static struct audio_ext_clk audio_clk_array[];
|
||||
|
|
@ -70,46 +72,75 @@ static int audio_ext_clk_prepare(struct clk_hw *hw)
|
|||
{
|
||||
struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
|
||||
struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
|
||||
|
||||
if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
clk_priv->clk_cfg.enable = 1;
|
||||
ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
|
||||
if (ret < 0) {
|
||||
if (__ratelimit(&rtl))
|
||||
pr_err_ratelimited("%s afe_set_digital_codec_core_clock failed\n",
|
||||
__func__);
|
||||
return ret;
|
||||
|
||||
/* Case 1. Clock driver supports ext clk source && platform enables ext clk support
|
||||
* - Use ext clk API
|
||||
* Case 2. Clock driver supports ext clk source && platform has NOT enabled ext clk support
|
||||
* - We try using ext clk API, it fails; we fall back to internal clk API
|
||||
* Case 3. Clock driver doesn't support ext clk source
|
||||
* - Use internal clk API
|
||||
*
|
||||
* NOTE: Platform, the machine driver, confirms ext clk support
|
||||
* by registering for the 'ext_mclk_cb' callback with
|
||||
* Q6AFE driver.
|
||||
*/
|
||||
if (clk_priv->supports_ext_mclk) {
|
||||
ret = afe_set_lpass_clk_cfg_ext_mclk(IDX_RSVD_3,
|
||||
&clk_priv->clk_cfg,
|
||||
clk_priv->ext_mclk_freq);
|
||||
if (ret == 0) {
|
||||
goto prepare_pinctrl;
|
||||
} else if (ret == -EOPNOTSUPP) {
|
||||
pr_err_ratelimited("%s: ext mclk prepare failed; falling back to internal clk\n",
|
||||
__func__);
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ret = afe_set_lpass_clk_cfg(IDX_RSVD_3,
|
||||
&clk_priv->clk_cfg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
prepare_pinctrl:
|
||||
if (pnctrl_info->pinctrl) {
|
||||
ret = pinctrl_select_state(pnctrl_info->pinctrl,
|
||||
pnctrl_info->active);
|
||||
pnctrl_info->active);
|
||||
if (ret) {
|
||||
pr_err("%s: active state select failed with %d\n",
|
||||
__func__, ret);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (pnctrl_info->base)
|
||||
iowrite32(1, pnctrl_info->base);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (__ratelimit(&rtl))
|
||||
pr_err_ratelimited("%s: afe_set_lpass_clk_cfg_ext_mclk failed with %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void audio_ext_clk_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
|
||||
struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
|
||||
|
||||
if (pnctrl_info->pinctrl) {
|
||||
ret = pinctrl_select_state(pnctrl_info->pinctrl,
|
||||
pnctrl_info->sleep);
|
||||
pnctrl_info->sleep);
|
||||
if (ret) {
|
||||
pr_err("%s: active state select failed with %d\n",
|
||||
__func__, ret);
|
||||
|
|
@ -117,19 +148,34 @@ static void audio_ext_clk_unprepare(struct clk_hw *hw)
|
|||
}
|
||||
}
|
||||
|
||||
if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
clk_priv->clk_cfg.enable = 0;
|
||||
ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
|
||||
if (ret < 0) {
|
||||
if (__ratelimit(&rtl))
|
||||
pr_err_ratelimited("%s: afe_set_lpass_clk_cfg failed, ret = %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (pnctrl_info->base)
|
||||
iowrite32(0, pnctrl_info->base);
|
||||
|
||||
if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
clk_priv->clk_cfg.enable = 0;
|
||||
if (clk_priv->supports_ext_mclk) {
|
||||
ret = afe_set_lpass_clk_cfg_ext_mclk(IDX_RSVD_3,
|
||||
&clk_priv->clk_cfg,
|
||||
clk_priv->ext_mclk_freq);
|
||||
if (ret == 0) {
|
||||
goto exit;
|
||||
} else if (ret == -EOPNOTSUPP) {
|
||||
pr_err_ratelimited("%s: ext mclk unprepare failed; falling back to internal clk\n",
|
||||
__func__);
|
||||
} else {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (ret && __ratelimit(&rtl))
|
||||
pr_err_ratelimited("%s: afe_set_lpass_clk_cfg failed, ret = %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
static u8 audio_ext_clk_get_parent(struct clk_hw *hw)
|
||||
|
|
@ -518,6 +564,7 @@ static int audio_ref_clk_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
struct audio_ext_clk_priv *clk_priv;
|
||||
u32 clk_freq = 0, clk_id = 0, clk_src = 0, use_pinctrl = 0;
|
||||
u32 ext_mclk_src_freq = 0;
|
||||
|
||||
clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
|
||||
if (!clk_priv)
|
||||
|
|
@ -561,9 +608,27 @@ static int audio_ref_clk_probe(struct platform_device *pdev)
|
|||
if (!ret)
|
||||
clk_priv->clk_cfg.clk_id = clk_id;
|
||||
|
||||
if (of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,supports-ext-mclk"))
|
||||
clk_priv->supports_ext_mclk = true;
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,ext-mclk-src-freq",
|
||||
&ext_mclk_src_freq);
|
||||
if (!ret) {
|
||||
clk_priv->ext_mclk_freq = ext_mclk_src_freq;
|
||||
} else if (clk_priv->supports_ext_mclk) {
|
||||
dev_err(&pdev->dev, "%s: qcom,ext-mclk-src-freq not defined\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
|
||||
__func__, clk_priv->clk_cfg.clk_freq_in_hz,
|
||||
clk_priv->clk_cfg.clk_id, clk_priv->clk_src);
|
||||
__func__, clk_priv->clk_cfg.clk_freq_in_hz,
|
||||
clk_priv->clk_cfg.clk_id, clk_priv->clk_src);
|
||||
dev_dbg(&pdev->dev, "%s: supports-ext-mclk: %d, ext-mclk-input-freq: %d\n",
|
||||
__func__, clk_priv->supports_ext_mclk, clk_priv->ext_mclk_freq);
|
||||
|
||||
platform_set_drvdata(pdev, clk_priv);
|
||||
|
||||
ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names",
|
||||
|
|
|
|||
|
|
@ -465,6 +465,7 @@ struct rx_macro_priv {
|
|||
u16 default_clk_id;
|
||||
int8_t rx0_gain_val;
|
||||
int8_t rx1_gain_val;
|
||||
u32 mclk_freq;
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver rx_macro_dai[];
|
||||
|
|
@ -1411,11 +1412,12 @@ static int rx_macro_mclk_event(struct snd_soc_dapm_widget *w,
|
|||
int ret = 0;
|
||||
struct device *rx_dev = NULL;
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
int mclk_freq = MCLK_FREQ;
|
||||
int mclk_freq = 0;
|
||||
|
||||
if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
mclk_freq = rx_priv->mclk_freq;
|
||||
dev_dbg(rx_dev, "%s: event = %d\n", __func__, event);
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
|
|
@ -2689,7 +2691,8 @@ static void rx_macro_hphdelay_lutbypass(struct snd_soc_component *component,
|
|||
}
|
||||
|
||||
if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
|
||||
snd_soc_component_update_bits(component,
|
||||
if (!rx_priv->is_ear_mode_on)
|
||||
snd_soc_component_update_bits(component,
|
||||
BOLERO_CDC_RX_RX0_RX_PATH_CFG1,
|
||||
0x02, 0x00);
|
||||
snd_soc_component_update_bits(component, hph_lut_bypass_reg,
|
||||
|
|
@ -4166,13 +4169,14 @@ static int rx_macro_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct macro_ops ops = {0};
|
||||
struct rx_macro_priv *rx_priv = NULL;
|
||||
u32 rx_base_addr = 0, muxsel = 0;
|
||||
u32 rx_base_addr = 0, muxsel = 0, mclk_freq = 0;
|
||||
char __iomem *rx_io_base = NULL, *muxsel_io = NULL;
|
||||
int ret = 0;
|
||||
u8 bcl_pmic_params[3];
|
||||
u32 default_clk_id = 0;
|
||||
u32 is_used_rx_swr_gpio = 1;
|
||||
const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
|
||||
const char *cdc_mclk_clk_rate = "qcom,cdc-mclk-clk-rate";
|
||||
|
||||
if (!bolero_is_va_macro_registered(&pdev->dev)) {
|
||||
dev_err(&pdev->dev,
|
||||
|
|
@ -4207,6 +4211,15 @@ static int rx_macro_probe(struct platform_device *pdev)
|
|||
__func__, "qcom,default-clk-id");
|
||||
default_clk_id = RX_CORE_CLK;
|
||||
}
|
||||
ret = of_property_read_u32(pdev->dev.of_node, cdc_mclk_clk_rate,
|
||||
&mclk_freq);
|
||||
if (ret) {
|
||||
rx_priv->mclk_freq = MCLK_FREQ;
|
||||
} else {
|
||||
rx_priv->mclk_freq = mclk_freq;
|
||||
}
|
||||
dev_dbg(rx_priv->dev,
|
||||
"%s: mclk_freq = %u\n", __func__, rx_priv->mclk_freq);
|
||||
if (of_find_property(pdev->dev.of_node, is_used_rx_swr_gpio_dt,
|
||||
NULL)) {
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ struct tx_macro_priv {
|
|||
bool register_event_listener;
|
||||
u16 current_clk_id;
|
||||
int disable_afe_wakeup_event_listener;
|
||||
u32 mclk_freq;
|
||||
};
|
||||
|
||||
static bool tx_macro_get_data(struct snd_soc_component *component,
|
||||
|
|
@ -2985,13 +2986,12 @@ static int tx_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
|
|||
struct tx_macro_priv *tx_priv)
|
||||
{
|
||||
u32 div_factor = TX_MACRO_CLK_DIV_2;
|
||||
u32 mclk_rate = TX_MACRO_MCLK_FREQ;
|
||||
|
||||
if (dmic_sample_rate == TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
|
||||
mclk_rate % dmic_sample_rate != 0)
|
||||
tx_priv->mclk_freq % dmic_sample_rate != 0)
|
||||
goto undefined_rate;
|
||||
|
||||
div_factor = mclk_rate / dmic_sample_rate;
|
||||
div_factor = tx_priv->mclk_freq / dmic_sample_rate;
|
||||
|
||||
switch (div_factor) {
|
||||
case 2:
|
||||
|
|
@ -3019,13 +3019,13 @@ static int tx_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
|
|||
|
||||
/* Valid dmic DIV factors */
|
||||
dev_dbg(tx_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
|
||||
__func__, div_factor, mclk_rate);
|
||||
__func__, div_factor, tx_priv->mclk_freq);
|
||||
|
||||
return dmic_sample_rate;
|
||||
|
||||
undefined_rate:
|
||||
dev_dbg(tx_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
|
||||
__func__, dmic_sample_rate, mclk_rate);
|
||||
__func__, dmic_sample_rate, tx_priv->mclk_freq);
|
||||
dmic_sample_rate = TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
|
||||
|
||||
return dmic_sample_rate;
|
||||
|
|
@ -3362,10 +3362,11 @@ static int tx_macro_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct macro_ops ops = {0};
|
||||
struct tx_macro_priv *tx_priv = NULL;
|
||||
u32 tx_base_addr = 0, sample_rate = 0;
|
||||
u32 tx_base_addr = 0, sample_rate = 0, mclk_freq = 0;
|
||||
char __iomem *tx_io_base = NULL;
|
||||
int ret = 0;
|
||||
const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate";
|
||||
const char *cdc_mclk_clk_rate = "qcom,cdc-mclk-clk-rate";
|
||||
u32 is_used_tx_swr_gpio = 1;
|
||||
const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio";
|
||||
u32 disable_afe_wakeup_event_listener = 0;
|
||||
|
|
@ -3425,6 +3426,17 @@ static int tx_macro_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
tx_priv->tx_io_base = tx_io_base;
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, cdc_mclk_clk_rate,
|
||||
&mclk_freq);
|
||||
if (ret) {
|
||||
tx_priv->mclk_freq = TX_MACRO_MCLK_FREQ;
|
||||
} else {
|
||||
tx_priv->mclk_freq = mclk_freq;
|
||||
}
|
||||
dev_dbg(tx_priv->dev,
|
||||
"%s: mclk_freq = %u\n", __func__, tx_priv->mclk_freq);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
|
||||
&sample_rate);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ struct va_macro_priv {
|
|||
u16 current_clk_id;
|
||||
int pcm_rate[VA_MACRO_NUM_DECIMATORS];
|
||||
bool dev_up;
|
||||
u32 mclk_freq;
|
||||
};
|
||||
|
||||
static bool va_macro_get_data(struct snd_soc_component *component,
|
||||
|
|
@ -1567,6 +1568,12 @@ static int va_macro_hw_params(struct snd_pcm_substream *substream,
|
|||
dai->name, dai->id, params_rate(params),
|
||||
params_channels(params));
|
||||
|
||||
if (va_priv->mclk_freq != VA_MACRO_MCLK_FREQ) {
|
||||
dev_err(va_dev, "%s: unsupported VA mclk: %u\n",
|
||||
__func__, va_priv->mclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sample_rate = params_rate(params);
|
||||
if (sample_rate > 16000)
|
||||
va_priv->clk_div_switch = true;
|
||||
|
|
@ -2636,13 +2643,12 @@ static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
|
|||
struct va_macro_priv *va_priv)
|
||||
{
|
||||
u32 div_factor;
|
||||
u32 mclk_rate = VA_MACRO_MCLK_FREQ;
|
||||
|
||||
if (dmic_sample_rate == VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED ||
|
||||
mclk_rate % dmic_sample_rate != 0)
|
||||
va_priv->mclk_freq % dmic_sample_rate != 0)
|
||||
goto undefined_rate;
|
||||
|
||||
div_factor = mclk_rate / dmic_sample_rate;
|
||||
div_factor = va_priv->mclk_freq / dmic_sample_rate;
|
||||
|
||||
switch (div_factor) {
|
||||
case 2:
|
||||
|
|
@ -2670,13 +2676,13 @@ static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
|
|||
|
||||
/* Valid dmic DIV factors */
|
||||
dev_dbg(va_priv->dev, "%s: DMIC_DIV = %u, mclk_rate = %u\n",
|
||||
__func__, div_factor, mclk_rate);
|
||||
__func__, div_factor, va_priv->mclk_freq);
|
||||
|
||||
return dmic_sample_rate;
|
||||
|
||||
undefined_rate:
|
||||
dev_dbg(va_priv->dev, "%s: Invalid rate %d, for mclk %d\n",
|
||||
__func__, dmic_sample_rate, mclk_rate);
|
||||
__func__, dmic_sample_rate, va_priv->mclk_freq);
|
||||
dmic_sample_rate = VA_MACRO_DMIC_SAMPLE_RATE_UNDEFINED;
|
||||
|
||||
return dmic_sample_rate;
|
||||
|
|
@ -3061,7 +3067,7 @@ static int va_macro_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct macro_ops ops;
|
||||
struct va_macro_priv *va_priv;
|
||||
u32 va_base_addr, sample_rate = 0;
|
||||
u32 va_base_addr, sample_rate = 0, mclk_freq = 0;
|
||||
char __iomem *va_io_base;
|
||||
bool va_without_decimation = false;
|
||||
const char *micb_supply_str = "va-vdd-micb-supply";
|
||||
|
|
@ -3074,6 +3080,7 @@ static int va_macro_probe(struct platform_device *pdev)
|
|||
struct clk *lpass_audio_hw_vote = NULL;
|
||||
u32 is_used_va_swr_gpio = 0;
|
||||
const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
|
||||
const char *cdc_mclk_clk_rate = "qcom,cdc-mclk-clk-rate";
|
||||
|
||||
va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv),
|
||||
GFP_KERNEL);
|
||||
|
|
@ -3092,6 +3099,15 @@ static int va_macro_probe(struct platform_device *pdev)
|
|||
"qcom,va-without-decimation");
|
||||
|
||||
va_priv->va_without_decimation = va_without_decimation;
|
||||
ret = of_property_read_u32(pdev->dev.of_node, cdc_mclk_clk_rate,
|
||||
&mclk_freq);
|
||||
if (ret) {
|
||||
va_priv->mclk_freq = VA_MACRO_MCLK_FREQ;
|
||||
} else {
|
||||
va_priv->mclk_freq = mclk_freq;
|
||||
}
|
||||
dev_dbg(va_priv->dev,
|
||||
"%s: mclk_freq = %u\n", __func__, va_priv->mclk_freq);
|
||||
ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
|
||||
&sample_rate);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
|
||||
enum {
|
||||
DP_CONTROLLER0 = 0,
|
||||
HDMI_CONTROLLER,
|
||||
DP_CONTROLLER_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -96,7 +98,7 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
|
|||
codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai_id == HDMI_MS_DAI)
|
||||
if (dai_id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -148,7 +150,7 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
|
|||
codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai_id == HDMI_MS_DAI)
|
||||
if (dai_id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -214,7 +216,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
|
|||
codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai_id == HDMI_MS_DAI)
|
||||
if (dai_id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -306,7 +308,7 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
|
|||
codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai_id == HDMI_MS_DAI)
|
||||
if (dai_id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -366,7 +368,7 @@ static int msm_ext_disp_audio_device_get(struct snd_kcontrol *kcontrol,
|
|||
int dai_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
|
||||
if (dai_id < 0 || dai_id > DP_DAI2) {
|
||||
if (dai_id < 0 || dai_id >= DP_DAI_MAX) {
|
||||
dev_err(component->dev,
|
||||
"%s: invalid dai id: %d\n", __func__, dai_id);
|
||||
rc = -EINVAL;
|
||||
|
|
@ -398,7 +400,7 @@ static int msm_ext_disp_audio_device_set(struct snd_kcontrol *kcontrol,
|
|||
int dai_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
|
||||
if (dai_id < 0 || dai_id > DP_DAI2) {
|
||||
if (dai_id < 0 || dai_id >= DP_DAI_MAX) {
|
||||
dev_err(component->dev,
|
||||
"%s: invalid dai id: %d\n", __func__, dai_id);
|
||||
rc = -EINVAL;
|
||||
|
|
@ -498,8 +500,8 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
|
|||
SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2,
|
||||
msm_ext_disp_audio_device_get,
|
||||
msm_ext_disp_audio_device_set),
|
||||
SOC_SINGLE_MULTI_EXT("External HDMI Device",
|
||||
SND_SOC_NOPM, HDMI_MS_DAI, DP_STREAM_MAX - 1, 0, 2,
|
||||
SOC_SINGLE_MULTI_EXT("External HDMI Audio Device",
|
||||
SND_SOC_NOPM, HDMI_DAI, DP_STREAM_MAX - 1, 0, 2,
|
||||
msm_ext_disp_audio_device_get,
|
||||
msm_ext_disp_audio_device_set),
|
||||
|
||||
|
|
@ -526,7 +528,7 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
|
|||
codec_data->ctl[dai->id], codec_data->stream[dai->id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai->id == HDMI_MS_DAI)
|
||||
if (dai->id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -587,7 +589,7 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
|
|||
codec_data->ctl[dai->id], codec_data->stream[dai->id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai->id == HDMI_MS_DAI)
|
||||
if (dai->id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
@ -661,6 +663,10 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
|
|||
audio_setup_params.down_mix = down_mix;
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai->id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
|
||||
rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
|
||||
&codec_info);
|
||||
|
|
@ -701,7 +707,7 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
|
|||
codec_data->ctl[dai->id], codec_data->stream[dai->id]);
|
||||
|
||||
mutex_lock(&codec_data->dp_ops_lock);
|
||||
if (dai->id == HDMI_MS_DAI)
|
||||
if (dai->id == HDMI_DAI)
|
||||
type = EXT_DISPLAY_TYPE_HDMI;
|
||||
else
|
||||
type = EXT_DISPLAY_TYPE_DP;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -60,6 +60,8 @@ enum {
|
|||
HPH_COMP_DELAY,
|
||||
HPH_PA_DELAY,
|
||||
AMIC2_BCS_ENABLE,
|
||||
WCD_HPHL_EN,
|
||||
WCD_EAR_EN,
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
|
||||
|
|
@ -876,6 +878,7 @@ static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|||
set_bit(HPH_PA_DELAY, &wcd937x->status_mask);
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_PDM_WD_CTL0, 0x17, 0x13);
|
||||
set_bit(WCD_HPHL_EN, &wcd937x->status_mask);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
/*
|
||||
|
|
@ -906,12 +909,14 @@ static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|||
WCD937X_IRQ_HPHL_PDM_WD_INT);
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
wcd_disable_irq(&wcd937x->irq_info,
|
||||
if (!test_bit(WCD_EAR_EN, &wcd937x->status_mask)) {
|
||||
wcd_disable_irq(&wcd937x->irq_info,
|
||||
WCD937X_IRQ_HPHL_PDM_WD_INT);
|
||||
if (wcd937x->update_wcd_event)
|
||||
wcd937x->update_wcd_event(wcd937x->handle,
|
||||
if (wcd937x->update_wcd_event)
|
||||
wcd937x->update_wcd_event(wcd937x->handle,
|
||||
SLV_BOLERO_EVT_RX_MUTE,
|
||||
(WCD_RX1 << 0x10 | 0x1));
|
||||
}
|
||||
blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
|
||||
WCD_EVENT_PRE_HPHL_PA_OFF,
|
||||
&wcd937x->mbhc->wcd_mbhc);
|
||||
|
|
@ -942,6 +947,7 @@ static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|||
WCD_CLSH_EVENT_POST_PA,
|
||||
WCD_CLSH_STATE_HPHL,
|
||||
hph_mode);
|
||||
clear_bit(WCD_HPHL_EN, &wcd937x->status_mask);
|
||||
break;
|
||||
};
|
||||
return ret;
|
||||
|
|
@ -1030,10 +1036,12 @@ static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_PDM_WD_CTL2,
|
||||
0x05, 0x05);
|
||||
else
|
||||
else {
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_PDM_WD_CTL0,
|
||||
0x17, 0x13);
|
||||
set_bit(WCD_EAR_EN, &wcd937x->status_mask);
|
||||
}
|
||||
if (!wcd937x->comp1_enable)
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD937X_ANA_EAR_COMPANDER_CTL, 0x80, 0x80);
|
||||
|
|
@ -1056,16 +1064,24 @@ static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|||
WCD937X_IRQ_HPHL_PDM_WD_INT);
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX)
|
||||
if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX) {
|
||||
wcd_disable_irq(&wcd937x->irq_info,
|
||||
WCD937X_IRQ_AUX_PDM_WD_INT);
|
||||
else
|
||||
wcd_disable_irq(&wcd937x->irq_info,
|
||||
if (wcd937x->update_wcd_event)
|
||||
wcd937x->update_wcd_event(wcd937x->handle,
|
||||
SLV_BOLERO_EVT_RX_MUTE,
|
||||
(WCD_RX1 << 0x10 | 0x1));
|
||||
}
|
||||
else {
|
||||
if(!test_bit(WCD_HPHL_EN, &wcd937x->status_mask)) {
|
||||
wcd_disable_irq(&wcd937x->irq_info,
|
||||
WCD937X_IRQ_HPHL_PDM_WD_INT);
|
||||
if (wcd937x->update_wcd_event)
|
||||
wcd937x->update_wcd_event(wcd937x->handle,
|
||||
if (wcd937x->update_wcd_event)
|
||||
wcd937x->update_wcd_event(wcd937x->handle,
|
||||
SLV_BOLERO_EVT_RX_MUTE,
|
||||
(WCD_RX1 << 0x10 | 0x1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
if (!wcd937x->comp1_enable)
|
||||
|
|
@ -1082,10 +1098,12 @@ static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_PDM_WD_CTL2,
|
||||
0x05, 0x00);
|
||||
else
|
||||
else {
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_PDM_WD_CTL0,
|
||||
0x17, 0x00);
|
||||
clear_bit(WCD_EAR_EN, &wcd937x->status_mask);
|
||||
}
|
||||
usleep_range(10000, 10010);
|
||||
/* disable EAR CnP FSM */
|
||||
snd_soc_component_update_bits(component,
|
||||
|
|
@ -1151,13 +1169,16 @@ static int wcd937x_enable_rx1(struct snd_soc_dapm_widget *w,
|
|||
wcd937x_rx_connect_port(component, COMP_L, true);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
wcd937x_rx_connect_port(component, HPH_L, false);
|
||||
if (wcd937x->comp1_enable)
|
||||
wcd937x_rx_connect_port(component, COMP_L, false);
|
||||
wcd937x_rx_clk_disable(component);
|
||||
snd_soc_component_update_bits(component,
|
||||
if (!test_bit(WCD_HPHL_EN, &wcd937x->status_mask) &&
|
||||
!test_bit(WCD_EAR_EN, &wcd937x->status_mask)) {
|
||||
wcd937x_rx_connect_port(component, HPH_L, false);
|
||||
if (wcd937x->comp1_enable)
|
||||
wcd937x_rx_connect_port(component, COMP_L, false);
|
||||
wcd937x_rx_clk_disable(component);
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
|
||||
0x01, 0x00);
|
||||
}
|
||||
break;
|
||||
};
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "codecs/bolero/wsa-macro.h"
|
||||
#include "lahaina-port-config.h"
|
||||
#include "msm_dailink.h"
|
||||
#include "msm-common.h"
|
||||
|
||||
#define DRV_NAME "lahaina-asoc-snd"
|
||||
#define __CHIPSET__ "LAHAINA "
|
||||
|
|
@ -132,16 +133,6 @@ enum {
|
|||
AUX_PCM_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
PRIM_MI2S = 0,
|
||||
SEC_MI2S,
|
||||
TERT_MI2S,
|
||||
QUAT_MI2S,
|
||||
QUIN_MI2S,
|
||||
SEN_MI2S,
|
||||
MI2S_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
WSA_CDC_DMA_RX_0 = 0,
|
||||
WSA_CDC_DMA_RX_1,
|
||||
|
|
@ -182,28 +173,42 @@ enum {
|
|||
AFE_LOOPBACK_TX_IDX_MAX,
|
||||
};
|
||||
|
||||
struct msm_asoc_mach_data {
|
||||
struct snd_info_entry *codec_root;
|
||||
int usbc_en2_gpio; /* used by gpio driver API */
|
||||
int lito_v2_enabled;
|
||||
struct device_node *dmic01_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *dmic23_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *dmic45_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
|
||||
atomic_t mi2s_gpio_ref_count[MI2S_MAX]; /* used by pinctrl API */
|
||||
struct device_node *us_euro_gpio_p; /* used by pinctrl API */
|
||||
struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
|
||||
bool is_afe_config_done;
|
||||
struct device_node *fsa_handle;
|
||||
struct clk *lpass_audio_hw_vote;
|
||||
int core_audio_vote_count;
|
||||
u32 wsa_max_devs;
|
||||
u32 tdm_max_slots; /* Max TDM slots used */
|
||||
int wcd_disabled;
|
||||
int (*get_wsa_dev_num)(struct snd_soc_component*);
|
||||
struct afe_cps_hw_intf_cfg cps_config;
|
||||
#define MCLK_CFG_CELLS 5
|
||||
struct ext_mclk_freq_cfg {
|
||||
u32 clk_freq;
|
||||
u32 div2x;
|
||||
u32 m;
|
||||
u32 n;
|
||||
u32 d;
|
||||
};
|
||||
|
||||
/* Coupled with "qcom,ext-mclk-srcs" DTSI property */
|
||||
#define MCLK_SRCS_CELLS 3
|
||||
struct ext_mclk_src_cfg {
|
||||
u32 clk_id;
|
||||
u32 clk_root;
|
||||
u32 gpio_idx;
|
||||
};
|
||||
|
||||
struct ext_mclk_cfg_info {
|
||||
u32 mclk_freq;
|
||||
const char *prop;
|
||||
struct ext_mclk_freq_cfg *mclk_cfg;
|
||||
u32 num_mclk_cfg;
|
||||
};
|
||||
|
||||
struct ext_mclk_gpio_info {
|
||||
struct device_node *gpio_p; /* used by pinctrl API */
|
||||
const char *ext_mclk_muxsel_str;
|
||||
uint32_t ext_mclk_muxsel_val;
|
||||
uint32_t ref_cnt;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct ext_mclk_src_info {
|
||||
u32 clk_id;
|
||||
u32 clk_root;
|
||||
struct ext_mclk_gpio_info *gpio_info;
|
||||
};
|
||||
|
||||
struct tdm_port {
|
||||
|
|
@ -227,6 +232,19 @@ struct dev_config {
|
|||
u32 channels;
|
||||
};
|
||||
|
||||
static bool ext_mclk_enable;
|
||||
static uint32_t num_ext_mclk_gpios;
|
||||
static struct ext_mclk_gpio_info *ext_mclk_gpio_info;
|
||||
static struct ext_mclk_src_cfg *ext_mclk_src_info;
|
||||
static struct ext_mclk_cfg_info ext_mclk_freq_info[MCLK_FREQ_MAX] = {
|
||||
[MCLK_FREQ_11P2896_MHZ] = {11289600, "ext-mclk-cfg-11p2896", NULL, 0},
|
||||
[MCLK_FREQ_12P288_MHZ] = {12288000, "ext-mclk-cfg-12p288", NULL, 0},
|
||||
[MCLK_FREQ_16P384_MHZ] = {16384000, "ext-mclk-cfg-16p384", NULL, 0},
|
||||
[MCLK_FREQ_19P200_MHZ] = {19200000, "ext-mclk-cfg-19p200", NULL, 0},
|
||||
[MCLK_FREQ_22P5792_MHZ] = {22579200, "ext-mclk-cfg-22p5792", NULL, 0},
|
||||
[MCLK_FREQ_24P576_MHZ] = {24576000, "ext-mclk-cfg-24p576", NULL, 0},
|
||||
};
|
||||
|
||||
/* Default configuration of slimbus channels */
|
||||
static struct dev_config slim_rx_cfg[] = {
|
||||
[SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
|
||||
|
|
@ -1027,6 +1045,213 @@ static cpumask_t audio_cpu_map = CPU_MASK_NONE;
|
|||
static struct dev_pm_qos_request *msm_audio_req;
|
||||
static unsigned int qos_client_active_cnt;
|
||||
|
||||
static int lahaina_audio_vote(struct snd_soc_card *card, bool enable)
|
||||
{
|
||||
struct msm_asoc_mach_data *pdata = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!card) {
|
||||
pr_err("%s: sound card is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata = snd_soc_card_get_drvdata(card);
|
||||
if (!pdata || !pdata->lpass_audio_hw_vote) {
|
||||
pr_err("%s: lpass audio hw voting not supported\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Locking and reference counting is handled by the underlying clock
|
||||
* framework.
|
||||
*/
|
||||
if (enable) {
|
||||
ret = clk_prepare_enable(pdata->lpass_audio_hw_vote);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "%s: audio vote error: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
clk_disable_unprepare(pdata->lpass_audio_hw_vote);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lahaina_populate_ext_mclk_cfg(struct ext_mclk_cfg_info *freq_cfg,
|
||||
uint32_t mclk_freq,
|
||||
struct afe_param_id_clock_set_v2_t *dyn_mclk_cfg)
|
||||
{
|
||||
struct ext_mclk_freq_cfg *mclk_cfg = NULL;
|
||||
uint32_t mclk_cfg_entries = 0;
|
||||
enum afe_mclk_freq freq = MCLK_FREQ_MIN;
|
||||
int i = 0;
|
||||
|
||||
if (!freq_cfg || !dyn_mclk_cfg)
|
||||
return -EINVAL;
|
||||
|
||||
for (freq = MCLK_FREQ_MIN; freq < MCLK_FREQ_MAX; freq++) {
|
||||
if (freq_cfg[freq].mclk_freq == mclk_freq)
|
||||
break;
|
||||
}
|
||||
|
||||
if (freq == MCLK_FREQ_MAX) {
|
||||
pr_err("%s: unsupported mclk freq: %u\n", __func__, mclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!freq_cfg[freq].mclk_cfg ||
|
||||
!freq_cfg[freq].num_mclk_cfg) {
|
||||
pr_err("%s: cfg table unavailable for mclk freq: %u\n",
|
||||
__func__, mclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mclk_cfg = freq_cfg[freq].mclk_cfg;
|
||||
mclk_cfg_entries = freq_cfg[freq].num_mclk_cfg;
|
||||
|
||||
for (i = 0; i < mclk_cfg_entries; i++) {
|
||||
if (mclk_cfg[i].clk_freq == dyn_mclk_cfg->clk_freq_in_hz) {
|
||||
dyn_mclk_cfg->divider_2x = mclk_cfg[i].div2x;
|
||||
dyn_mclk_cfg->m = mclk_cfg[i].m;
|
||||
dyn_mclk_cfg->n = mclk_cfg[i].n;
|
||||
dyn_mclk_cfg->d = mclk_cfg[i].d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == mclk_cfg_entries) {
|
||||
pr_err("%s: requested output mclk freq %u is not supported\n",
|
||||
__func__, dyn_mclk_cfg->clk_freq_in_hz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lahaina_handle_ext_mclk_gpio(struct snd_soc_card *card,
|
||||
struct ext_mclk_gpio_info *gpio_info,
|
||||
uint32_t enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!gpio_info)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&gpio_info->lock);
|
||||
if (enable) {
|
||||
if (++gpio_info->ref_cnt == 1) {
|
||||
ret = msm_cdc_pinctrl_select_active_state(gpio_info->gpio_p);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: couldn't activate mclk pinctrl\n",
|
||||
__func__);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (gpio_info->ext_mclk_muxsel_str != NULL) {
|
||||
ret = lahaina_audio_vote(card, true);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: HW voting failed, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = afe_set_lpass_ext_mclk_mux_cfg(gpio_info->ext_mclk_muxsel_str,
|
||||
gpio_info->ext_mclk_muxsel_val);
|
||||
lahaina_audio_vote(card, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (--gpio_info->ref_cnt == 0) {
|
||||
ret = msm_cdc_pinctrl_select_sleep_state(gpio_info->gpio_p);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: couldn't deactivate mclk pinctrl\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&gpio_info->lock);
|
||||
if (ret)
|
||||
enable ? --gpio_info->ref_cnt : ++gpio_info->ref_cnt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lahaina_enable_and_get_mclk_cfg(void *private_data, uint32_t enable,
|
||||
uint32_t mclk_freq,
|
||||
struct afe_param_id_clock_set_v2_t *dyn_mclk_cfg)
|
||||
{
|
||||
struct snd_soc_card *card = (struct snd_soc_card *)private_data;
|
||||
struct msm_asoc_mach_data *pdata = NULL;
|
||||
struct ext_mclk_src_info *ext_mclk_src = NULL;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!card || !dyn_mclk_cfg)
|
||||
return -EINVAL;
|
||||
|
||||
if (!ext_mclk_enable) {
|
||||
dev_err(card->dev, "%s: ext mclk support not enabled on the platform\n",
|
||||
__func__);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
pdata = snd_soc_card_get_drvdata(card);
|
||||
if (!pdata || !pdata->ext_mclk_srcs || !pdata->num_ext_mclk_srcs)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < pdata->num_ext_mclk_srcs; i++) {
|
||||
if (pdata->ext_mclk_srcs[i].clk_id == dyn_mclk_cfg->clk_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == pdata->num_ext_mclk_srcs) {
|
||||
dev_err(card->dev, "%s: unsupported clk id for ext mclk support: %u\n",
|
||||
__func__, dyn_mclk_cfg->clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_mclk_src = &pdata->ext_mclk_srcs[i];
|
||||
if (!ext_mclk_src) {
|
||||
dev_err(card->dev, "%s: ext mclk src/clk cfg unavailable for mclk: %u\n",
|
||||
__func__, pdata->ext_mclk_srcs[i].clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Populate clk root */
|
||||
dyn_mclk_cfg->clk_root = (uint16_t) ext_mclk_src->clk_root;
|
||||
|
||||
/* Populate div2x, M, N, D values */
|
||||
ret = lahaina_populate_ext_mclk_cfg(ext_mclk_freq_info, mclk_freq,
|
||||
dyn_mclk_cfg);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: unable to populate ext mclk cfg, ret: %d\n", __func__, ret);
|
||||
goto reset;
|
||||
}
|
||||
|
||||
/* Enable/disable ext mclk GPIO */
|
||||
ret = lahaina_handle_ext_mclk_gpio(card, ext_mclk_src->gpio_info, enable);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: unable to enable/disable ext mclk gpio, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto reset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reset:
|
||||
/* Reset clk cfg */
|
||||
dyn_mclk_cfg->divider_2x = 0;
|
||||
dyn_mclk_cfg->m = 0;
|
||||
dyn_mclk_cfg->n = 0;
|
||||
dyn_mclk_cfg->d = 0;
|
||||
dyn_mclk_cfg->clk_root = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm_audio_add_qos_request(void)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -1814,20 +2039,41 @@ static int tdm_get_sample_rate(int value)
|
|||
sample_rate = SAMPLING_RATE_8KHZ;
|
||||
break;
|
||||
case 1:
|
||||
sample_rate = SAMPLING_RATE_16KHZ;
|
||||
sample_rate = SAMPLING_RATE_11P025KHZ;
|
||||
break;
|
||||
case 2:
|
||||
sample_rate = SAMPLING_RATE_32KHZ;
|
||||
sample_rate = SAMPLING_RATE_16KHZ;
|
||||
break;
|
||||
case 3:
|
||||
sample_rate = SAMPLING_RATE_48KHZ;
|
||||
sample_rate = SAMPLING_RATE_22P05KHZ;
|
||||
break;
|
||||
case 4:
|
||||
sample_rate = SAMPLING_RATE_176P4KHZ;
|
||||
sample_rate = SAMPLING_RATE_32KHZ;
|
||||
break;
|
||||
case 5:
|
||||
sample_rate = SAMPLING_RATE_44P1KHZ;
|
||||
break;
|
||||
case 6:
|
||||
sample_rate = SAMPLING_RATE_48KHZ;
|
||||
break;
|
||||
case 7:
|
||||
sample_rate = SAMPLING_RATE_88P2KHZ;
|
||||
break;
|
||||
case 8:
|
||||
sample_rate = SAMPLING_RATE_96KHZ;
|
||||
break;
|
||||
case 9:
|
||||
sample_rate = SAMPLING_RATE_176P4KHZ;
|
||||
break;
|
||||
case 10:
|
||||
sample_rate = SAMPLING_RATE_192KHZ;
|
||||
break;
|
||||
case 11:
|
||||
sample_rate = SAMPLING_RATE_352P8KHZ;
|
||||
break;
|
||||
case 12:
|
||||
sample_rate = SAMPLING_RATE_384KHZ;
|
||||
break;
|
||||
default:
|
||||
sample_rate = SAMPLING_RATE_48KHZ;
|
||||
break;
|
||||
|
|
@ -1843,23 +2089,44 @@ static int tdm_get_sample_rate_val(int sample_rate)
|
|||
case SAMPLING_RATE_8KHZ:
|
||||
sample_rate_val = 0;
|
||||
break;
|
||||
case SAMPLING_RATE_16KHZ:
|
||||
case SAMPLING_RATE_11P025KHZ:
|
||||
sample_rate_val = 1;
|
||||
break;
|
||||
case SAMPLING_RATE_32KHZ:
|
||||
case SAMPLING_RATE_16KHZ:
|
||||
sample_rate_val = 2;
|
||||
break;
|
||||
case SAMPLING_RATE_48KHZ:
|
||||
case SAMPLING_RATE_22P05KHZ:
|
||||
sample_rate_val = 3;
|
||||
break;
|
||||
case SAMPLING_RATE_176P4KHZ:
|
||||
case SAMPLING_RATE_32KHZ:
|
||||
sample_rate_val = 4;
|
||||
break;
|
||||
case SAMPLING_RATE_352P8KHZ:
|
||||
case SAMPLING_RATE_44P1KHZ:
|
||||
sample_rate_val = 5;
|
||||
break;
|
||||
case SAMPLING_RATE_48KHZ:
|
||||
sample_rate_val = 6;
|
||||
break;
|
||||
case SAMPLING_RATE_88P2KHZ:
|
||||
sample_rate_val = 7;
|
||||
break;
|
||||
case SAMPLING_RATE_96KHZ:
|
||||
sample_rate_val = 8;
|
||||
break;
|
||||
case SAMPLING_RATE_176P4KHZ:
|
||||
sample_rate_val = 9;
|
||||
break;
|
||||
case SAMPLING_RATE_192KHZ:
|
||||
sample_rate_val = 10;
|
||||
break;
|
||||
case SAMPLING_RATE_352P8KHZ:
|
||||
sample_rate_val = 11;
|
||||
break;
|
||||
case SAMPLING_RATE_384KHZ:
|
||||
sample_rate_val = 12;
|
||||
break;
|
||||
default:
|
||||
sample_rate_val = 3;
|
||||
sample_rate_val = 6;
|
||||
break;
|
||||
}
|
||||
return sample_rate_val;
|
||||
|
|
@ -4742,6 +5009,25 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
|
|||
aux_pcm_tx_sample_rate_put),
|
||||
};
|
||||
|
||||
static int msm_ext_mclk_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = ext_mclk_enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_ext_mclk_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ext_mclk_enable = (bool) ucontrol->value.integer.value[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new msm_ext_mclk_controls[] = {
|
||||
SOC_SINGLE_BOOL_EXT("EXT MCLK Enable", 0,
|
||||
msm_ext_mclk_get, msm_ext_mclk_put),
|
||||
};
|
||||
|
||||
static int msm_ext_disp_get_idx_from_beid(int32_t be_id)
|
||||
{
|
||||
int idx;
|
||||
|
|
@ -8806,6 +9092,411 @@ static void parse_cps_configuration(struct platform_device *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int msm_parse_ext_mclk_gpios(struct snd_soc_card *card,
|
||||
struct ext_mclk_gpio_info **ext_mclk_gpios)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t num_gpios = 0;
|
||||
struct device_node *np = NULL;
|
||||
struct ext_mclk_gpio_info *gpio_info = NULL;
|
||||
const char *ext_mclk_muxsel_str = NULL;
|
||||
u32 ext_mclk_muxsel_val = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!card || !card->dev || !card->dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
np = card->dev->of_node;
|
||||
|
||||
if (!of_get_property(np, "qcom,ext-mclk-gpios", &len)) {
|
||||
dev_err(card->dev, "%s: ext mclk gpios not found in DT\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
dev_err(card->dev, "%s: invalid ext mclk gpios configuration in DT\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_gpios = len / sizeof(uint32_t);
|
||||
dev_dbg(card->dev, "%d ext mclk gpios found\n", num_gpios);
|
||||
|
||||
gpio_info = devm_kzalloc(card->dev,
|
||||
num_gpios * sizeof(struct ext_mclk_gpio_info),
|
||||
GFP_KERNEL);
|
||||
if (!gpio_info)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_gpios; i++) {
|
||||
mutex_init(&gpio_info[i].lock);
|
||||
gpio_info[i].ref_cnt = 0;
|
||||
gpio_info[i].gpio_p = of_parse_phandle(np, "qcom,ext-mclk-gpios", i);
|
||||
if (!gpio_info[i].gpio_p) {
|
||||
dev_err(card->dev, "ext mclk gpio %d device node is NULL", i);
|
||||
ret = -EINVAL;
|
||||
goto free_gpio_info;
|
||||
}
|
||||
|
||||
/* aud_ref_mux is present only for LPI GPIOs on lahaina.
|
||||
* Hence we mandate parsing of mux config only for LPI GPIOs.
|
||||
* Review the existence of aud_ref_mux for LPI/TLMM GPIOs
|
||||
* while porting this change to other platforms
|
||||
*/
|
||||
if (of_property_read_bool(gpio_info[i].gpio_p, "qcom,lpi-gpios")) {
|
||||
ret = of_property_read_string(gpio_info[i].gpio_p,
|
||||
"qcom,ext-mclk-muxsel-str", &ext_mclk_muxsel_str);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: qcom,ext-mclk-muxsel-str not found in DT\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto free_gpio_info;
|
||||
} else {
|
||||
ret = of_property_read_u32(gpio_info[i].gpio_p,
|
||||
"qcom,ext-mclk-muxsel-val", &ext_mclk_muxsel_val);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: qcom,ext-mclk-muxsel-val not found in DT\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto free_gpio_info;
|
||||
}
|
||||
}
|
||||
dev_dbg(card->dev, "%s: gpio_info[%d] - muxsel= %s, val= %u\n",
|
||||
__func__, i, ext_mclk_muxsel_str, ext_mclk_muxsel_val);
|
||||
gpio_info[i].ext_mclk_muxsel_str = ext_mclk_muxsel_str;
|
||||
gpio_info[i].ext_mclk_muxsel_val = ext_mclk_muxsel_val;
|
||||
}
|
||||
}
|
||||
|
||||
num_ext_mclk_gpios = num_gpios;
|
||||
*ext_mclk_gpios = gpio_info;
|
||||
dev_dbg(card->dev, "%s: ext mclk gpios probe successful\n", __func__);
|
||||
return 0;
|
||||
|
||||
free_gpio_info:
|
||||
for (; i >= 0; i--) {
|
||||
mutex_destroy(&gpio_info[i].lock);
|
||||
of_node_put(gpio_info[i].gpio_p);
|
||||
}
|
||||
devm_kfree(card->dev, gpio_info);
|
||||
gpio_info = NULL;
|
||||
|
||||
*ext_mclk_gpios = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_parse_ext_mclk_srcs(struct snd_soc_card *card,
|
||||
struct ext_mclk_src_cfg **ext_mclk_src,
|
||||
uint32_t *n_srcs)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ext_mclk_src_cfg *src_cfg = NULL;
|
||||
struct device_node *np = NULL;
|
||||
uint32_t len = 0;
|
||||
uint32_t num_srcs = 0;
|
||||
uint32_t cells = 0;
|
||||
|
||||
if (!card || !card->dev || !card->dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
np = card->dev->of_node;
|
||||
|
||||
if (!of_get_property(np, "qcom,ext-mclk-srcs", &len)) {
|
||||
dev_err(card->dev, "%s: ext mclk srcs cfg not found in DT\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "#ext-mclk-srcs-cells", &cells);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: ext mclk srcs cells not found in DT\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!len || (len % (cells * sizeof(uint32_t))) ||
|
||||
(cells != MCLK_SRCS_CELLS)) {
|
||||
dev_err(card->dev, "%s: invalid ext mclk srcs cfg in DT\n", __func__);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
num_srcs = len / (cells * sizeof(uint32_t));
|
||||
|
||||
src_cfg = devm_kzalloc(card->dev,
|
||||
num_srcs * sizeof(struct ext_mclk_src_cfg),
|
||||
GFP_KERNEL);
|
||||
if (!src_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32_array(np, "qcom,ext-mclk-srcs", (u32 *)src_cfg,
|
||||
cells * num_srcs);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: could not find %s entry in dt\n",
|
||||
__func__, "qcom,ext-mclk-srcs");
|
||||
ret = -EINVAL;
|
||||
goto free_mclk_array;
|
||||
}
|
||||
|
||||
*ext_mclk_src = src_cfg;
|
||||
*n_srcs = num_srcs;
|
||||
dev_dbg(card->dev, "%s: ext mclk srcs probe successful\n", __func__);
|
||||
return 0;
|
||||
|
||||
free_mclk_array:
|
||||
devm_kfree(card->dev, src_cfg);
|
||||
src_cfg = NULL;
|
||||
|
||||
*ext_mclk_src = NULL;
|
||||
*n_srcs = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_parse_dt_ext_mclk_cfg(struct snd_soc_card *card,
|
||||
enum afe_mclk_freq freq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ext_mclk_freq_cfg *mclk_cfg = NULL;
|
||||
uint32_t len = 0;
|
||||
uint32_t num_cfg = 0;
|
||||
uint32_t cells = 0;
|
||||
int i = 0;
|
||||
struct device_node *np = NULL;
|
||||
uint32_t *freq_cfg_tbl = NULL;
|
||||
|
||||
if (!card || !card->dev || !card->dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
np = card->dev->of_node;
|
||||
|
||||
if (!of_get_property(np, ext_mclk_freq_info[freq].prop, &len)) {
|
||||
dev_dbg(card->dev, "%s: ext mclk cfg for %s not found in DT\n",
|
||||
__func__, ext_mclk_freq_info[freq].prop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "#ext-mclk-cfg-cells", &cells);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: ext mclk cfg cells not found in DT\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!len || (len % (cells * sizeof(uint32_t))) ||
|
||||
(cells != MCLK_CFG_CELLS)) {
|
||||
dev_err(card->dev, "%s: invalid mclk configuration in DT\n", __func__);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
num_cfg = len / (cells * sizeof(uint32_t));
|
||||
mclk_cfg = devm_kzalloc(card->dev, num_cfg * sizeof(struct ext_mclk_freq_cfg),
|
||||
GFP_KERNEL);
|
||||
if (!mclk_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
freq_cfg_tbl = devm_kzalloc(card->dev, cells * num_cfg * sizeof(uint32_t),
|
||||
GFP_KERNEL);
|
||||
if (!freq_cfg_tbl) {
|
||||
ret = -ENOMEM;
|
||||
goto free_mclk_cfg;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(np, ext_mclk_freq_info[freq].prop,
|
||||
freq_cfg_tbl, cells * num_cfg);
|
||||
if (ret)
|
||||
goto free_freq_cfg_tbl;
|
||||
|
||||
dev_dbg(card->dev, "table for %u freq\n",
|
||||
ext_mclk_freq_info[freq].mclk_freq);
|
||||
|
||||
for (i = 0; i < num_cfg; i++) {
|
||||
memcpy(&mclk_cfg[i], &freq_cfg_tbl[i * cells],
|
||||
sizeof(uint32_t) * cells);
|
||||
dev_dbg(card->dev,
|
||||
"clk freq (Hz): %u, div2x: %u, m: %u, n: %u, d: %u\n",
|
||||
mclk_cfg[i].clk_freq, mclk_cfg[i].div2x, mclk_cfg[i].m,
|
||||
mclk_cfg[i].n, mclk_cfg[i].d);
|
||||
}
|
||||
|
||||
ext_mclk_freq_info[freq].mclk_cfg = mclk_cfg;
|
||||
ext_mclk_freq_info[freq].num_mclk_cfg = num_cfg;
|
||||
|
||||
devm_kfree(card->dev, freq_cfg_tbl);
|
||||
freq_cfg_tbl = NULL;
|
||||
|
||||
return 0;
|
||||
|
||||
free_freq_cfg_tbl:
|
||||
devm_kfree(card->dev, freq_cfg_tbl);
|
||||
freq_cfg_tbl = NULL;
|
||||
free_mclk_cfg:
|
||||
devm_kfree(card->dev, mclk_cfg);
|
||||
mclk_cfg = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_parse_ext_mclk_freq_cfg(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = MCLK_FREQ_MIN;
|
||||
|
||||
if (!card || !card->dev || !card->dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = MCLK_FREQ_MIN; i < MCLK_FREQ_MAX; i++) {
|
||||
ret = msm_parse_dt_ext_mclk_cfg(card, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(card->dev, "%s: ext mclk freq probe successful!\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lahaina_ext_mclk_cfg_deinit(struct snd_soc_card *card)
|
||||
{
|
||||
struct msm_asoc_mach_data *pdata = NULL;
|
||||
int i = 0;
|
||||
enum afe_mclk_freq freq = MCLK_FREQ_MIN;
|
||||
|
||||
if (!card || !card->dev)
|
||||
return;
|
||||
|
||||
pdata = (struct msm_asoc_mach_data *) snd_soc_card_get_drvdata(card);
|
||||
if (!pdata)
|
||||
return;
|
||||
|
||||
afe_unregister_ext_mclk_cb();
|
||||
|
||||
for (i = 0; i < pdata->num_ext_mclk_srcs; i++)
|
||||
pdata->ext_mclk_srcs[i].gpio_info = NULL;
|
||||
|
||||
pdata->num_ext_mclk_srcs = 0;
|
||||
|
||||
if (ext_mclk_gpio_info) {
|
||||
for (i = 0; i < num_ext_mclk_gpios; i++) {
|
||||
mutex_destroy(&ext_mclk_gpio_info[i].lock);
|
||||
of_node_put(ext_mclk_gpio_info[i].gpio_p);
|
||||
}
|
||||
devm_kfree(card->dev, ext_mclk_gpio_info);
|
||||
ext_mclk_gpio_info = NULL;
|
||||
}
|
||||
|
||||
if (ext_mclk_src_info) {
|
||||
devm_kfree(card->dev, ext_mclk_src_info);
|
||||
ext_mclk_src_info = NULL;
|
||||
}
|
||||
|
||||
for (freq = MCLK_FREQ_MIN; freq < MCLK_FREQ_MAX; freq++) {
|
||||
if (ext_mclk_freq_info[freq].mclk_cfg)
|
||||
devm_kfree(card->dev, ext_mclk_freq_info[freq].mclk_cfg);
|
||||
ext_mclk_freq_info[freq].mclk_cfg = NULL;
|
||||
ext_mclk_freq_info[freq].num_mclk_cfg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int lahaina_ext_mclk_init_controls(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!card) {
|
||||
pr_err("%s: sound card is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snd_soc_add_card_controls(card, msm_ext_mclk_controls,
|
||||
ARRAY_SIZE(msm_ext_mclk_controls));
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "%s: add_card_controls failed for ext mclk ctls: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lahaina_ext_mclk_cfg_init(struct snd_soc_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_asoc_mach_data *pdata = NULL;
|
||||
uint32_t num_ext_mclk_srcs = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!card || !card->dev || !card->dev->of_node)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = (struct msm_asoc_mach_data *) snd_soc_card_get_drvdata(card);
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
ret = msm_parse_ext_mclk_gpios(card, &ext_mclk_gpio_info);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: unable to parse ext mclk gpios, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
ret = msm_parse_ext_mclk_srcs(card, &ext_mclk_src_info,
|
||||
&num_ext_mclk_srcs);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: unable to parse ext mclk srcs, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
ret = msm_parse_ext_mclk_freq_cfg(card);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: unable to parse ext mclk freq cfg, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
pdata->num_ext_mclk_srcs = num_ext_mclk_srcs;
|
||||
|
||||
if (pdata->num_ext_mclk_srcs) {
|
||||
pdata->ext_mclk_srcs = devm_kzalloc(card->dev,
|
||||
num_ext_mclk_srcs * sizeof(struct ext_mclk_src_info),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->ext_mclk_srcs) {
|
||||
pdata->num_ext_mclk_srcs = 0;
|
||||
ret = -ENOMEM;
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ext_mclk_srcs; i++) {
|
||||
pdata->ext_mclk_srcs[i].clk_id = ext_mclk_src_info[i].clk_id;
|
||||
pdata->ext_mclk_srcs[i].clk_root = ext_mclk_src_info[i].clk_root;
|
||||
pdata->ext_mclk_srcs[i].gpio_info = &ext_mclk_gpio_info[ext_mclk_src_info[i].gpio_idx];
|
||||
|
||||
dev_dbg(card->dev, "%s: clk id: 0x%x clk root: 0x%x gpio idx: %d\n",
|
||||
__func__, pdata->ext_mclk_srcs[i].clk_id,
|
||||
pdata->ext_mclk_srcs[i].clk_root,
|
||||
ext_mclk_src_info[i].gpio_idx);
|
||||
}
|
||||
|
||||
ret = lahaina_ext_mclk_init_controls(card);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: Could not init ext mclk mixer ctls, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
ret = afe_register_ext_mclk_cb(lahaina_enable_and_get_mclk_cfg,
|
||||
(void *)card);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "%s: Could not register afe ext mclk cb, ret: %d\n",
|
||||
__func__, ret);
|
||||
goto deinit;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(card->dev, "%s: ext mclk init successful!\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
deinit:
|
||||
lahaina_ext_mclk_cfg_deinit(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_asoc_machine_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = NULL;
|
||||
|
|
@ -8864,15 +9555,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* Get maximum WSA device count for this platform */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,wsa-max-devs", &pdata->wsa_max_devs);
|
||||
if (ret) {
|
||||
dev_info(&pdev->dev,
|
||||
"%s: wsa-max-devs property missing in DT %s, ret = %d\n",
|
||||
__func__, pdev->dev.of_node->full_name, ret);
|
||||
pdata->wsa_max_devs = 0;
|
||||
}
|
||||
/* Get maximum WSA device count for this platform */
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,wsa-max-devs", &pdata->wsa_max_devs);
|
||||
if (ret) {
|
||||
dev_info(&pdev->dev,
|
||||
"%s: wsa-max-devs property missing in DT %s, ret = %d\n",
|
||||
__func__, pdev->dev.of_node->full_name, ret);
|
||||
pdata->wsa_max_devs = 0;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
|
|
@ -8887,6 +9578,19 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|||
dev_info(&pdev->dev, "%s: Sound card %s registered\n",
|
||||
__func__, card->name);
|
||||
|
||||
/* Enable ext clk support ONLY after sound card enumeration and
|
||||
* registration has occurred with the internal clock
|
||||
*/
|
||||
if (of_property_read_bool(pdev->dev.of_node, "qcom,supports-ext-mclk")) {
|
||||
ret = lahaina_ext_mclk_cfg_init(card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: ext mclk cfg init from DT failed: %d\n",
|
||||
__func__, ret);
|
||||
goto err;
|
||||
}
|
||||
pdata->supports_ext_mclk = 1;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "qcom,tdm-max-slots",
|
||||
&pdata->tdm_max_slots);
|
||||
if (ret) {
|
||||
|
|
@ -9029,7 +9733,11 @@ err:
|
|||
static int msm_asoc_machine_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct msm_asoc_mach_data *pdata = NULL;
|
||||
|
||||
pdata = snd_soc_card_get_drvdata(card);
|
||||
if (pdata && pdata->supports_ext_mclk)
|
||||
lahaina_ext_mclk_cfg_deinit(card);
|
||||
snd_event_master_deregister(&pdev->dev);
|
||||
snd_soc_unregister_card(card);
|
||||
msm_i2s_auxpcm_deinit();
|
||||
|
|
|
|||
60
techpack/audio/asoc/msm-common.c
Normal file
60
techpack/audio/asoc/msm-common.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/info.h>
|
||||
|
||||
#include "msm-common.h"
|
||||
|
||||
int msm_lpass_audio_hw_vote_req(struct snd_pcm_substream *substream, bool enable)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
||||
int rc = 0;
|
||||
|
||||
if (enable) {
|
||||
if (pdata->lpass_audio_hw_vote == NULL) {
|
||||
dev_err(rtd->card->dev, "%s: Invalid lpass audio hw node\n",
|
||||
__func__);
|
||||
rc = -EINVAL;
|
||||
goto rtn;
|
||||
}
|
||||
if (pdata->core_audio_vote_count == 0) {
|
||||
rc = clk_prepare_enable(pdata->lpass_audio_hw_vote);
|
||||
if (rc < 0) {
|
||||
dev_err(rtd->card->dev, "%s: audio vote error\n",
|
||||
__func__);
|
||||
goto rtn;
|
||||
}
|
||||
}
|
||||
|
||||
pdata->core_audio_vote_count++;
|
||||
} else {
|
||||
if (pdata->lpass_audio_hw_vote != NULL) {
|
||||
if (--pdata->core_audio_vote_count == 0) {
|
||||
clk_disable_unprepare(
|
||||
pdata->lpass_audio_hw_vote);
|
||||
} else if (pdata->core_audio_vote_count < 0) {
|
||||
pr_err("%s: audio vote mismatch\n", __func__);
|
||||
pdata->core_audio_vote_count = 0;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: Invalid lpass audio hw node\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
rtn:
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_lpass_audio_hw_vote_req);
|
||||
|
||||
52
techpack/audio/asoc/msm-common.h
Normal file
52
techpack/audio/asoc/msm-common.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_COMMON_H_
|
||||
#define _MSM_COMMON_H_
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <dsp/apr_audio-v2.h>
|
||||
|
||||
enum {
|
||||
PRIM_MI2S = 0,
|
||||
SEC_MI2S,
|
||||
TERT_MI2S,
|
||||
QUAT_MI2S,
|
||||
QUIN_MI2S,
|
||||
SEN_MI2S,
|
||||
MI2S_MAX,
|
||||
};
|
||||
|
||||
struct msm_asoc_mach_data {
|
||||
struct snd_info_entry *codec_root;
|
||||
int usbc_en2_gpio; /* used by gpio driver API */
|
||||
int lito_v2_enabled;
|
||||
struct device_node *dmic01_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *dmic23_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *dmic45_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
|
||||
atomic_t mi2s_gpio_ref_count[MI2S_MAX]; /* used by pinctrl API */
|
||||
struct device_node *us_euro_gpio_p; /* used by pinctrl API */
|
||||
struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
|
||||
struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
|
||||
bool supports_ext_mclk;
|
||||
struct ext_mclk_src_info *ext_mclk_srcs;
|
||||
u32 num_ext_mclk_srcs;
|
||||
bool is_afe_config_done;
|
||||
struct device_node *fsa_handle;
|
||||
struct clk *lpass_audio_hw_vote;
|
||||
int core_audio_vote_count;
|
||||
u32 wsa_max_devs;
|
||||
u32 tdm_max_slots; /* Max TDM slots used */
|
||||
int wcd_disabled;
|
||||
int (*get_wsa_dev_num)(struct snd_soc_component*);
|
||||
struct afe_cps_hw_intf_cfg cps_config;
|
||||
};
|
||||
|
||||
int msm_lpass_audio_hw_vote_req(struct snd_pcm_substream *substream, bool enable);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,39 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Changes from Qualcomm Innovation Center are provided under the following license:
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the
|
||||
* disclaimer below) provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of Qualcomm Innovation Center, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
|
||||
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
|
||||
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -5219,8 +5186,13 @@ static int msm_compr_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
if (prtd && prtd->audio_client) {
|
||||
stream_id = prtd->audio_client->session;
|
||||
be_id = chmixer_pspd->port_idx;
|
||||
#ifdef CONFIG_PLATFORM_AUTO
|
||||
msm_pcm_routing_set_channel_mixer_runtime(fe_id, be_id,
|
||||
stream_id, session_type, chmixer_pspd);
|
||||
#else
|
||||
msm_pcm_routing_set_channel_mixer_runtime(be_id,
|
||||
stream_id, session_type, chmixer_pspd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
enum {
|
||||
DP_CONTROLLER0 = 0,
|
||||
DP_CONTROLLER1,
|
||||
HDMI_CONTROLLER,
|
||||
DP_CONTROLLER_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,18 @@
|
|||
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
#define SAMPLING_RATE_11P025KHZ 11025
|
||||
#define SAMPLING_RATE_22P05KHZ 22050
|
||||
#define SAMPLING_RATE_44P1KHZ 44100
|
||||
#define SAMPLING_RATE_88P2KHZ 88200
|
||||
#define SAMPLING_RATE_176P4KHZ 176400
|
||||
#define SAMPLING_RATE_352P8KHZ 352800
|
||||
|
||||
#define IS_TDM_INTERFACE(x) \
|
||||
((x >= AFE_PORT_ID_TDM_PORT_RANGE_START) && (x < AFE_PORT_ID_TDM_PORT_RANGE_END))
|
||||
|
||||
static int msm_mi2s_get_port_id(u32 mi2s_id, int stream, u16 *port_id);
|
||||
int msm_lpass_audio_hw_vote_req(struct snd_pcm_substream *substream, bool enable);
|
||||
|
||||
enum {
|
||||
ENC_FMT_NONE,
|
||||
|
|
@ -300,6 +311,11 @@ enum {
|
|||
IDX_GROUP_TDM_MAX,
|
||||
};
|
||||
|
||||
#define IS_FRACTIONAL(x) \
|
||||
((x == SAMPLING_RATE_11P025KHZ) || (x == SAMPLING_RATE_22P05KHZ) || \
|
||||
(x == SAMPLING_RATE_44P1KHZ) || (x == SAMPLING_RATE_88P2KHZ) || \
|
||||
(x == SAMPLING_RATE_176P4KHZ) || (x == SAMPLING_RATE_352P8KHZ))
|
||||
|
||||
struct msm_dai_q6_dai_data {
|
||||
DECLARE_BITMAP(status_mask, STATUS_MAX);
|
||||
DECLARE_BITMAP(hwfree_status, STATUS_MAX);
|
||||
|
|
@ -11665,6 +11681,9 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
struct msm_dai_q6_tdm_dai_data *dai_data =
|
||||
dev_get_drvdata(dai->dev);
|
||||
u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int index = rtd->cpu_dai->id;
|
||||
int sample_rate = dai_data->rate;
|
||||
int group_idx = 0;
|
||||
atomic_t *group_ref = NULL;
|
||||
int intf_idx = PORT_ID_TO_INTF_IDX(dai->id);
|
||||
|
|
@ -11688,6 +11707,15 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
group_ref = &tdm_group_ref[group_idx];
|
||||
|
||||
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
if (IS_TDM_INTERFACE(index) && (IS_FRACTIONAL(sample_rate))) {
|
||||
rc = msm_lpass_audio_hw_vote_req(substream, true);
|
||||
if (rc < 0) {
|
||||
dev_err(dai->dev, "%s: fail to enable audio hw clk 0x%x\n",
|
||||
__func__, dai->id);
|
||||
goto rtn;
|
||||
}
|
||||
}
|
||||
|
||||
if (msm_dai_q6_get_tdm_clk_ref(group_idx) == 0) {
|
||||
/* TX and RX share the same clk. So enable the clk
|
||||
* per TDM interface. */
|
||||
|
|
@ -11746,6 +11774,9 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
msm_dai_q6_tdm_set_clk(dai_data,
|
||||
dai->id, false);
|
||||
}
|
||||
if (IS_TDM_INTERFACE(index) && (IS_FRACTIONAL(sample_rate)))
|
||||
msm_lpass_audio_hw_vote_req(substream, false);
|
||||
|
||||
dev_err(dai->dev, "%s: fail to open AFE port 0x%x\n",
|
||||
__func__, dai->id);
|
||||
} else {
|
||||
|
|
@ -11775,6 +11806,10 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream,
|
|||
int group_idx = 0;
|
||||
atomic_t *group_ref = NULL;
|
||||
int intf_idx = PORT_ID_TO_INTF_IDX(dai->id);
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int index = cpu_dai->id;
|
||||
int sample_rate = dai_data->rate;
|
||||
|
||||
group_idx = msm_dai_q6_get_group_idx(dai->id);
|
||||
if (group_idx < 0) {
|
||||
|
|
@ -11831,6 +11866,9 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream,
|
|||
|
||||
}
|
||||
|
||||
if (IS_TDM_INTERFACE(index) && (IS_FRACTIONAL(sample_rate)))
|
||||
msm_lpass_audio_hw_vote_req(substream, false);
|
||||
|
||||
mutex_unlock(&tdm_mutex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
|
|
@ -879,6 +879,13 @@ static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
|
|||
|
||||
if (p_info->model_id != 0 &&
|
||||
p_info->param_type == LSM_DEREG_MULTI_SND_MODEL) {
|
||||
|
||||
if(list_empty(&client->stage_cfg[p_info->stage_idx].sound_models)) {
|
||||
pr_err("%s: sound_models list is empty \n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(sm,
|
||||
&client->stage_cfg[p_info->stage_idx].sound_models,
|
||||
list) {
|
||||
|
|
@ -2379,8 +2386,13 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|||
prtd->lsm_client->get_param_payload = NULL;
|
||||
goto done;
|
||||
}
|
||||
if (__builtin_uadd_overflow(sizeof(p_info_32), p_info_32.param_size, &size)) {
|
||||
pr_err("%s: param size exceeds limit of %u bytes.\n",
|
||||
__func__, UINT_MAX);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
size = sizeof(p_info_32) + p_info_32.param_size;
|
||||
param_info_rsp = kzalloc(size, GFP_KERNEL);
|
||||
|
||||
if (!param_info_rsp) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Add support for 24 and 32bit format for ASM loopback and playback session.
|
||||
|
|
@ -1022,10 +1022,17 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
if (prtd->audio_client) {
|
||||
stream_id = prtd->audio_client->session;
|
||||
be_id = chmixer_pspd->port_idx;
|
||||
#ifdef CONFIG_PLATFORM_AUTO
|
||||
msm_pcm_routing_set_channel_mixer_runtime(fe_id, be_id,
|
||||
stream_id,
|
||||
session_type,
|
||||
chmixer_pspd);
|
||||
#else
|
||||
msm_pcm_routing_set_channel_mixer_runtime(be_id,
|
||||
stream_id,
|
||||
session_type,
|
||||
chmixer_pspd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
mutex_unlock(&loopback_session_lock);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Add support for 24 and 32bit format for ASM loopback and playback session.
|
||||
|
|
@ -1329,7 +1329,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
|
|||
offset = prtd->in_frame_info[idx].offset;
|
||||
pr_debug("Offset value = %d\n", offset);
|
||||
|
||||
if (offset >= size) {
|
||||
if (size && offset >= size) {
|
||||
pr_err("%s: Invalid dsp buf offset\n", __func__);
|
||||
ret = -EFAULT;
|
||||
q6asm_cpu_buf_release(OUT, prtd->audio_client);
|
||||
|
|
@ -2681,10 +2681,17 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
if (chmixer_pspd->enable && prtd && prtd->audio_client) {
|
||||
stream_id = prtd->audio_client->session;
|
||||
be_id = chmixer_pspd->port_idx;
|
||||
#ifdef CONFIG_PLATFORM_AUTO
|
||||
msm_pcm_routing_set_channel_mixer_runtime(fe_id, be_id,
|
||||
stream_id,
|
||||
session_type,
|
||||
chmixer_pspd);
|
||||
#else
|
||||
msm_pcm_routing_set_channel_mixer_runtime(be_id,
|
||||
stream_id,
|
||||
session_type,
|
||||
chmixer_pspd);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (reset_override_out_ch_map)
|
||||
|
|
|
|||
|
|
@ -2361,6 +2361,7 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
|
|||
* msm_pcm_routing_set_channel_mixer_runtime - apply channel mixer
|
||||
* setting during runtime.
|
||||
*
|
||||
* @fe_id: frontend index
|
||||
* @be_id: backend index
|
||||
* @session_id: session index
|
||||
* @session_type: session type
|
||||
|
|
@ -2368,12 +2369,13 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
|
|||
*
|
||||
* Retuen: 0 for success, else error
|
||||
*/
|
||||
int msm_pcm_routing_set_channel_mixer_runtime(int be_id, int session_id,
|
||||
int msm_pcm_routing_set_channel_mixer_runtime(int fe_id, int be_id, int session_id,
|
||||
int session_type,
|
||||
struct msm_pcm_channel_mixer *params)
|
||||
{
|
||||
int rc = 0;
|
||||
int port_id, copp_idx = 0;
|
||||
bool tmp = false;
|
||||
|
||||
be_id--;
|
||||
if (be_id < 0 || be_id >= MSM_BACKEND_DAI_MAX) {
|
||||
|
|
@ -2382,8 +2384,13 @@ int msm_pcm_routing_set_channel_mixer_runtime(int be_id, int session_id,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
port_id = msm_bedais[be_id].port_id;
|
||||
copp_idx = adm_get_default_copp_idx(port_id);
|
||||
tmp = msm_pcm_routing_get_portid_copp_idx(fe_id, session_type, &port_id, &copp_idx);
|
||||
|
||||
if(!tmp){
|
||||
pr_err("%s: Could not find copp_idx for fe_id: %d, will use default copp_idx\n",
|
||||
__func__, fe_id);
|
||||
copp_idx = adm_get_default_copp_idx(port_id);
|
||||
}
|
||||
pr_debug("%s: port_id - %d, copp_idx %d session id - %d\n",
|
||||
__func__, port_id, copp_idx, session_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,10 @@ static int afe_loopback_tx_port_id = -1;
|
|||
static struct msm_pcm_channel_mixer ec_ref_chmix_cfg[MSM_FRONTEND_DAI_MAX];
|
||||
static struct msm_ec_ref_port_cfg ec_ref_port_cfg;
|
||||
|
||||
static int32_t mclk_cfg_be_idx;
|
||||
static int32_t mclk_cfg_src_id;
|
||||
static uint32_t mclk_cfg_freq;
|
||||
|
||||
#define WEIGHT_0_DB 0x4000
|
||||
/* all the FEs which can support channel mixer */
|
||||
static struct msm_pcm_channel_mixer channel_mixer[MSM_FRONTEND_DAI_MM_SIZE];
|
||||
|
|
@ -30766,6 +30770,10 @@ static const struct snd_kcontrol_new wsa_cdc_dma_rx_0_port_mixer_controls[] = {
|
|||
MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
|
||||
MSM_BACKEND_DAI_TX_CDC_DMA_TX_3, 1, 0, msm_routing_get_port_mixer,
|
||||
msm_routing_put_port_mixer),
|
||||
SOC_DOUBLE_EXT("SLIM_7_TX", SND_SOC_NOPM,
|
||||
MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
|
||||
MSM_BACKEND_DAI_SLIMBUS_7_TX, 1, 0, msm_routing_get_port_mixer,
|
||||
msm_routing_put_port_mixer),
|
||||
SOC_DOUBLE_EXT("SLIM_8_TX", SND_SOC_NOPM,
|
||||
MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
|
||||
MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
|
||||
|
|
@ -36837,6 +36845,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
{"SLIM1_UL_HL", NULL, "SLIMBUS_1_TX"},
|
||||
{"SLIM3_UL_HL", NULL, "SLIMBUS_3_TX"},
|
||||
{"SLIM4_UL_HL", NULL, "SLIMBUS_4_TX"},
|
||||
{"SLIM7_UL_HL", NULL, "SLIMBUS_7_TX"},
|
||||
{"SLIM8_UL_HL", NULL, "SLIMBUS_8_TX"},
|
||||
{"WSA_CDC_DMA_RX_0_DL_HL", "Switch", "CDC_DMA_DL_HL"},
|
||||
{"WSA_CDC_DMA_RX_0", NULL, "WSA_CDC_DMA_RX_0_DL_HL"},
|
||||
|
|
@ -36962,6 +36971,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
/* connect to INT4_MI2S_DL_HL since same pcm_id */
|
||||
{"WSA_CDC_DMA_RX_0 Port Mixer", "VA_CDC_DMA_TX_0", "VA_CDC_DMA_TX_0"},
|
||||
{"WSA_CDC_DMA_RX_0 Port Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
|
||||
{"WSA_CDC_DMA_RX_0 Port Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
|
||||
{"WSA_CDC_DMA_RX_0 Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
|
||||
{"WSA_CDC_DMA_RX_0", NULL, "WSA_CDC_DMA_RX_0 Port Mixer"},
|
||||
|
||||
|
|
@ -42813,6 +42823,16 @@ static const struct snd_kcontrol_new
|
|||
},
|
||||
};
|
||||
|
||||
static int msm_routing_get_mclk_src_cfg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = mclk_cfg_be_idx;
|
||||
ucontrol->value.integer.value[1] = mclk_cfg_src_id;
|
||||
ucontrol->value.integer.value[2] = mclk_cfg_freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_routing_put_mclk_src_cfg(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
|
@ -42825,6 +42845,10 @@ static int msm_routing_put_mclk_src_cfg(struct snd_kcontrol *kcontrol,
|
|||
mclk_src_id = ucontrol->value.integer.value[1];
|
||||
mclk_freq = ucontrol->value.integer.value[2];
|
||||
|
||||
mclk_cfg_be_idx = be_idx;
|
||||
mclk_cfg_src_id = mclk_src_id;
|
||||
mclk_cfg_freq = mclk_freq;
|
||||
|
||||
if (be_idx < 0 || be_idx >= MSM_BACKEND_DAI_MAX) {
|
||||
pr_err("%s: Invalid be id %d\n", __func__, be_idx);
|
||||
return -EINVAL;
|
||||
|
|
@ -42854,7 +42878,8 @@ static int msm_routing_put_mclk_src_cfg(struct snd_kcontrol *kcontrol,
|
|||
|
||||
static const struct snd_kcontrol_new mclk_src_controls[] = {
|
||||
SOC_SINGLE_MULTI_EXT("MCLK_SRC CFG", SND_SOC_NOPM, 0, 24576000, 0, 3,
|
||||
NULL, msm_routing_put_mclk_src_cfg),
|
||||
msm_routing_get_mclk_src_cfg,
|
||||
msm_routing_put_mclk_src_cfg),
|
||||
};
|
||||
|
||||
static int msm_routing_stereo_channel_reverse_control_get(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Add support for 24 and 32bit format for ASM loopback and playback session.
|
||||
|
|
@ -818,10 +818,17 @@ int msm_pcm_routing_set_channel_mixer_cfg(
|
|||
int fe_id, int session_type,
|
||||
struct msm_pcm_channel_mixer *params);
|
||||
|
||||
#ifdef CONFIG_PLATFORM_AUTO
|
||||
int msm_pcm_routing_set_channel_mixer_runtime(
|
||||
int be_id, int session_id,
|
||||
int fe_id, int be_id, int session_id,
|
||||
int session_type,
|
||||
struct msm_pcm_channel_mixer *params);
|
||||
#else
|
||||
int msm_pcm_routing_set_channel_mixer_runtime(
|
||||
int be_id, int session_id,
|
||||
int session_type,
|
||||
struct msm_pcm_channel_mixer *params);
|
||||
#endif
|
||||
|
||||
int msm_pcm_routing_set_stream_ec_ref_chmix_cfg(
|
||||
int fedai_id, struct msm_pcm_channel_mixer *cfg_data);
|
||||
|
|
|
|||
|
|
@ -1713,16 +1713,11 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
|
|||
if (data->opcode == APR_BASIC_RSP_RESULT) {
|
||||
pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
|
||||
__func__, payload[0]);
|
||||
|
||||
if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
|
||||
((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
|
||||
(payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
|
||||
if (data->payload_size <
|
||||
(2 * sizeof(uint32_t))) {
|
||||
pr_err("%s: Invalid payload size %d\n",
|
||||
__func__, data->payload_size);
|
||||
return 0;
|
||||
}
|
||||
if (data->payload_size <
|
||||
(2 * sizeof(uint32_t))) {
|
||||
pr_err("%s: Invalid payload size %d\n",
|
||||
__func__, data->payload_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (payload[1] != 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
|
@ -785,8 +785,14 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
|
||||
switch (param_hdr.param_id) {
|
||||
case AFE_PARAM_ID_CALIB_RES_CFG_V2:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(struct asm_calib_res_cfg);
|
||||
if (param_hdr.param_size != sizeof(struct asm_calib_res_cfg)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (sizeof(struct asm_calib_res_cfg) - ((2 - num_ch) * 4))) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -794,8 +800,14 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
data_dest = (u32 *) &this_afe.calib_data;
|
||||
break;
|
||||
case AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(struct afe_sp_th_vi_ftm_params);
|
||||
if (param_hdr.param_size != sizeof(struct afe_sp_th_vi_ftm_params)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (sizeof(struct afe_sp_th_vi_ftm_params) - ((2 - num_ch) * 4 * 3))) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -803,8 +815,14 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
data_dest = (u32 *) &this_afe.th_vi_resp;
|
||||
break;
|
||||
case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(struct afe_sp_th_vi_v_vali_params);
|
||||
if (param_hdr.param_size != sizeof(struct afe_sp_th_vi_v_vali_params)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (sizeof(struct afe_sp_th_vi_v_vali_params) - ((2 - num_ch) * 4 * 2))) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -812,8 +830,14 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
data_dest = (u32 *) &this_afe.th_vi_v_vali_resp;
|
||||
break;
|
||||
case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(struct afe_sp_ex_vi_ftm_params);
|
||||
if (param_hdr.param_size != sizeof(struct afe_sp_ex_vi_ftm_params)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (sizeof(struct afe_sp_ex_vi_ftm_params) - ((2 - num_ch) * 4 * 4))) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -821,9 +845,15 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
data_dest = (u32 *) &this_afe.ex_vi_resp;
|
||||
break;
|
||||
case AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(
|
||||
struct afe_sp_rx_tmax_xmax_logging_param);
|
||||
if (param_hdr.param_size != sizeof(struct afe_sp_rx_tmax_xmax_logging_param)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (num_ch * sizeof(struct afe_sp_rx_tmax_xmax_logging_param))) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -831,10 +861,16 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
data_dest = (u32 *) &this_afe.xt_logging_resp;
|
||||
break;
|
||||
case AFE_PARAM_ID_SP_V4_CALIB_RES_CFG:
|
||||
num_ch = data_start[0];
|
||||
expected_size += sizeof(
|
||||
struct afe_sp_v4_param_th_vi_calib_res_cfg);
|
||||
if (param_hdr.param_size != sizeof(
|
||||
struct afe_sp_v4_param_th_vi_calib_res_cfg)) {
|
||||
if (num_ch > SP_V2_NUM_MAX_SPKRS) {
|
||||
pr_err("%s: Error: num_ch %d is greater than expected\n",
|
||||
__func__,num_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (param_hdr.param_size != (sizeof(
|
||||
struct afe_sp_v4_param_th_vi_calib_res_cfg) - (2 - num_ch) * 4)) {
|
||||
pr_err("%s: Error: param_size %d is greater than expected\n",
|
||||
__func__,param_hdr.param_size);
|
||||
return -EINVAL;
|
||||
|
|
@ -9858,8 +9894,8 @@ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
|
|||
}
|
||||
EXPORT_SYMBOL(afe_set_pll_clk_drift);
|
||||
|
||||
static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
||||
uint32_t mclk_freq)
|
||||
int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
||||
uint32_t mclk_freq)
|
||||
{
|
||||
struct param_hdr_v3 param_hdr;
|
||||
struct afe_param_id_clock_set_v2_t dyn_mclk_cfg;
|
||||
|
|
@ -9871,6 +9907,12 @@ static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!afe_ext_mclk.ext_mclk_cb) {
|
||||
pr_debug("%s: ext_mclk_cb not registered; platform doesn't support ext clk\n",
|
||||
__func__);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= AFE_MAX_PORTS) {
|
||||
pr_err("%s: index[%d] invalid!\n", __func__, index);
|
||||
return -EINVAL;
|
||||
|
|
@ -9883,34 +9925,33 @@ static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
|||
param_hdr.param_size = sizeof(struct afe_param_id_clock_set_v2_t);
|
||||
|
||||
memset(&dyn_mclk_cfg, 0, sizeof(dyn_mclk_cfg));
|
||||
dyn_mclk_cfg.clk_freq_in_hz = cfg->clk_freq_in_hz;
|
||||
if (afe_ext_mclk.ext_mclk_cb) {
|
||||
ret = afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
|
||||
cfg->enable, mclk_freq, &dyn_mclk_cfg);
|
||||
if (ret) {
|
||||
pr_err_ratelimited("%s: get mclk cfg failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
pr_err_ratelimited("%s: mclk callback not registered\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dyn_mclk_cfg.clk_freq_in_hz = cfg->clk_freq_in_hz;
|
||||
dyn_mclk_cfg.clk_set_minor_version = 1;
|
||||
dyn_mclk_cfg.clk_id = cfg->clk_id;
|
||||
dyn_mclk_cfg.clk_attri = cfg->clk_attri;
|
||||
dyn_mclk_cfg.enable = cfg->enable;
|
||||
pr_debug("%s: Minor version =0x%x clk id = %d\n", __func__,
|
||||
dyn_mclk_cfg.clk_set_minor_version, dyn_mclk_cfg.clk_id);
|
||||
dyn_mclk_cfg.clk_set_minor_version, dyn_mclk_cfg.clk_id);
|
||||
pr_debug("%s: clk freq (Hz) = %d, clk attri = 0x%x\n", __func__,
|
||||
dyn_mclk_cfg.clk_freq_in_hz, dyn_mclk_cfg.clk_attri);
|
||||
pr_debug("%s: clk root = 0x%x clk enable = 0x%x\n", __func__,
|
||||
dyn_mclk_cfg.clk_root, dyn_mclk_cfg.enable);
|
||||
pr_debug("%s: divider_2x =%d m = %d n = %d, d =%d\n", __func__,
|
||||
dyn_mclk_cfg.divider_2x, dyn_mclk_cfg.m, dyn_mclk_cfg.n,
|
||||
dyn_mclk_cfg.d);
|
||||
dyn_mclk_cfg.clk_freq_in_hz, dyn_mclk_cfg.clk_attri);
|
||||
pr_debug("%s: clk input freq (Hz) = %d clk enable = 0x%x\n", __func__,
|
||||
mclk_freq, dyn_mclk_cfg.enable);
|
||||
|
||||
if (dyn_mclk_cfg.enable) {
|
||||
/* callback to populate Div2x, M, N, D, clock root and enable GPIOs */
|
||||
ret = afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
|
||||
dyn_mclk_cfg.enable, mclk_freq, &dyn_mclk_cfg);
|
||||
if (ret) {
|
||||
pr_err_ratelimited("%s: mclk cb during enable failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_debug("%s: clk root = 0x%x divider_2x = %d m = %d n = %d d = %d\n",
|
||||
__func__, dyn_mclk_cfg.clk_root, dyn_mclk_cfg.divider_2x,
|
||||
dyn_mclk_cfg.m, dyn_mclk_cfg.n, dyn_mclk_cfg.d);
|
||||
}
|
||||
|
||||
ret = afe_q6_interface_prepare();
|
||||
if (ret != 0) {
|
||||
|
|
@ -9922,23 +9963,108 @@ static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
|||
mutex_lock(&this_afe.afe_cmd_lock);
|
||||
ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
|
||||
(u8 *) &dyn_mclk_cfg);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pr_err_ratelimited("%s: ext MCLK clk cfg failed with ret %d\n",
|
||||
__func__, ret);
|
||||
__func__, ret);
|
||||
mutex_unlock(&this_afe.afe_cmd_lock);
|
||||
goto stop_mclk;
|
||||
}
|
||||
|
||||
mutex_unlock(&this_afe.afe_cmd_lock);
|
||||
|
||||
if (!dyn_mclk_cfg.enable) {
|
||||
/* callback to disable GPIOs */
|
||||
ret = afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
|
||||
dyn_mclk_cfg.enable, mclk_freq, &dyn_mclk_cfg);
|
||||
if (ret) {
|
||||
pr_err_ratelimited("%s: mclk cb during disable failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
stop_mclk:
|
||||
if (afe_ext_mclk.ext_mclk_cb && cfg->enable) {
|
||||
afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
|
||||
cfg->enable, mclk_freq, &dyn_mclk_cfg);
|
||||
}
|
||||
dyn_mclk_cfg.enable = 0;
|
||||
afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
|
||||
dyn_mclk_cfg.enable, mclk_freq, &dyn_mclk_cfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(afe_set_lpass_clk_cfg_ext_mclk);
|
||||
|
||||
|
||||
int afe_set_lpass_ext_mclk_mux_cfg(const char *mux_str,
|
||||
uint32_t mux_val)
|
||||
{
|
||||
struct param_hdr_v3 param_hdr;
|
||||
struct afe_param_id_clock_mux_cfg_t clk_mux_cfg;
|
||||
uint32_t build_major_version = 0;
|
||||
uint32_t build_minor_version = 0;
|
||||
uint32_t build_branch_version = 0;
|
||||
int afe_api_version = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!mux_str) {
|
||||
pr_err("%s: mux_str is NULL\n", __func__);
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = q6core_get_avcs_avs_build_version_info(
|
||||
&build_major_version, &build_minor_version,
|
||||
&build_branch_version);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
afe_api_version = ret;
|
||||
pr_debug("%s: mjor: %u, mnor: %u, brnch: %u, afe_api: %u\n",
|
||||
__func__, build_major_version, build_minor_version,
|
||||
build_branch_version, afe_api_version);
|
||||
if ((build_major_version != AVS_BUILD_MAJOR_VERSION_V2) ||
|
||||
(build_minor_version != AVS_BUILD_MINOR_VERSION_V9) ||
|
||||
(build_branch_version != AVS_BUILD_BRANCH_VERSION_V0) ||
|
||||
(afe_api_version < AFE_API_VERSION_V11)) {
|
||||
pr_err("%s: AFE_PARAM_ID_CLOCK_MUX_CFG unsupported by AVS\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(¶m_hdr, 0, sizeof(param_hdr));
|
||||
param_hdr.module_id = AFE_MODULE_CLOCK_SET;
|
||||
param_hdr.instance_id = INSTANCE_ID_0;
|
||||
param_hdr.param_id = AFE_PARAM_ID_CLOCK_MUX_CFG;
|
||||
param_hdr.param_size = sizeof(struct afe_param_id_clock_mux_cfg_t);
|
||||
memset(&clk_mux_cfg, 0, sizeof(clk_mux_cfg));
|
||||
strlcpy(clk_mux_cfg.mux_string, mux_str, sizeof(clk_mux_cfg.mux_string));
|
||||
clk_mux_cfg.mux_value = mux_val;
|
||||
pr_debug("%s: ext mclk mux cfg - mux_string: %s, mux_value = %u\n", __func__,
|
||||
clk_mux_cfg.mux_string, clk_mux_cfg.mux_value);
|
||||
|
||||
ret = afe_q6_interface_prepare();
|
||||
if (ret != 0) {
|
||||
pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&this_afe.afe_cmd_lock);
|
||||
ret = q6afe_svc_pack_and_set_param_in_band(IDX_RSVD_3, param_hdr,
|
||||
(u8 *) &clk_mux_cfg);
|
||||
if (ret < 0) {
|
||||
pr_err_ratelimited("%s: ext mclk mux cfg failed with ret %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
mutex_unlock(&this_afe.afe_cmd_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(afe_set_lpass_ext_mclk_mux_cfg);
|
||||
|
||||
static int ext_dyn_mclk_port_id;
|
||||
static int ext_dyn_clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
|
||||
|
|
@ -10162,7 +10288,8 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
|
|||
build_branch_version, afe_api_version);
|
||||
if ((build_major_version != AVS_BUILD_MAJOR_VERSION_V2) ||
|
||||
(build_minor_version != AVS_BUILD_MINOR_VERSION_V9) ||
|
||||
(build_branch_version != AVS_BUILD_BRANCH_VERSION_V3) ||
|
||||
((build_branch_version != AVS_BUILD_BRANCH_VERSION_V0) &&
|
||||
(build_branch_version != AVS_BUILD_BRANCH_VERSION_V3)) ||
|
||||
(afe_api_version < AFE_API_VERSION_V8)) {
|
||||
pr_err("%s: ext mclk not supported by AVS\n", __func__);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -8843,6 +8843,8 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
|
|||
}
|
||||
mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
|
||||
mmap_region_cmd;
|
||||
|
||||
mutex_lock(&ac->cmd_lock);
|
||||
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, dir);
|
||||
atomic_set(&ac->mem_state, -1);
|
||||
pr_debug("%s: mmap_region=0x%pK token=0x%x\n", __func__,
|
||||
|
|
@ -8900,7 +8902,6 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
|
|||
buffer_node = NULL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
mutex_lock(&ac->cmd_lock);
|
||||
|
||||
for (i = 0; i < bufcnt; i++) {
|
||||
ab = &port->buf[i];
|
||||
|
|
@ -8913,9 +8914,9 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
|
|||
buffer_node[i].mmap_hdl);
|
||||
}
|
||||
ac->port[dir].tmp_hdl = 0;
|
||||
mutex_unlock(&ac->cmd_lock);
|
||||
rc = 0;
|
||||
fail_cmd:
|
||||
mutex_unlock(&ac->cmd_lock);
|
||||
kfree(mmap_region_cmd);
|
||||
mmap_region_cmd = NULL;
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -1506,8 +1506,10 @@ int q6core_map_mdf_memory_regions(uint64_t *buf_add, uint32_t mempool_id,
|
|||
* bufcnt;
|
||||
|
||||
mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
|
||||
if (mmap_region_cmd == NULL)
|
||||
if (mmap_region_cmd == NULL) {
|
||||
mutex_unlock(&q6core_lcl.cmd_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
|
||||
mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2013-2021, Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mutex.h>
|
||||
|
|
@ -2130,6 +2130,12 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (data->payload_size < (2 * sizeof(uint32_t))) {
|
||||
pr_err("%s: payload has invalid size[%d]\n", __func__,
|
||||
data->payload_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
command = payload[0];
|
||||
retcode = payload[1];
|
||||
sid = (data->token >> 8) & 0x0F;
|
||||
|
|
@ -2454,6 +2460,12 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
|||
sizeof(struct param_hdr_v2);
|
||||
|
||||
if (param_type == LSM_REG_MULTI_SND_MODEL) {
|
||||
if(list_empty(&client->stage_cfg[p_info->stage_idx].sound_models)) {
|
||||
pr_err("%s: sound_models list is empty \n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(sm,
|
||||
&client->stage_cfg[p_info->stage_idx].sound_models,
|
||||
list) {
|
||||
|
|
|
|||
|
|
@ -6898,6 +6898,7 @@ int voc_set_device_config(uint32_t session_id, uint8_t path_dir,
|
|||
struct media_format_info *finfo)
|
||||
{
|
||||
struct voice_data *v = voice_get_session(session_id);
|
||||
int ret = 0;
|
||||
|
||||
if (v == NULL) {
|
||||
pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
|
||||
|
|
@ -6929,12 +6930,12 @@ int voc_set_device_config(uint32_t session_id, uint8_t path_dir,
|
|||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid path_dir %d\n", __func__, path_dir);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&v->lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(voc_set_device_config);
|
||||
|
||||
|
|
|
|||
|
|
@ -12549,6 +12549,17 @@ struct afe_param_id_clock_set_v2_t {
|
|||
uint32_t d;
|
||||
};
|
||||
|
||||
#define AFE_PARAM_ID_CLOCK_MUX_CFG 0x000102fd
|
||||
struct afe_param_id_clock_mux_cfg_t {
|
||||
char mux_string[128];
|
||||
/* Name of the Mux string.
|
||||
* String name may varies for each target, so HLOS must pass the proper string based on IPCAT.
|
||||
* @values Valid string with a maximum of 128 characters
|
||||
*/
|
||||
uint32_t mux_value;
|
||||
/* Value of the external m-clock. */
|
||||
};
|
||||
|
||||
struct afe_clk_cfg {
|
||||
/* Minor version used for tracking the version of the I2S
|
||||
* configuration interface.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef __Q6AFE_V2_H__
|
||||
#define __Q6AFE_V2_H__
|
||||
|
|
@ -55,6 +55,8 @@
|
|||
/* for external mclk dynamic switch */
|
||||
#define AFE_API_VERSION_V8 8
|
||||
#define AFE_API_VERSION_V10 10
|
||||
/* for external mclk selection through mux */
|
||||
#define AFE_API_VERSION_V11 11
|
||||
|
||||
#define AFE_SAMPLING_RATE_8KHZ 8000
|
||||
|
||||
|
|
@ -419,6 +421,7 @@ enum afe_mclk_freq {
|
|||
MCLK_FREQ_11P2896_MHZ = MCLK_FREQ_MIN,
|
||||
MCLK_FREQ_12P288_MHZ,
|
||||
MCLK_FREQ_16P384_MHZ,
|
||||
MCLK_FREQ_19P200_MHZ,
|
||||
MCLK_FREQ_22P5792_MHZ,
|
||||
MCLK_FREQ_24P576_MHZ,
|
||||
MCLK_FREQ_MAX,
|
||||
|
|
@ -603,8 +606,11 @@ int afe_port_send_afe_limiter_param(u16 port_id,
|
|||
struct afe_param_id_port_afe_limiter_disable_t *disable_limiter);
|
||||
int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
|
||||
u16 port);
|
||||
int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
|
||||
uint32_t mclk_freq);
|
||||
int afe_set_lpass_clk_cfg_ext_mclk_v2(int index,
|
||||
struct afe_param_id_clock_set_v2_t *dyn_mclk_cfg, uint32_t mclk_freq);
|
||||
int afe_set_lpass_ext_mclk_mux_cfg(const char *mux_str, uint32_t mux_val);
|
||||
int afe_get_sp_rx_tmax_xmax_logging_data(
|
||||
struct afe_sp_rx_tmax_xmax_logging_param *xt_logging,
|
||||
u16 port_id);
|
||||
|
|
@ -634,6 +640,14 @@ int afe_set_source_clk(u16 port_id, const char *clk_src);
|
|||
void afe_set_clk_src_array(const char *clk_src[CLK_SRC_MAX]);
|
||||
int afe_set_mclk_src_cfg(u16 port_id, uint32_t mclk_src_id, uint32_t mclk_freq);
|
||||
|
||||
/* Client of AFE registers afe_enable_mclk_and_get_info_cb_func callback function via
|
||||
* afe_register_ext_mclk_cb() when external clock is supported by the platform. During
|
||||
* clock enable sequence, AFE triggers this callback before requesting DSP for clock
|
||||
* enable. Client can provide Div2X, M, N, D and clock root as part of this callback.
|
||||
* Client can also enable required GPIO that are essential to route external clock in
|
||||
* this callback. During clock disable sequence, AFE triggers this callback after
|
||||
* requesting DSP for clock disable. Client can disable required GPIOs in this callback.
|
||||
*/
|
||||
typedef int (*afe_enable_mclk_and_get_info_cb_func) (void *private_data,
|
||||
uint32_t enable, uint32_t mclk_freq,
|
||||
struct afe_param_id_clock_set_v2_t *dyn_mclk_cfg);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
#define SWR_CLK_RATE_4P8MHZ 4800000
|
||||
#define SWR_CLK_RATE_9P6MHZ 9600000
|
||||
#define SWR_CLK_RATE_11P2896MHZ 11289600
|
||||
#define SWR_CLK_RATE_0P384MHZ 384000
|
||||
#define SWR_CLK_RATE_0P768MHZ 768000
|
||||
#define SWR_CLK_RATE_1P536MHZ 1536000
|
||||
#define SWR_CLK_RATE_3P072MHZ 3072000
|
||||
#define SWR_CLK_RATE_6P144MHZ 6144000
|
||||
#define SWR_CLK_RATE_12P288MHZ 12288000
|
||||
|
||||
extern struct bus_type soundwire_type;
|
||||
struct swr_device;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct swr_mstr_port {
|
|||
#define MCLK_FREQ 9600000
|
||||
#define MCLK_FREQ_LP 600000
|
||||
#define MCLK_FREQ_NATIVE 11289600
|
||||
#define MCLK_FREQ_12P288MHZ 12288000
|
||||
|
||||
#if (IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL) || \
|
||||
IS_ENABLED(CONFIG_SOUNDWIRE_MSTR_CTRL))
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@
|
|||
#include "core.h"
|
||||
#include "pinctrl-utils.h"
|
||||
|
||||
#define LPI_AUTO_SUSPEND_DELAY 100 /* delay in msec */
|
||||
#define LPI_AUTO_SUSPEND_DELAY_ERROR 1 /* delay in msec */
|
||||
|
||||
#define LPI_ADDRESS_SIZE 0x20000
|
||||
#define LPI_SLEW_ADDRESS_SIZE 0x1000
|
||||
|
||||
|
|
@ -118,8 +115,6 @@ struct lpi_gpio_state {
|
|||
struct clk *lpass_core_hw_vote;
|
||||
struct clk *lpass_audio_hw_vote;
|
||||
struct mutex slew_access_lock;
|
||||
bool core_hw_vote_status;
|
||||
struct mutex core_hw_vote_lock;
|
||||
};
|
||||
|
||||
static const char *const lpi_gpio_groups[] = {
|
||||
|
|
@ -144,12 +139,54 @@ static const char *const lpi_gpio_functions[] = {
|
|||
[LPI_GPIO_FUNC_INDEX_FUNC5] = LPI_GPIO_FUNC_FUNC5,
|
||||
};
|
||||
|
||||
int lpi_pinctrl_runtime_suspend(struct device *dev);
|
||||
int lpi_pinctrl_hw_vote(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(dev);
|
||||
struct clk *hw_vote = state->lpass_core_hw_vote;
|
||||
|
||||
if (state->lpass_core_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
|
||||
if (state->lpass_audio_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
hw_vote = state->lpass_audio_hw_vote;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: lpi_pinctrl_hw_vote\n", __func__);
|
||||
ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s:lpass core hw island enable failed\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: lpi_pinctrl_hw_vote done\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lpi_pinctrl_hw_unvote(struct device *dev)
|
||||
{
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(dev);
|
||||
struct clk *hw_vote = state->lpass_core_hw_vote;
|
||||
|
||||
if (state->lpass_core_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
|
||||
if (state->lpass_audio_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
hw_vote = state->lpass_audio_hw_vote;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: lpi_pinctrl_hw_unvote\n", __func__);
|
||||
digital_cdc_rsc_mgr_hw_vote_disable(hw_vote);
|
||||
dev_dbg(dev, "%s: lpi_pinctrl_hw_unvote done\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static int lpi_gpio_read(struct lpi_gpio_pad *pad, unsigned int addr)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(lpi_dev);
|
||||
static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
|
||||
|
||||
if (!lpi_dev_up) {
|
||||
|
|
@ -158,52 +195,38 @@ static int lpi_gpio_read(struct lpi_gpio_pad *pad, unsigned int addr)
|
|||
__func__);
|
||||
return 0;
|
||||
}
|
||||
pm_runtime_get_sync(lpi_dev);
|
||||
mutex_lock(&state->core_hw_vote_lock);
|
||||
if (!state->core_hw_vote_status) {
|
||||
if (__ratelimit(&rtl))
|
||||
pr_err("%s: core hw vote clk is not enabled\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
|
||||
ret = lpi_pinctrl_hw_vote(lpi_dev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ioread32(pad->base + pad->offset + addr);
|
||||
if (ret < 0)
|
||||
pr_err("%s: read 0x%x failed\n", __func__, addr);
|
||||
|
||||
lpi_pinctrl_hw_unvote(lpi_dev);
|
||||
|
||||
err:
|
||||
mutex_unlock(&state->core_hw_vote_lock);
|
||||
pm_runtime_mark_last_busy(lpi_dev);
|
||||
pm_runtime_put_autosuspend(lpi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpi_gpio_write(struct lpi_gpio_pad *pad, unsigned int addr,
|
||||
unsigned int val)
|
||||
{
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(lpi_dev);
|
||||
int ret = 0;
|
||||
static DEFINE_RATELIMIT_STATE(rtl, 1 * HZ, 1);
|
||||
|
||||
if (!lpi_dev_up) {
|
||||
return 0;
|
||||
}
|
||||
pm_runtime_get_sync(lpi_dev);
|
||||
mutex_lock(&state->core_hw_vote_lock);
|
||||
if (!state->core_hw_vote_status) {
|
||||
if (__ratelimit(&rtl))
|
||||
pr_err("%s: core hw vote clk is not enabled\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
|
||||
ret = lpi_pinctrl_hw_vote(lpi_dev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
iowrite32(val, pad->base + pad->offset + addr);
|
||||
|
||||
lpi_pinctrl_hw_unvote(lpi_dev);
|
||||
err:
|
||||
mutex_unlock(&state->core_hw_vote_lock);
|
||||
pm_runtime_mark_last_busy(lpi_dev);
|
||||
pm_runtime_put_autosuspend(lpi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -516,39 +539,6 @@ static int lpi_notifier_service_cb(struct notifier_block *this,
|
|||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
int lpi_pinctrl_suspend(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(dev, "%s: system suspend\n", __func__);
|
||||
|
||||
if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) {
|
||||
ret = lpi_pinctrl_runtime_suspend(dev);
|
||||
if (!ret) {
|
||||
/*
|
||||
* Synchronize runtime-pm and system-pm states:
|
||||
* At this point, we are already suspended. If
|
||||
* runtime-pm still thinks its active, then
|
||||
* make sure its status is in sync with HW
|
||||
* status. The three below calls let the
|
||||
* runtime-pm know that we are suspended
|
||||
* already without re-invoking the suspend
|
||||
* callback
|
||||
*/
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lpi_pinctrl_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block service_nb = {
|
||||
.notifier_call = lpi_notifier_service_cb,
|
||||
.priority = -INT_MAX,
|
||||
|
|
@ -557,7 +547,6 @@ static struct notifier_block service_nb = {
|
|||
static void lpi_pinctrl_ssr_disable(struct device *dev, void *data)
|
||||
{
|
||||
lpi_dev_up = false;
|
||||
lpi_pinctrl_suspend(dev);
|
||||
}
|
||||
|
||||
static const struct snd_event_ops lpi_pinctrl_ssr_ops = {
|
||||
|
|
@ -773,7 +762,6 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
|
|||
state->chip.can_sleep = false;
|
||||
|
||||
mutex_init(&state->slew_access_lock);
|
||||
mutex_init(&state->core_hw_vote_lock);
|
||||
|
||||
state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
|
||||
if (IS_ERR(state->ctrl))
|
||||
|
|
@ -832,12 +820,6 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
|
|||
}
|
||||
state->lpass_audio_hw_vote = lpass_audio_hw_vote;
|
||||
|
||||
state->core_hw_vote_status = false;
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, LPI_AUTO_SUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_snd_evt:
|
||||
|
|
@ -845,7 +827,6 @@ err_snd_evt:
|
|||
err_range:
|
||||
gpiochip_remove(&state->chip);
|
||||
err_chip:
|
||||
mutex_destroy(&state->core_hw_vote_lock);
|
||||
mutex_destroy(&state->slew_access_lock);
|
||||
err_io:
|
||||
return ret;
|
||||
|
|
@ -855,13 +836,9 @@ static int lpi_pinctrl_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct lpi_gpio_state *state = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
||||
snd_event_client_deregister(&pdev->dev);
|
||||
audio_notifier_deregister("lpi_tlmm");
|
||||
gpiochip_remove(&state->chip);
|
||||
mutex_destroy(&state->core_hw_vote_lock);
|
||||
mutex_destroy(&state->slew_access_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -874,79 +851,9 @@ static const struct of_device_id lpi_pinctrl_of_match[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match);
|
||||
|
||||
int lpi_pinctrl_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
struct clk *hw_vote = state->lpass_core_hw_vote;
|
||||
|
||||
if (state->lpass_core_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
|
||||
if (state->lpass_audio_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
hw_vote = state->lpass_audio_hw_vote;
|
||||
}
|
||||
|
||||
mutex_lock(&state->core_hw_vote_lock);
|
||||
ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote);
|
||||
if (ret < 0) {
|
||||
pm_runtime_set_autosuspend_delay(dev,
|
||||
LPI_AUTO_SUSPEND_DELAY_ERROR);
|
||||
dev_err(dev, "%s:lpass core hw island enable failed\n",
|
||||
__func__);
|
||||
goto exit;
|
||||
} else {
|
||||
state->core_hw_vote_status = true;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&state->core_hw_vote_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lpi_pinctrl_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct lpi_gpio_state *state = dev_get_drvdata(dev);
|
||||
struct clk *hw_vote = state->lpass_core_hw_vote;
|
||||
|
||||
if (state->lpass_core_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
|
||||
if (state->lpass_audio_hw_vote == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
hw_vote = state->lpass_audio_hw_vote;
|
||||
}
|
||||
|
||||
mutex_lock(&state->core_hw_vote_lock);
|
||||
if (state->core_hw_vote_status) {
|
||||
digital_cdc_rsc_mgr_hw_vote_disable(hw_vote);
|
||||
state->core_hw_vote_status = false;
|
||||
}
|
||||
mutex_unlock(&state->core_hw_vote_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops lpi_pinctrl_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(
|
||||
lpi_pinctrl_suspend,
|
||||
lpi_pinctrl_resume
|
||||
)
|
||||
SET_RUNTIME_PM_OPS(
|
||||
lpi_pinctrl_runtime_suspend,
|
||||
lpi_pinctrl_runtime_resume,
|
||||
NULL
|
||||
)
|
||||
};
|
||||
|
||||
static struct platform_driver lpi_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = "qcom-lpi-pinctrl",
|
||||
.pm = &lpi_pinctrl_dev_pm_ops,
|
||||
.of_match_table = lpi_pinctrl_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1160,8 +1160,8 @@ static void swrm_switch_frame_shape(struct swr_mstr_ctrl *swrm, int mclk_freq)
|
|||
} else {
|
||||
n_col = SWR_MIN_COL;
|
||||
col = SWRM_COL_02;
|
||||
n_row = SWR_ROW_50;
|
||||
row = SWRM_ROW_50;
|
||||
n_row = (mclk_freq == MCLK_FREQ_12P288MHZ) ? SWR_ROW_64 : SWR_ROW_50;
|
||||
row = (mclk_freq == MCLK_FREQ_12P288MHZ) ? SWRM_ROW_64 : SWRM_ROW_50;
|
||||
frame_sync = SWRM_FRAME_SYNC_SEL;
|
||||
}
|
||||
|
||||
|
|
@ -1222,16 +1222,25 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq)
|
|||
if (mclk_freq == SWR_CLK_RATE_9P6MHZ) {
|
||||
if (bus_clk_freq <= SWR_CLK_RATE_0P6MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_0P6MHZ;
|
||||
else if (bus_clk_freq <= SWR_CLK_RATE_1P2MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
|
||||
else if (bus_clk_freq <= SWR_CLK_RATE_2P4MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
|
||||
else if(bus_clk_freq <= SWR_CLK_RATE_4P8MHZ)
|
||||
else if ((bus_clk_freq <= SWR_CLK_RATE_1P2MHZ) ||
|
||||
(bus_clk_freq <= SWR_CLK_RATE_2P4MHZ) ||
|
||||
(bus_clk_freq <= SWR_CLK_RATE_4P8MHZ))
|
||||
bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
|
||||
else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_9P6MHZ;
|
||||
else
|
||||
bus_clk_freq = SWR_CLK_RATE_9P6MHZ;
|
||||
} else if (mclk_freq == SWR_CLK_RATE_12P288MHZ) {
|
||||
if (bus_clk_freq <= SWR_CLK_RATE_0P768MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_0P768MHZ;
|
||||
else if ((bus_clk_freq <= SWR_CLK_RATE_1P536MHZ) ||
|
||||
(bus_clk_freq <= SWR_CLK_RATE_3P072MHZ) ||
|
||||
(bus_clk_freq <= SWR_CLK_RATE_6P144MHZ))
|
||||
bus_clk_freq = SWR_CLK_RATE_6P144MHZ;
|
||||
else if(bus_clk_freq <= SWR_CLK_RATE_12P288MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_12P288MHZ;
|
||||
else
|
||||
bus_clk_freq = SWR_CLK_RATE_12P288MHZ;
|
||||
} else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ)
|
||||
bus_clk_freq = SWR_CLK_RATE_11P2896MHZ;
|
||||
|
||||
|
|
@ -1368,12 +1377,14 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
|
|||
|
||||
if ((swrm->master_id == MASTER_ID_TX) &&
|
||||
(swrm->use_custom_phy_addr) &&
|
||||
((swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) ||
|
||||
((swrm->bus_clk == SWR_CLK_RATE_12P288MHZ) ||
|
||||
(swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) ||
|
||||
(swrm->bus_clk == SWR_CLK_RATE_0P6MHZ) ||
|
||||
(swrm->bus_clk == SWR_CLK_RATE_4P8MHZ))) {
|
||||
dev_num = swrm_get_device_id(swrm, port_req->dev_num);
|
||||
port_id = port_req->slave_port_id;
|
||||
if (swrm->bus_clk == SWR_CLK_RATE_9P6MHZ)
|
||||
if ((swrm->bus_clk == SWR_CLK_RATE_12P288MHZ) ||
|
||||
(swrm->bus_clk == SWR_CLK_RATE_9P6MHZ))
|
||||
pp_dev = swrdev_frame_params_9p6MHz[dev_num].pp;
|
||||
else if (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ)
|
||||
pp_dev = swrdev_frame_params_0p6MHz[dev_num].pp;
|
||||
|
|
@ -1681,7 +1692,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
|
|||
/* set col = 16 */
|
||||
n_col = SWR_MAX_COL;
|
||||
col = SWRM_COL_16;
|
||||
if (swrm->bus_clk == MCLK_FREQ_LP) {
|
||||
if ((swrm->bus_clk == MCLK_FREQ_LP) ||
|
||||
(swrm->bus_clk == SWR_CLK_RATE_0P768MHZ)) {
|
||||
n_col = SWR_MIN_COL;
|
||||
col = SWRM_COL_02;
|
||||
}
|
||||
|
|
@ -1699,16 +1711,15 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
|
|||
}
|
||||
/* Use default 50 * x, frame shape. Change based on mclk */
|
||||
if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
|
||||
dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", col);
|
||||
n_row = SWR_ROW_64;
|
||||
row = SWRM_ROW_64;
|
||||
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
||||
} else {
|
||||
dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", col);
|
||||
n_row = SWR_ROW_50;
|
||||
row = SWRM_ROW_50;
|
||||
n_row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? SWR_ROW_64 : SWR_ROW_50;
|
||||
row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? SWRM_ROW_64 : SWRM_ROW_50;
|
||||
frame_sync = SWRM_FRAME_SYNC_SEL;
|
||||
}
|
||||
dev_dbg(swrm->dev, "setting %d x %d frameshape\n", row, col);
|
||||
ssp_period = swrm_get_ssp_period(swrm, row, col, frame_sync);
|
||||
bus_clk_div_factor = swrm_get_clk_div(swrm->mclk_freq, swrm->bus_clk);
|
||||
dev_dbg(swrm->dev, "%s: ssp_period: %d, bus_clk_div:%d \n", __func__,
|
||||
|
|
@ -2209,6 +2220,15 @@ handle_irq:
|
|||
swrm->clk_stop_wakeup = false;
|
||||
}
|
||||
break;
|
||||
case SWRM_INTERRUPT_STATUS_DOUT_RATE_MISMATCH:
|
||||
dev_err(swrm->dev,
|
||||
"%s: SWR Port Channel rate mismatch\n",
|
||||
__func__);
|
||||
swrm->intr_mask &=
|
||||
~SWRM_INTERRUPT_STATUS_DOUT_RATE_MISMATCH;
|
||||
swr_master_write(swrm,
|
||||
SWRM_CPU1_INTERRUPT_EN, swrm->intr_mask);
|
||||
break;
|
||||
default:
|
||||
dev_err_ratelimited(swrm->dev,
|
||||
"%s: SWR unknown interrupt value: %d\n",
|
||||
|
|
@ -2450,14 +2470,28 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|||
{
|
||||
int ret = 0, i = 0;
|
||||
u32 val;
|
||||
u8 row_ctrl = SWR_ROW_50;
|
||||
u8 col_ctrl = SWR_MIN_COL;
|
||||
u8 row_ctrl = 0, row = 0;
|
||||
u8 col_ctrl = SWR_MIN_COL, col = SWRM_COL_02;
|
||||
u8 ssp_period = 1;
|
||||
u8 retry_cmd_num = 3;
|
||||
u32 reg[SWRM_MAX_INIT_REG];
|
||||
u32 value[SWRM_MAX_INIT_REG];
|
||||
u32 temp = 0;
|
||||
int len = 0;
|
||||
int frame_sync = SWRM_FRAME_SYNC_SEL;
|
||||
|
||||
if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
|
||||
row_ctrl = SWR_ROW_64;
|
||||
row = SWRM_ROW_64;
|
||||
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
|
||||
|
||||
} else {
|
||||
row_ctrl = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ?
|
||||
SWR_ROW_64 : SWR_ROW_50;
|
||||
row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ?
|
||||
SWRM_ROW_64 : SWRM_ROW_50;
|
||||
frame_sync = SWRM_FRAME_SYNC_SEL;
|
||||
}
|
||||
|
||||
/* Change no of retry counts to 1 for wsa to avoid underflow */
|
||||
if (swrm->master_id == MASTER_ID_WSA)
|
||||
|
|
@ -2475,8 +2509,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
|
|||
__func__, temp);
|
||||
}
|
||||
}
|
||||
ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50,
|
||||
SWRM_COL_02, SWRM_FRAME_SYNC_SEL);
|
||||
ssp_period = swrm_get_ssp_period(swrm, row, col, frame_sync);
|
||||
dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
|
||||
|
||||
/* Clear Rows and Cols */
|
||||
|
|
@ -2595,7 +2628,7 @@ static int swrm_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct swr_mstr_ctrl *swrm;
|
||||
struct swr_ctrl_platform_data *pdata;
|
||||
u32 i, num_ports, port_num, port_type, ch_mask, swrm_hctl_reg = 0;
|
||||
u32 i, num_ports, port_num, port_type, ch_mask, swrm_hctl_reg = 0, mclk_freq = 0;
|
||||
u32 *temp, map_size, map_length, ch_iter = 0, old_port_num = 0;
|
||||
int ret = 0;
|
||||
struct clk *lpass_core_hw_vote = NULL;
|
||||
|
|
@ -2830,8 +2863,6 @@ static int swrm_probe(struct platform_device *pdev)
|
|||
swrm->num_rx_chs = 0;
|
||||
swrm->clk_ref_count = 0;
|
||||
swrm->swr_irq_wakeup_capable = 0;
|
||||
swrm->mclk_freq = MCLK_FREQ;
|
||||
swrm->bus_clk = MCLK_FREQ;
|
||||
swrm->dev_up = true;
|
||||
swrm->state = SWR_MSTR_UP;
|
||||
swrm->ipc_wakeup = false;
|
||||
|
|
@ -2861,6 +2892,17 @@ static int swrm_probe(struct platform_device *pdev)
|
|||
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
|
||||
INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "qcom,swrm-mclk-clk-rate",
|
||||
&mclk_freq);
|
||||
if (ret) {
|
||||
swrm->mclk_freq = MCLK_FREQ;
|
||||
dev_dbg(&pdev->dev, "%s SWRM MCLK not specified, using default: %d,\n",
|
||||
__func__, swrm->mclk_freq);
|
||||
} else {
|
||||
swrm->mclk_freq = mclk_freq;
|
||||
}
|
||||
swrm->bus_clk = swrm->mclk_freq;
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,disable-div2-clk-switch",
|
||||
&swrm->disable_div2_clk_switch)) {
|
||||
|
|
@ -3092,6 +3134,12 @@ static int swrm_runtime_resume(struct device *dev)
|
|||
struct swr_master *mstr = &swrm->master;
|
||||
struct swr_device *swr_dev;
|
||||
u32 temp = 0;
|
||||
u8 row_ctrl = SWR_ROW_50;
|
||||
u8 col_ctrl = SWR_MIN_COL;
|
||||
|
||||
if ((swrm->mclk_freq == MCLK_FREQ_NATIVE) ||
|
||||
(swrm->mclk_freq == MCLK_FREQ_12P288MHZ))
|
||||
row_ctrl = SWR_ROW_64;
|
||||
|
||||
dev_dbg(dev, "%s: pm_runtime: resume, state:%d\n",
|
||||
__func__, swrm->state);
|
||||
|
|
@ -3178,7 +3226,7 @@ static int swrm_runtime_resume(struct device *dev)
|
|||
SWRS_SCP_INT_STATUS_MASK_1);
|
||||
if (swrm->state == SWR_MSTR_SSR) {
|
||||
mutex_unlock(&swrm->reslock);
|
||||
enable_bank_switch(swrm, 0, SWR_ROW_50, SWR_MIN_COL);
|
||||
enable_bank_switch(swrm, 0, row_ctrl, col_ctrl);
|
||||
mutex_lock(&swrm->reslock);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3235,6 +3283,13 @@ static int swrm_runtime_suspend(struct device *dev)
|
|||
int current_state = 0;
|
||||
struct irq_data *irq_data = NULL;
|
||||
|
||||
u8 row_ctrl = SWR_ROW_50;
|
||||
u8 col_ctrl = SWR_MIN_COL;
|
||||
|
||||
if ((swrm->mclk_freq == MCLK_FREQ_NATIVE) ||
|
||||
(swrm->mclk_freq == MCLK_FREQ_12P288MHZ))
|
||||
row_ctrl = SWR_ROW_64;
|
||||
|
||||
dev_dbg(dev, "%s: pm_runtime: suspend state: %d\n",
|
||||
__func__, swrm->state);
|
||||
if (swrm->state == SWR_MSTR_SSR_RESET) {
|
||||
|
|
@ -3268,7 +3323,7 @@ static int swrm_runtime_suspend(struct device *dev)
|
|||
dev_err(dev, "%s: clk stop mode not supported or SSR entry\n",
|
||||
__func__);
|
||||
mutex_unlock(&swrm->reslock);
|
||||
enable_bank_switch(swrm, 0, SWR_ROW_50, SWR_MIN_COL);
|
||||
enable_bank_switch(swrm, 0, row_ctrl, col_ctrl);
|
||||
mutex_lock(&swrm->reslock);
|
||||
swrm_clk_pause(swrm);
|
||||
swr_master_write(swrm, SWRM_COMP_CFG, 0x00);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015, 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SWRM_REGISTERS_H
|
||||
|
|
@ -125,6 +126,7 @@
|
|||
#endif /* CONFIG_SWRM_VER_1P1 */
|
||||
|
||||
#define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP 0x10000
|
||||
#define SWRM_INTERRUPT_STATUS_DOUT_RATE_MISMATCH 0x20000
|
||||
|
||||
#define SWRM_COMP_PARAMS_WR_FIFO_DEPTH 0x00007C00
|
||||
#define SWRM_COMP_PARAMS_RD_FIFO_DEPTH 0x000F8000
|
||||
|
|
|
|||
Loading…
Reference in a new issue