Loading sound/soc/codecs/msm8x16-wcd.c +58 −8 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ #include <linux/regulator/consumer.h> #include <linux/mfd/wcd9xxx/pdata.h> #include <linux/qdsp6v2/apr.h> #include <linux/timer.h> #include <linux/workqueue.h> #include <linux/sched.h> #include <sound/q6afe-v2.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -215,8 +218,7 @@ static int msm8x16_wcd_ahb_write_device(u16 reg, u8 *value, u32 bytes) pr_debug("%s: q6 not ready %d\n", __func__, q6_state); return 0; } else pr_debug("%s: DSP is ready q6_state = %d\n", __func__, q6_state); pr_debug("%s: DSP is ready %d\n", __func__, q6_state); iowrite32(temp, ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR + offset, 4)); return 0; Loading Loading @@ -312,18 +314,42 @@ int msm8x16_wcd_spmi_write(unsigned short reg, int bytes, void *src) return msm8x16_wcd_spmi_write_device(reg, src, bytes); } static int __msm8x16_wcd_reg_read(struct msm8x16_wcd *msm8x16_wcd, static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec, unsigned short reg) { int ret = -EINVAL; u8 temp; struct msm8x16_wcd *msm8x16_wcd = codec->control_data; struct msm8916_asoc_mach_data *pdata = NULL; pr_debug("%s reg = %x\n", __func__, reg); mutex_lock(&msm8x16_wcd->io_lock); pdata = snd_soc_card_get_drvdata(codec->card); if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) ret = msm8x16_wcd_spmi_read(reg, 1, &temp); else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { if ((atomic_read(&pdata->mclk_rsc_ref) == 0) && (pdata->snd_card_on == true) && (atomic_read(&pdata->dis_work_mclk) == false)) { mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 9600000; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) { pr_err("failed to enable the MCLK\n"); return 0; } pr_debug("%s: MCLK not enabled\n", __func__); atomic_set(&pdata->dis_work_mclk, true); schedule_delayed_work(&pdata->enable_mclk_work, 50); ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp); mutex_unlock(&pdata->cdc_mclk_mutex); mutex_unlock(&msm8x16_wcd->io_lock); return temp; } ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp); } mutex_unlock(&msm8x16_wcd->io_lock); if (ret < 0) { Loading @@ -339,16 +365,40 @@ static int __msm8x16_wcd_reg_read(struct msm8x16_wcd *msm8x16_wcd, return temp; } static int __msm8x16_wcd_reg_write(struct msm8x16_wcd *msm8x16_wcd, static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec, unsigned short reg, u8 val) { int ret = -EINVAL; struct msm8x16_wcd *msm8x16_wcd = codec->control_data; struct msm8916_asoc_mach_data *pdata = NULL; mutex_lock(&msm8x16_wcd->io_lock); pdata = snd_soc_card_get_drvdata(codec->card); if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) ret = msm8x16_wcd_spmi_write(reg, 1, &val); else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { if ((atomic_read(&pdata->mclk_rsc_ref) == 0) && (pdata->snd_card_on == true) && (atomic_read(&pdata->dis_work_mclk) == false)) { pr_debug("MCLK not enabled %s:\n", __func__); mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 9600000; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) { pr_err("failed to enable the MCLK\n"); return 0; } atomic_set(&pdata->dis_work_mclk, true); schedule_delayed_work(&pdata->enable_mclk_work, 50); ret = msm8x16_wcd_ahb_write_device(reg, &val, 1); mutex_unlock(&pdata->cdc_mclk_mutex); mutex_unlock(&msm8x16_wcd->io_lock); return ret; } ret = msm8x16_wcd_ahb_write_device(reg, &val, 1); } mutex_unlock(&msm8x16_wcd->io_lock); return ret; Loading Loading @@ -387,7 +437,7 @@ static int msm8x16_wcd_write(struct snd_soc_codec *codec, unsigned int reg, dev_err(codec->dev, "Cache write to %x failed: %d\n", reg, ret); } return __msm8x16_wcd_reg_write(codec->control_data, reg, (u8)value); return __msm8x16_wcd_reg_write(codec, reg, (u8)value); } static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, Loading @@ -414,7 +464,7 @@ static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, dev_err(codec->dev, "Cache read from %x failed: %d\n", reg, ret); } val = __msm8x16_wcd_reg_read(codec->control_data, reg); val = __msm8x16_wcd_reg_read(codec, reg); dev_dbg(codec->dev, "%s: Read from reg 0x%x val 0x%x\n", __func__, reg, val); return val; Loading sound/soc/codecs/msm8x16-wcd.h +13 −2 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <sound/soc.h> #include <sound/jack.h> #include <sound/q6afe-v2.h> #include <linux/mfd/wcd9xxx/pdata.h> #include "wcd-mbhc-v2.h" Loading Loading @@ -116,6 +117,16 @@ struct msm8x16_wcd_regulator { struct regulator *regulator; }; struct msm8916_asoc_mach_data { int codec_type; int snd_card_on; atomic_t mclk_rsc_ref; atomic_t dis_work_mclk; struct mutex cdc_mclk_mutex; struct delayed_work enable_mclk_work; struct afe_digital_clk_cfg digital_cdc_clk; }; struct msm8x16_wcd_pdata { int irq; int irq_base; Loading @@ -137,9 +148,9 @@ struct msm8x16_wcd { u8 version; int reset_gpio; int (*read_dev)(struct msm8x16_wcd *msm8x16, int (*read_dev)(struct snd_soc_codec *codec, unsigned short reg); int (*write_dev)(struct msm8x16_wcd *msm8x16, int (*write_dev)(struct snd_soc_codec *codec, unsigned short reg, u8 val); u32 num_of_supplies; Loading sound/soc/msm/msm8x16.c +76 −36 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ #include <linux/qpnp/clkdiv.h> #include <linux/io.h> #include <linux/module.h> #include <linux/timer.h> #include <linux/workqueue.h> #include <linux/sched.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/soc-dapm.h> Loading @@ -44,6 +47,7 @@ static int msm_btsco_ch = 1; static int msm_ter_mi2s_tx_ch = 1; static int msm_proxy_rx_ch = 2; static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable, bool dapm); Loading Loading @@ -74,17 +78,6 @@ static struct afe_clk_cfg mi2s_tx_clk = { 0, }; struct msm8916_asoc_mach_data { int codec_type; }; static struct afe_digital_clk_cfg digital_cdc_clk = { AFE_API_VERSION_I2S_CONFIG, 9600000, 5, /* Digital Codec root */ 0, }; struct cdc_pdm_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *cdc_pdm_sus; Loading @@ -93,8 +86,6 @@ struct cdc_pdm_pinctrl_info { static struct cdc_pdm_pinctrl_info pinctrl_info; static atomic_t mclk_rsc_ref; static struct mutex cdc_mclk_mutex; static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static inline int param_is_mask(int p) Loading Loading @@ -313,30 +304,38 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable, bool dapm) { int ret = 0; struct msm8916_asoc_mach_data *pdata = NULL; mutex_lock(&cdc_mclk_mutex); pr_debug("%s: enable = %d codec name %s enable %d mclk ref counter %d\n", pdata = snd_soc_card_get_drvdata(codec->card); mutex_lock(&pdata->cdc_mclk_mutex); pr_err("%s: enable = %d codec name %s enable %d mclk ref counter %d\n", __func__, enable, codec->name, enable, atomic_read(&mclk_rsc_ref)); atomic_read(&pdata->mclk_rsc_ref)); if (enable) { if (atomic_inc_return(&mclk_rsc_ref) == 1) { digital_cdc_clk.clk_val = 9600000; if (atomic_inc_return(&pdata->mclk_rsc_ref) == 1) { pdata->digital_cdc_clk.clk_val = 9600000; afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_clk); &pdata->digital_cdc_clk); msm8x16_wcd_mclk_enable(codec, 1, dapm); cancel_delayed_work_sync(&pdata->enable_mclk_work); } } else { if (atomic_dec_return(&mclk_rsc_ref) == 0) { digital_cdc_clk.clk_val = 0; if (atomic_dec_return(&pdata->mclk_rsc_ref) == 0) { pdata->digital_cdc_clk.clk_val = 0; msm8x16_wcd_mclk_enable(codec, 0, dapm); afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_clk); &pdata->digital_cdc_clk); if (atomic_read(&pdata->dis_work_mclk) == true) { pr_debug("add work in disable of %s\n", __func__); schedule_delayed_work( &pdata->enable_mclk_work, 10); } } } mutex_unlock(&cdc_mclk_mutex); mutex_unlock(&pdata->cdc_mclk_mutex); return ret; } Loading @@ -357,19 +356,14 @@ static int msm8x16_mclk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { pr_debug("%s: event = %d\n", __func__, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: return msm8x16_enable_codec_ext_clk(w->codec, 1, true); case SND_SOC_DAPM_POST_PMD: return msm8x16_enable_codec_ext_clk(w->codec, 0, true); default: return -EINVAL; } return 0; } static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) { int ret; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; pr_debug("%s(): substream = %s stream = %d\n", __func__, substream->name, substream->stream); Loading @@ -379,6 +373,9 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) pr_err("%s:clock disable failed\n", __func__); pinctrl_select_state(pinctrl_info.pinctrl, pinctrl_info.cdc_pdm_sus); ret = msm8x16_enable_codec_ext_clk(codec, 0, true); if (ret < 0) pr_err("failed to disable the mclk\n"); } static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) Loading @@ -386,6 +383,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int ret = 0; int val = 0; Loading @@ -405,6 +403,11 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) val = val | 0x00200000; iowrite32(val, ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4)); } ret = msm8x16_enable_codec_ext_clk(codec, 1, true); if (ret < 0) { pr_err("failed to enable mclk\n"); return ret; } ret = pinctrl_select_state(pinctrl_info.pinctrl, pinctrl_info.cdc_pdm_act); Loading Loading @@ -900,6 +903,32 @@ static int cdc_pdm_get_pinctrl(struct platform_device *pdev) return 0; } void enable_mclk(struct work_struct *work) { struct msm8916_asoc_mach_data *pdata = NULL; struct delayed_work *dwork; int ret = 0; pr_info("%s:\n", __func__); dwork = to_delayed_work(work); pdata = container_of(dwork, struct msm8916_asoc_mach_data, enable_mclk_work); if (atomic_read(&pdata->mclk_rsc_ref) == 0) { if (atomic_read(&pdata->dis_work_mclk) == true) { pr_debug("clock enabled now disable\n"); mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 0; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) pr_err("failed to disable the MCLK\n"); atomic_set(&pdata->dis_work_mclk, false); mutex_unlock(&pdata->cdc_mclk_mutex); } } } static int msm8x16_asoc_machine_probe(struct platform_device *pdev) { struct snd_soc_card *card; Loading Loading @@ -949,7 +978,12 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) dev_info(&pdev->dev, "default codec configured\n"); pdata->codec_type = 0; } /* initialize the mclk */ pdata->digital_cdc_clk.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; pdata->digital_cdc_clk.clk_val = 9600000; pdata->digital_cdc_clk.clk_root = 5; pdata->digital_cdc_clk.reserved = 0; ret = cdc_pdm_get_pinctrl(pdev); if (ret < 0) { pr_err("failed to get the pdm gpios\n"); Loading @@ -965,6 +999,7 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, pdata); pdata->snd_card_on = false; ret = snd_soc_of_parse_card_name(card, "qcom,model"); if (ret) goto err; Loading @@ -980,8 +1015,12 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) ret); goto err; } mutex_init(&cdc_mclk_mutex); atomic_set(&mclk_rsc_ref, 0); /* initialize timer */ INIT_DELAYED_WORK(&pdata->enable_mclk_work, enable_mclk); pdata->snd_card_on = true; mutex_init(&pdata->cdc_mclk_mutex); atomic_set(&pdata->mclk_rsc_ref, 0); atomic_set(&pdata->dis_work_mclk, false); return 0; err: devm_kfree(&pdev->dev, pdata); Loading @@ -991,9 +1030,10 @@ err: static int msm8x16_asoc_machine_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); mutex_destroy(&cdc_mclk_mutex); mutex_destroy(&pdata->cdc_mclk_mutex); return 0; } Loading Loading
sound/soc/codecs/msm8x16-wcd.c +58 −8 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ #include <linux/regulator/consumer.h> #include <linux/mfd/wcd9xxx/pdata.h> #include <linux/qdsp6v2/apr.h> #include <linux/timer.h> #include <linux/workqueue.h> #include <linux/sched.h> #include <sound/q6afe-v2.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -215,8 +218,7 @@ static int msm8x16_wcd_ahb_write_device(u16 reg, u8 *value, u32 bytes) pr_debug("%s: q6 not ready %d\n", __func__, q6_state); return 0; } else pr_debug("%s: DSP is ready q6_state = %d\n", __func__, q6_state); pr_debug("%s: DSP is ready %d\n", __func__, q6_state); iowrite32(temp, ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR + offset, 4)); return 0; Loading Loading @@ -312,18 +314,42 @@ int msm8x16_wcd_spmi_write(unsigned short reg, int bytes, void *src) return msm8x16_wcd_spmi_write_device(reg, src, bytes); } static int __msm8x16_wcd_reg_read(struct msm8x16_wcd *msm8x16_wcd, static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec, unsigned short reg) { int ret = -EINVAL; u8 temp; struct msm8x16_wcd *msm8x16_wcd = codec->control_data; struct msm8916_asoc_mach_data *pdata = NULL; pr_debug("%s reg = %x\n", __func__, reg); mutex_lock(&msm8x16_wcd->io_lock); pdata = snd_soc_card_get_drvdata(codec->card); if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) ret = msm8x16_wcd_spmi_read(reg, 1, &temp); else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { if ((atomic_read(&pdata->mclk_rsc_ref) == 0) && (pdata->snd_card_on == true) && (atomic_read(&pdata->dis_work_mclk) == false)) { mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 9600000; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) { pr_err("failed to enable the MCLK\n"); return 0; } pr_debug("%s: MCLK not enabled\n", __func__); atomic_set(&pdata->dis_work_mclk, true); schedule_delayed_work(&pdata->enable_mclk_work, 50); ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp); mutex_unlock(&pdata->cdc_mclk_mutex); mutex_unlock(&msm8x16_wcd->io_lock); return temp; } ret = msm8x16_wcd_ahb_read_device(reg, 1, &temp); } mutex_unlock(&msm8x16_wcd->io_lock); if (ret < 0) { Loading @@ -339,16 +365,40 @@ static int __msm8x16_wcd_reg_read(struct msm8x16_wcd *msm8x16_wcd, return temp; } static int __msm8x16_wcd_reg_write(struct msm8x16_wcd *msm8x16_wcd, static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec, unsigned short reg, u8 val) { int ret = -EINVAL; struct msm8x16_wcd *msm8x16_wcd = codec->control_data; struct msm8916_asoc_mach_data *pdata = NULL; mutex_lock(&msm8x16_wcd->io_lock); pdata = snd_soc_card_get_drvdata(codec->card); if (MSM8X16_WCD_IS_TOMBAK_REG(reg)) ret = msm8x16_wcd_spmi_write(reg, 1, &val); else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) { if ((atomic_read(&pdata->mclk_rsc_ref) == 0) && (pdata->snd_card_on == true) && (atomic_read(&pdata->dis_work_mclk) == false)) { pr_debug("MCLK not enabled %s:\n", __func__); mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 9600000; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) { pr_err("failed to enable the MCLK\n"); return 0; } atomic_set(&pdata->dis_work_mclk, true); schedule_delayed_work(&pdata->enable_mclk_work, 50); ret = msm8x16_wcd_ahb_write_device(reg, &val, 1); mutex_unlock(&pdata->cdc_mclk_mutex); mutex_unlock(&msm8x16_wcd->io_lock); return ret; } ret = msm8x16_wcd_ahb_write_device(reg, &val, 1); } mutex_unlock(&msm8x16_wcd->io_lock); return ret; Loading Loading @@ -387,7 +437,7 @@ static int msm8x16_wcd_write(struct snd_soc_codec *codec, unsigned int reg, dev_err(codec->dev, "Cache write to %x failed: %d\n", reg, ret); } return __msm8x16_wcd_reg_write(codec->control_data, reg, (u8)value); return __msm8x16_wcd_reg_write(codec, reg, (u8)value); } static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, Loading @@ -414,7 +464,7 @@ static unsigned int msm8x16_wcd_read(struct snd_soc_codec *codec, dev_err(codec->dev, "Cache read from %x failed: %d\n", reg, ret); } val = __msm8x16_wcd_reg_read(codec->control_data, reg); val = __msm8x16_wcd_reg_read(codec, reg); dev_dbg(codec->dev, "%s: Read from reg 0x%x val 0x%x\n", __func__, reg, val); return val; Loading
sound/soc/codecs/msm8x16-wcd.h +13 −2 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <sound/soc.h> #include <sound/jack.h> #include <sound/q6afe-v2.h> #include <linux/mfd/wcd9xxx/pdata.h> #include "wcd-mbhc-v2.h" Loading Loading @@ -116,6 +117,16 @@ struct msm8x16_wcd_regulator { struct regulator *regulator; }; struct msm8916_asoc_mach_data { int codec_type; int snd_card_on; atomic_t mclk_rsc_ref; atomic_t dis_work_mclk; struct mutex cdc_mclk_mutex; struct delayed_work enable_mclk_work; struct afe_digital_clk_cfg digital_cdc_clk; }; struct msm8x16_wcd_pdata { int irq; int irq_base; Loading @@ -137,9 +148,9 @@ struct msm8x16_wcd { u8 version; int reset_gpio; int (*read_dev)(struct msm8x16_wcd *msm8x16, int (*read_dev)(struct snd_soc_codec *codec, unsigned short reg); int (*write_dev)(struct msm8x16_wcd *msm8x16, int (*write_dev)(struct snd_soc_codec *codec, unsigned short reg, u8 val); u32 num_of_supplies; Loading
sound/soc/msm/msm8x16.c +76 −36 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ #include <linux/qpnp/clkdiv.h> #include <linux/io.h> #include <linux/module.h> #include <linux/timer.h> #include <linux/workqueue.h> #include <linux/sched.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/soc-dapm.h> Loading @@ -44,6 +47,7 @@ static int msm_btsco_ch = 1; static int msm_ter_mi2s_tx_ch = 1; static int msm_proxy_rx_ch = 2; static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable, bool dapm); Loading Loading @@ -74,17 +78,6 @@ static struct afe_clk_cfg mi2s_tx_clk = { 0, }; struct msm8916_asoc_mach_data { int codec_type; }; static struct afe_digital_clk_cfg digital_cdc_clk = { AFE_API_VERSION_I2S_CONFIG, 9600000, 5, /* Digital Codec root */ 0, }; struct cdc_pdm_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *cdc_pdm_sus; Loading @@ -93,8 +86,6 @@ struct cdc_pdm_pinctrl_info { static struct cdc_pdm_pinctrl_info pinctrl_info; static atomic_t mclk_rsc_ref; static struct mutex cdc_mclk_mutex; static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static inline int param_is_mask(int p) Loading Loading @@ -313,30 +304,38 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable, bool dapm) { int ret = 0; struct msm8916_asoc_mach_data *pdata = NULL; mutex_lock(&cdc_mclk_mutex); pr_debug("%s: enable = %d codec name %s enable %d mclk ref counter %d\n", pdata = snd_soc_card_get_drvdata(codec->card); mutex_lock(&pdata->cdc_mclk_mutex); pr_err("%s: enable = %d codec name %s enable %d mclk ref counter %d\n", __func__, enable, codec->name, enable, atomic_read(&mclk_rsc_ref)); atomic_read(&pdata->mclk_rsc_ref)); if (enable) { if (atomic_inc_return(&mclk_rsc_ref) == 1) { digital_cdc_clk.clk_val = 9600000; if (atomic_inc_return(&pdata->mclk_rsc_ref) == 1) { pdata->digital_cdc_clk.clk_val = 9600000; afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_clk); &pdata->digital_cdc_clk); msm8x16_wcd_mclk_enable(codec, 1, dapm); cancel_delayed_work_sync(&pdata->enable_mclk_work); } } else { if (atomic_dec_return(&mclk_rsc_ref) == 0) { digital_cdc_clk.clk_val = 0; if (atomic_dec_return(&pdata->mclk_rsc_ref) == 0) { pdata->digital_cdc_clk.clk_val = 0; msm8x16_wcd_mclk_enable(codec, 0, dapm); afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_clk); &pdata->digital_cdc_clk); if (atomic_read(&pdata->dis_work_mclk) == true) { pr_debug("add work in disable of %s\n", __func__); schedule_delayed_work( &pdata->enable_mclk_work, 10); } } } mutex_unlock(&cdc_mclk_mutex); mutex_unlock(&pdata->cdc_mclk_mutex); return ret; } Loading @@ -357,19 +356,14 @@ static int msm8x16_mclk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { pr_debug("%s: event = %d\n", __func__, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: return msm8x16_enable_codec_ext_clk(w->codec, 1, true); case SND_SOC_DAPM_POST_PMD: return msm8x16_enable_codec_ext_clk(w->codec, 0, true); default: return -EINVAL; } return 0; } static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) { int ret; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; pr_debug("%s(): substream = %s stream = %d\n", __func__, substream->name, substream->stream); Loading @@ -379,6 +373,9 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) pr_err("%s:clock disable failed\n", __func__); pinctrl_select_state(pinctrl_info.pinctrl, pinctrl_info.cdc_pdm_sus); ret = msm8x16_enable_codec_ext_clk(codec, 0, true); if (ret < 0) pr_err("failed to disable the mclk\n"); } static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) Loading @@ -386,6 +383,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int ret = 0; int val = 0; Loading @@ -405,6 +403,11 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) val = val | 0x00200000; iowrite32(val, ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL , 4)); } ret = msm8x16_enable_codec_ext_clk(codec, 1, true); if (ret < 0) { pr_err("failed to enable mclk\n"); return ret; } ret = pinctrl_select_state(pinctrl_info.pinctrl, pinctrl_info.cdc_pdm_act); Loading Loading @@ -900,6 +903,32 @@ static int cdc_pdm_get_pinctrl(struct platform_device *pdev) return 0; } void enable_mclk(struct work_struct *work) { struct msm8916_asoc_mach_data *pdata = NULL; struct delayed_work *dwork; int ret = 0; pr_info("%s:\n", __func__); dwork = to_delayed_work(work); pdata = container_of(dwork, struct msm8916_asoc_mach_data, enable_mclk_work); if (atomic_read(&pdata->mclk_rsc_ref) == 0) { if (atomic_read(&pdata->dis_work_mclk) == true) { pr_debug("clock enabled now disable\n"); mutex_lock(&pdata->cdc_mclk_mutex); pdata->digital_cdc_clk.clk_val = 0; ret = afe_set_digital_codec_core_clock( AFE_PORT_ID_PRIMARY_MI2S_RX, &pdata->digital_cdc_clk); if (ret < 0) pr_err("failed to disable the MCLK\n"); atomic_set(&pdata->dis_work_mclk, false); mutex_unlock(&pdata->cdc_mclk_mutex); } } } static int msm8x16_asoc_machine_probe(struct platform_device *pdev) { struct snd_soc_card *card; Loading Loading @@ -949,7 +978,12 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) dev_info(&pdev->dev, "default codec configured\n"); pdata->codec_type = 0; } /* initialize the mclk */ pdata->digital_cdc_clk.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; pdata->digital_cdc_clk.clk_val = 9600000; pdata->digital_cdc_clk.clk_root = 5; pdata->digital_cdc_clk.reserved = 0; ret = cdc_pdm_get_pinctrl(pdev); if (ret < 0) { pr_err("failed to get the pdm gpios\n"); Loading @@ -965,6 +999,7 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, pdata); pdata->snd_card_on = false; ret = snd_soc_of_parse_card_name(card, "qcom,model"); if (ret) goto err; Loading @@ -980,8 +1015,12 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) ret); goto err; } mutex_init(&cdc_mclk_mutex); atomic_set(&mclk_rsc_ref, 0); /* initialize timer */ INIT_DELAYED_WORK(&pdata->enable_mclk_work, enable_mclk); pdata->snd_card_on = true; mutex_init(&pdata->cdc_mclk_mutex); atomic_set(&pdata->mclk_rsc_ref, 0); atomic_set(&pdata->dis_work_mclk, false); return 0; err: devm_kfree(&pdev->dev, pdata); Loading @@ -991,9 +1030,10 @@ err: static int msm8x16_asoc_machine_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); mutex_destroy(&cdc_mclk_mutex); mutex_destroy(&pdata->cdc_mclk_mutex); return 0; } Loading