diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/lpass-rx-macro.c | 18 | ||||
-rw-r--r-- | sound/soc/codecs/lpass-tx-macro.c | 36 | ||||
-rw-r--r-- | sound/soc/codecs/lpass-va-macro.c | 82 | ||||
-rw-r--r-- | sound/soc/codecs/lpass-wsa-macro.c | 19 | ||||
-rw-r--r-- | sound/soc/codecs/wsa883x.c | 28 |
5 files changed, 112 insertions, 71 deletions
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 3143f9cd7277..a9ef9d5ffcc5 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -596,7 +596,6 @@ struct rx_macro { int rx_port_value[RX_MACRO_PORTS_MAX]; u16 prim_int_users[INTERP_MAX]; int rx_mclk_users; - bool reset_swr; int clsh_users; int rx_mclk_cnt; bool is_ear_mode_on; @@ -3442,18 +3441,15 @@ static int swclk_gate_enable(struct clk_hw *hw) } rx_macro_mclk_enable(rx, true); - if (rx->reset_swr) - regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, - CDC_RX_SWR_RESET_MASK, - CDC_RX_SWR_RESET); + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_RESET_MASK, + CDC_RX_SWR_RESET); regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, CDC_RX_SWR_CLK_EN_MASK, 1); - if (rx->reset_swr) - regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, - CDC_RX_SWR_RESET_MASK, 0); - rx->reset_swr = false; + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_RESET_MASK, 0); return 0; } @@ -3579,7 +3575,6 @@ static int rx_macro_probe(struct platform_device *pdev) dev_set_drvdata(dev, rx); - rx->reset_swr = true; rx->dev = dev; /* set MCLK and NPL rates */ @@ -3659,6 +3654,8 @@ static int rx_macro_remove(struct platform_device *pdev) static const struct of_device_id rx_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-rx-macro" }, { .compatible = "qcom,sm8250-lpass-rx-macro" }, + { .compatible = "qcom,sm8450-lpass-rx-macro" }, + { .compatible = "qcom,sc8280xp-lpass-rx-macro" }, { } }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); @@ -3701,7 +3698,6 @@ static int __maybe_unused rx_macro_runtime_resume(struct device *dev) } regcache_cache_only(rx->regmap, false); regcache_sync(rx->regmap); - rx->reset_swr = true; return 0; err_fsgen: diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 55503ba480bb..ee15cf6b98bb 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -259,7 +259,7 @@ struct tx_macro { struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS]; unsigned long active_ch_mask[TX_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS]; - unsigned long active_decimator[TX_MACRO_MAX_DAIS]; + int active_decimator[TX_MACRO_MAX_DAIS]; struct regmap *regmap; struct clk *mclk; struct clk *npl; @@ -268,7 +268,6 @@ struct tx_macro { struct clk *fsgen; struct clk_hw hw; bool dec_active[NUM_DECIMATORS]; - bool reset_swr; int tx_mclk_users; u16 dmic_clk_div; bool bcs_enable; @@ -823,17 +822,23 @@ static int tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, struct tx_macro *tx = snd_soc_component_get_drvdata(component); if (enable) { + if (tx->active_decimator[dai_id] == dec_id) + return 0; + set_bit(dec_id, &tx->active_ch_mask[dai_id]); tx->active_ch_cnt[dai_id]++; tx->active_decimator[dai_id] = dec_id; } else { + if (tx->active_decimator[dai_id] == -1) + return 0; + tx->active_ch_cnt[dai_id]--; clear_bit(dec_id, &tx->active_ch_mask[dai_id]); tx->active_decimator[dai_id] = -1; } snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); - return 0; + return 1; } static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, @@ -1019,9 +1024,12 @@ static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol, int path = e->shift_l; struct tx_macro *tx = snd_soc_component_get_drvdata(component); + if (tx->dec_mode[path] == value) + return 0; + tx->dec_mode[path] = value; - return 0; + return 1; } static int tx_macro_get_bcs(struct snd_kcontrol *kcontrol, @@ -1118,6 +1126,10 @@ static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) struct tx_macro *tx = snd_soc_component_get_drvdata(component); u16 decimator; + /* active decimator not set yet */ + if (tx->active_decimator[dai->id] == -1) + return 0; + decimator = tx->active_decimator[dai->id]; if (mute) @@ -1702,18 +1714,14 @@ static int swclk_gate_enable(struct clk_hw *hw) } tx_macro_mclk_enable(tx, true); - if (tx->reset_swr) - regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, - CDC_TX_SWR_RESET_MASK, - CDC_TX_SWR_RESET_ENABLE); + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_RESET_MASK, CDC_TX_SWR_RESET_ENABLE); regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, CDC_TX_SWR_CLK_EN_MASK, CDC_TX_SWR_CLK_ENABLE); - if (tx->reset_swr) - regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, - CDC_TX_SWR_RESET_MASK, 0x0); - tx->reset_swr = false; + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_RESET_MASK, 0x0); return 0; } @@ -1855,7 +1863,6 @@ static int tx_macro_probe(struct platform_device *pdev) dev_set_drvdata(dev, tx); - tx->reset_swr = true; tx->dev = dev; /* set MCLK and NPL rates */ @@ -1970,7 +1977,6 @@ static int __maybe_unused tx_macro_runtime_resume(struct device *dev) regcache_cache_only(tx->regmap, false); regcache_sync(tx->regmap); - tx->reset_swr = true; return 0; err_fsgen: @@ -1988,6 +1994,8 @@ static const struct dev_pm_ops tx_macro_pm_ops = { static const struct of_device_id tx_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-tx-macro" }, { .compatible = "qcom,sm8250-lpass-tx-macro" }, + { .compatible = "qcom,sm8450-lpass-tx-macro" }, + { .compatible = "qcom,sc8280xp-lpass-tx-macro" }, { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 1ea10dc70748..b0b6cf29cba3 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -23,7 +23,12 @@ #define CDC_VA_MCLK_CONTROL_EN BIT(0) #define CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) #define CDC_VA_FS_CONTROL_EN BIT(0) +#define CDC_VA_FS_COUNTER_CLR BIT(1) #define CDC_VA_CLK_RST_CTRL_SWR_CONTROL (0x0008) +#define CDC_VA_SWR_RESET_MASK BIT(1) +#define CDC_VA_SWR_RESET_ENABLE BIT(1) +#define CDC_VA_SWR_CLK_EN_MASK BIT(0) +#define CDC_VA_SWR_CLK_ENABLE BIT(0) #define CDC_VA_TOP_CSR_TOP_CFG0 (0x0080) #define CDC_VA_FS_BROADCAST_EN BIT(1) #define CDC_VA_TOP_CSR_DMIC0_CTL (0x0084) @@ -65,6 +70,8 @@ #define CDC_VA_TOP_CSR_SWR_MIC_CTL0 (0x00D0) #define CDC_VA_TOP_CSR_SWR_MIC_CTL1 (0x00D4) #define CDC_VA_TOP_CSR_SWR_MIC_CTL2 (0x00D8) +#define CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK (0xEE) +#define CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1 (0xCC) #define CDC_VA_TOP_CSR_SWR_CTRL (0x00DC) #define CDC_VA_INP_MUX_ADC_MUX0_CFG0 (0x0100) #define CDC_VA_INP_MUX_ADC_MUX0_CFG1 (0x0104) @@ -193,6 +200,7 @@ struct va_macro { unsigned long active_ch_mask[VA_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[VA_MACRO_MAX_DAIS]; u16 dmic_clk_div; + bool has_swr_master; int dec_mode[VA_MACRO_NUM_DECIMATORS]; struct regmap *regmap; @@ -215,6 +223,18 @@ struct va_macro { #define to_va_macro(_hw) container_of(_hw, struct va_macro, hw) +struct va_macro_data { + bool has_swr_master; +}; + +static const struct va_macro_data sm8250_va_data = { + .has_swr_master = false, +}; + +static const struct va_macro_data sm8450_va_data = { + .has_swr_master = true, +}; + static bool va_is_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -324,6 +344,9 @@ static bool va_is_rw_register(struct device *dev, unsigned int reg) case CDC_VA_TOP_CSR_DMIC2_CTL: case CDC_VA_TOP_CSR_DMIC3_CTL: case CDC_VA_TOP_CSR_DMIC_CFG: + case CDC_VA_TOP_CSR_SWR_MIC_CTL0: + case CDC_VA_TOP_CSR_SWR_MIC_CTL1: + case CDC_VA_TOP_CSR_SWR_MIC_CTL2: case CDC_VA_TOP_CSR_DEBUG_BUS: case CDC_VA_TOP_CSR_DEBUG_EN: case CDC_VA_TOP_CSR_TX_I2S_CTL: @@ -423,9 +446,12 @@ static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, CDC_VA_MCLK_CONTROL_EN, CDC_VA_MCLK_CONTROL_EN); - + /* clear the fs counter */ regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, - CDC_VA_FS_CONTROL_EN, + CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, + CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR); + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN); regmap_update_bits(regmap, CDC_VA_TOP_CSR_TOP_CFG0, @@ -1302,12 +1328,36 @@ static const struct snd_soc_component_driver va_macro_component_drv = { static int fsgen_gate_enable(struct clk_hw *hw) { - return va_macro_mclk_enable(to_va_macro(hw), true); + struct va_macro *va = to_va_macro(hw); + struct regmap *regmap = va->regmap; + int ret; + + ret = va_macro_mclk_enable(va, true); + if (!va->has_swr_master) + return ret; + + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + CDC_VA_SWR_RESET_MASK, CDC_VA_SWR_RESET_ENABLE); + + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + CDC_VA_SWR_CLK_EN_MASK, + CDC_VA_SWR_CLK_ENABLE); + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + CDC_VA_SWR_RESET_MASK, 0x0); + + return ret; } static void fsgen_gate_disable(struct clk_hw *hw) { - va_macro_mclk_enable(to_va_macro(hw), false); + struct va_macro *va = to_va_macro(hw); + struct regmap *regmap = va->regmap; + + if (va->has_swr_master) + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, + CDC_VA_SWR_CLK_EN_MASK, 0x0); + + va_macro_mclk_enable(va, false); } static int fsgen_gate_is_enabled(struct clk_hw *hw) @@ -1401,6 +1451,7 @@ undefined_rate: static int va_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct va_macro_data *data; struct va_macro *va; void __iomem *base; u32 sample_rate = 0; @@ -1455,6 +1506,9 @@ static int va_macro_probe(struct platform_device *pdev) dev_set_drvdata(dev, va); + data = of_device_get_match_data(dev); + va->has_swr_master = data->has_swr_master; + /* mclk rate */ clk_set_rate(va->mclk, 2 * VA_MACRO_MCLK_FREQ); @@ -1480,6 +1534,20 @@ static int va_macro_probe(struct platform_device *pdev) goto err_clkout; } + if (va->has_swr_master) { + /* Set default CLK div to 1 */ + regmap_update_bits(va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL0, + CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, + CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); + regmap_update_bits(va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL1, + CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, + CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); + regmap_update_bits(va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL2, + CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK, + CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1); + + } + ret = devm_snd_soc_register_component(dev, &va_macro_component_drv, va_macro_dais, ARRAY_SIZE(va_macro_dais)); @@ -1554,8 +1622,10 @@ static const struct dev_pm_ops va_macro_pm_ops = { }; static const struct of_device_id va_macro_dt_match[] = { - { .compatible = "qcom,sc7280-lpass-va-macro" }, - { .compatible = "qcom,sm8250-lpass-va-macro" }, + { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sm8250_va_data }, + { .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data }, + { .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data }, + { .compatible = "qcom,sc8280xp-lpass-va-macro", .data = &sm8450_va_data }, {} }; MODULE_DEVICE_TABLE(of, va_macro_dt_match); diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 27da6c6c3c5a..5e0abefe7cce 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -338,7 +338,6 @@ struct wsa_macro { int ec_hq[WSA_MACRO_RX1 + 1]; u16 prim_int_users[WSA_MACRO_RX1 + 1]; u16 wsa_mclk_users; - bool reset_swr; unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS]; int rx_port_value[WSA_MACRO_RX_MAX]; @@ -2271,23 +2270,16 @@ static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) wsa_macro_mclk_enable(wsa, true); /* reset swr ip */ - if (wsa->reset_swr) - regmap_update_bits(regmap, - CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, - CDC_WSA_SWR_RST_EN_MASK, - CDC_WSA_SWR_RST_ENABLE); + regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_RST_EN_MASK, CDC_WSA_SWR_RST_ENABLE); regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, CDC_WSA_SWR_CLK_EN_MASK, CDC_WSA_SWR_CLK_ENABLE); /* Bring out of reset */ - if (wsa->reset_swr) - regmap_update_bits(regmap, - CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, - CDC_WSA_SWR_RST_EN_MASK, - CDC_WSA_SWR_RST_DISABLE); - wsa->reset_swr = false; + regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, + CDC_WSA_SWR_RST_EN_MASK, CDC_WSA_SWR_RST_DISABLE); } else { regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, CDC_WSA_SWR_CLK_EN_MASK, 0); @@ -2431,7 +2423,6 @@ static int wsa_macro_probe(struct platform_device *pdev) dev_set_drvdata(dev, wsa); - wsa->reset_swr = true; wsa->dev = dev; /* set MCLK and NPL rates */ @@ -2561,6 +2552,8 @@ static const struct dev_pm_ops wsa_macro_pm_ops = { static const struct of_device_id wsa_macro_dt_match[] = { {.compatible = "qcom,sc7280-lpass-wsa-macro"}, {.compatible = "qcom,sm8250-lpass-wsa-macro"}, + {.compatible = "qcom,sm8450-lpass-wsa-macro"}, + {.compatible = "qcom,sc8280xp-lpass-wsa-macro" }, {} }; MODULE_DEVICE_TABLE(of, wsa_macro_dt_match); diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index 63e1d7aa6137..c7b10bbfba7e 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -415,7 +415,6 @@ #define WSA883X_NUM_REGISTERS (WSA883X_EMEM_63 + 1) #define WSA883X_MAX_REGISTER (WSA883X_NUM_REGISTERS - 1) -#define WSA883X_PROBE_TIMEOUT 1000 #define WSA883X_VERSION_1_0 0 #define WSA883X_VERSION_1_1 1 @@ -1409,6 +1408,7 @@ static int wsa883x_probe(struct sdw_slave *pdev, wsa883x->sconfig.type = SDW_STREAM_PDM; pdev->prop.sink_ports = GENMASK(WSA883X_MAX_SWR_PORTS, 0); + pdev->prop.simple_clk_stop_capable = true; pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; gpiod_direction_output(wsa883x->sd_n, 1); @@ -1440,43 +1440,17 @@ err: static int __maybe_unused wsa883x_runtime_suspend(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); - struct wsa883x_priv *wsa883x = dev_get_drvdata(dev); - - gpiod_direction_output(wsa883x->sd_n, 0); regcache_cache_only(regmap, true); regcache_mark_dirty(regmap); - regulator_disable(wsa883x->vdd); return 0; } static int __maybe_unused wsa883x_runtime_resume(struct device *dev) { - struct sdw_slave *slave = dev_to_sdw_dev(dev); struct regmap *regmap = dev_get_regmap(dev, NULL); - struct wsa883x_priv *wsa883x = dev_get_drvdata(dev); - unsigned long time; - int ret; - - ret = regulator_enable(wsa883x->vdd); - if (ret) { - dev_err(dev, "Failed to enable vdd regulator (%d)\n", ret); - return ret; - } - - gpiod_direction_output(wsa883x->sd_n, 1); - - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(WSA883X_PROBE_TIMEOUT)); - if (!time) { - dev_err(dev, "Initialization not complete, timed out\n"); - gpiod_direction_output(wsa883x->sd_n, 0); - regulator_disable(wsa883x->vdd); - return -ETIMEDOUT; - } - usleep_range(20000, 20010); regcache_cache_only(regmap, false); regcache_sync(regmap); |