Merge commit '33ea77356f47c6c596c8505ca90307fc1245ef3f' into audio-kernel-5-4.lnx.1.0

Change-Id: Iacb389506a643a1ac70a3d51c2dfc1eeb47f690c
This commit is contained in:
Phani Kumar Uppalapati
2020-07-21 18:31:26 -07:00
committed by Ashish Jain
60 changed files with 2849 additions and 1073 deletions

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef _BENGAL_PORT_CONFIG #ifndef _BENGAL_PORT_CONFIG
@@ -21,6 +21,15 @@ static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
{0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0}, {0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0},
}; };
static struct port_params rx_frame_params_rouleur[SWR_MSTR_PORT_LEN] = {
{3, 0, 0, 0xFF, 0xFF, 1, 0xFF, 0xFF, 1},
{31, 0, 0, 3, 6, 7, 0, 0xFF, 0},
{31, 1, 0, 0xFF, 0xFF, 4, 1, 0xFF, 0},
{7, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},
{0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0},
};
static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = { static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
{3, 0, 0, 0xFF, 0xFF, 1, 0xFF, 0xFF, 1}, {3, 0, 0, 0xFF, 0xFF, 1, 0xFF, 0xFF, 1},
{31, 0, 0, 3, 6, 7, 0, 0xFF, 0}, {31, 0, 0, 3, 6, 7, 0, 0xFF, 0},
@@ -42,4 +51,9 @@ static struct swr_mstr_port_map sm_port_map[] = {
{RX_MACRO, SWR_UC1, rx_frame_params_dsd}, {RX_MACRO, SWR_UC1, rx_frame_params_dsd},
}; };
static struct swr_mstr_port_map sm_port_map_rouleur[] = {
{VA_MACRO, SWR_UC0, tx_frame_params_default},
{RX_MACRO, SWR_UC0, rx_frame_params_rouleur},
{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
};
#endif /* _BENGAL_PORT_CONFIG */ #endif /* _BENGAL_PORT_CONFIG */

View File

@@ -59,10 +59,12 @@
#define WCD9XXX_MBHC_DEF_RLOADS 5 #define WCD9XXX_MBHC_DEF_RLOADS 5
#define WCD9XXX_MBHC_DEF_BUTTONS 8 #define WCD9XXX_MBHC_DEF_BUTTONS 8
#define ROULEUR_MBHC_DEF_BUTTONS 5
#define CODEC_EXT_CLK_RATE 9600000 #define CODEC_EXT_CLK_RATE 9600000
#define ADSP_STATE_READY_TIMEOUT_MS 3000 #define ADSP_STATE_READY_TIMEOUT_MS 3000
#define DEV_NAME_STR_LEN 32 #define DEV_NAME_STR_LEN 32
#define WCD_MBHC_HS_V_MAX 1600 #define WCD_MBHC_HS_V_MAX 1600
#define ROULEUR_MBHC_HS_V_MAX 1700
#define TDM_CHANNEL_MAX 8 #define TDM_CHANNEL_MAX 8
#define DEV_NAME_STR_LEN 32 #define DEV_NAME_STR_LEN 32
@@ -555,6 +557,7 @@ static int dmic_0_1_gpio_cnt;
static int dmic_2_3_gpio_cnt; static int dmic_2_3_gpio_cnt;
static void *def_wcd_mbhc_cal(void); static void *def_wcd_mbhc_cal(void);
static void *def_rouleur_mbhc_cal(void);
/* /*
* Need to report LINEIN * Need to report LINEIN
@@ -4259,6 +4262,9 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm; struct snd_soc_dapm_context *dapm;
struct snd_card *card; struct snd_card *card;
struct snd_info_entry *entry; struct snd_info_entry *entry;
struct platform_device *pdev = NULL;
int i = 0;
char *data = NULL;
struct msm_asoc_mach_data *pdata = struct msm_asoc_mach_data *pdata =
snd_soc_card_get_drvdata(rtd->card); snd_soc_card_get_drvdata(rtd->card);
@@ -4305,8 +4311,38 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
bolero_set_port_map(component, ARRAY_SIZE(sm_port_map), for (i = 0; i < rtd->card->num_aux_devs; i++)
{
if (msm_aux_dev[i].name != NULL ) {
if (strstr(msm_aux_dev[i].name, "wsa"))
continue;
}
if (msm_aux_dev[i].codec_of_node) {
pdev = of_find_device_by_node(
msm_aux_dev[i].codec_of_node);
if (pdev)
data = (char*) of_device_get_match_data(
&pdev->dev);
if (data != NULL) {
if (!strncmp(data, "wcd937x",
sizeof("wcd937x"))) {
bolero_set_port_map(component,
ARRAY_SIZE(sm_port_map),
sm_port_map); sm_port_map);
break;
} else if (!strncmp( data, "rouleur",
sizeof("rouleur"))) {
bolero_set_port_map(component,
ARRAY_SIZE(sm_port_map_rouleur),
sm_port_map_rouleur);
break;
}
}
}
}
card = rtd->card->snd_card; card = rtd->card->snd_card;
if (!pdata->codec_root) { if (!pdata->codec_root) {
entry = snd_info_create_subdir(card->module, "codecs", entry = snd_info_create_subdir(card->module, "codecs",
@@ -4356,6 +4392,34 @@ static void *def_wcd_mbhc_cal(void)
return wcd_mbhc_cal; return wcd_mbhc_cal;
} }
static void *def_rouleur_mbhc_cal(void)
{
void *wcd_mbhc_cal;
struct wcd_mbhc_btn_detect_cfg *btn_cfg;
u16 *btn_high;
wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(ROULEUR_MBHC_DEF_BUTTONS,
WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
if (!wcd_mbhc_cal)
return NULL;
WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->v_hs_max =
ROULEUR_MBHC_HS_V_MAX;
WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->num_btn =
ROULEUR_MBHC_DEF_BUTTONS;
btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
btn_high = ((void *)&btn_cfg->_v_btn_low) +
(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
btn_high[0] = 75;
btn_high[1] = 150;
btn_high[2] = 237;
btn_high[3] = 500;
btn_high[4] = 500;
return wcd_mbhc_cal;
}
/* Digital audio interface glue - connects codec <---> CPU */ /* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm_common_dai_links[] = { static struct snd_soc_dai_link msm_common_dai_links[] = {
/* FrontEnd DAI Links */ /* FrontEnd DAI Links */
@@ -4985,6 +5049,22 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST, .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ops = &msm_cdc_dma_be_ops, .ops = &msm_cdc_dma_be_ops,
}, },
{/* hw:x,39 */
.name = MSM_DAILINK_NAME(Compress3),
.stream_name = "Compress3",
.cpu_dai_name = "MultiMedia10",
.platform_name = "msm-compress-dsp",
.dynamic = 1,
.dpcm_playback = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dainlink has playback support */
.id = MSM_FRONTEND_DAI_MULTIMEDIA10,
},
}; };
static struct snd_soc_dai_link msm_common_be_dai_links[] = { static struct snd_soc_dai_link msm_common_be_dai_links[] = {
@@ -5075,6 +5155,33 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
.ignore_suspend = 1, .ignore_suspend = 1,
.ignore_pmdown_time = 1, .ignore_pmdown_time = 1,
}, },
/* Proxy Tx BACK END DAI Link */
{
.name = LPASS_BE_PROXY_TX,
.stream_name = "Proxy Capture",
.cpu_dai_name = "msm-dai-q6-dev.8195",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.id = MSM_BACKEND_DAI_PROXY_TX,
.ignore_suspend = 1,
},
/* Proxy Rx BACK END DAI Link */
{
.name = LPASS_BE_PROXY_RX,
.stream_name = "Proxy Playback",
.cpu_dai_name = "msm-dai-q6-dev.8194",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_PROXY_RX,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{ {
.name = LPASS_BE_USB_AUDIO_RX, .name = LPASS_BE_USB_AUDIO_RX,
.stream_name = "USB Audio Playback", .stream_name = "USB Audio Playback",
@@ -6115,16 +6222,21 @@ static int msm_aux_codec_init(struct snd_soc_component *component)
} }
mbhc_cfg_cal: mbhc_cfg_cal:
if (data != NULL) {
if (!strncmp(data, "wcd937x", sizeof("wcd937x"))) {
mbhc_calibration = def_wcd_mbhc_cal(); mbhc_calibration = def_wcd_mbhc_cal();
if (!mbhc_calibration) if (!mbhc_calibration)
return -ENOMEM; return -ENOMEM;
wcd_mbhc_cfg.calibration = mbhc_calibration; wcd_mbhc_cfg.calibration = mbhc_calibration;
if (data != NULL) {
if (!strncmp(data, "wcd937x", sizeof("wcd937x")))
ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg); ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
else if (!strncmp( data, "rouleur", sizeof("rouleur"))) } else if (!strncmp( data, "rouleur", sizeof("rouleur"))) {
mbhc_calibration = def_rouleur_mbhc_cal();
if (!mbhc_calibration)
return -ENOMEM;
wcd_mbhc_cfg.calibration = mbhc_calibration;
ret = rouleur_mbhc_hs_detect(component, &wcd_mbhc_cfg); ret = rouleur_mbhc_hs_detect(component, &wcd_mbhc_cfg);
} }
}
if (ret) { if (ret) {
dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n", dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
@@ -6714,10 +6826,16 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
} }
buf = nvmem_cell_read(cell, &len); buf = nvmem_cell_read(cell, &len);
nvmem_cell_put(cell); nvmem_cell_put(cell);
if (IS_ERR_OR_NULL(buf) || len <= 0 || len > sizeof(32)) { if (IS_ERR_OR_NULL(buf)) {
dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__); dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__);
goto ret; goto ret;
} }
if (len <= 0 || len > sizeof(u32)) {
dev_dbg(&pdev->dev, "%s: nvmem cell length out of range: %d\n",
__func__, len);
kfree(buf);
goto ret;
}
memcpy(&adsp_var_idx, buf, len); memcpy(&adsp_var_idx, buf, len);
kfree(buf); kfree(buf);
va_disable = adsp_var_idx; va_disable = adsp_var_idx;

View File

@@ -600,6 +600,28 @@ int bolero_dmic_clk_enable(struct snd_soc_component *component,
} }
EXPORT_SYMBOL(bolero_dmic_clk_enable); EXPORT_SYMBOL(bolero_dmic_clk_enable);
bool bolero_is_va_macro_registered(struct device *dev)
{
struct bolero_priv *priv;
if (!dev) {
pr_err("%s: dev is null\n", __func__);
return false;
}
if (!bolero_is_valid_child_dev(dev)) {
dev_err(dev, "%s: child device calling is not added yet\n",
__func__);
return false;
}
priv = dev_get_drvdata(dev->parent);
if (!priv) {
dev_err(dev, "%s: priv is null\n", __func__);
return false;
}
return priv->macros_supported[VA_MACRO];
}
EXPORT_SYMBOL(bolero_is_va_macro_registered);
/** /**
* bolero_register_macro - Registers macro to bolero * bolero_register_macro - Registers macro to bolero
* *
@@ -644,7 +666,6 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
bolero_mclk_mux_tbl[macro_id][MCLK_MUX0]; bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
if (macro_id == TX_MACRO) { if (macro_id == TX_MACRO) {
priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq; priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq;
priv->macro_params[macro_id].clk_switch = ops->clk_switch;
priv->macro_params[macro_id].reg_evt_listener = priv->macro_params[macro_id].reg_evt_listener =
ops->reg_evt_listener; ops->reg_evt_listener;
priv->macro_params[macro_id].clk_enable = ops->clk_enable; priv->macro_params[macro_id].clk_enable = ops->clk_enable;
@@ -661,7 +682,7 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
priv->num_macros_registered++; priv->num_macros_registered++;
priv->macros_supported[macro_id] = true; priv->macros_supported[macro_id] = true;
dev_dbg(dev, "%s: register macro successful:%d\n", macro_id); dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id);
if (priv->num_macros_registered == priv->num_macros) { if (priv->num_macros_registered == priv->num_macros) {
ret = bolero_copy_dais_from_macro(priv); ret = bolero_copy_dais_from_macro(priv);
@@ -719,7 +740,6 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id)
priv->macro_params[macro_id].dev = NULL; priv->macro_params[macro_id].dev = NULL;
if (macro_id == TX_MACRO) { if (macro_id == TX_MACRO) {
priv->macro_params[macro_id].reg_wake_irq = NULL; priv->macro_params[macro_id].reg_wake_irq = NULL;
priv->macro_params[macro_id].clk_switch = NULL;
priv->macro_params[macro_id].reg_evt_listener = NULL; priv->macro_params[macro_id].reg_evt_listener = NULL;
priv->macro_params[macro_id].clk_enable = NULL; priv->macro_params[macro_id].clk_enable = NULL;
} }
@@ -836,6 +856,18 @@ static int bolero_ssr_enable(struct device *dev, void *data)
BOLERO_MACRO_EVT_CLK_RESET, 0x0); BOLERO_MACRO_EVT_CLK_RESET, 0x0);
} }
trace_printk("%s: clk count reset\n", __func__); trace_printk("%s: clk count reset\n", __func__);
if (priv->rsc_clk_cb)
priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_GFMUX_UP);
for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
if (!priv->macro_params[macro_idx].event_handler)
continue;
priv->macro_params[macro_idx].event_handler(
priv->component,
BOLERO_MACRO_EVT_PRE_SSR_UP, 0x0);
}
regcache_cache_only(priv->regmap, false); regcache_cache_only(priv->regmap, false);
mutex_lock(&priv->clk_lock); mutex_lock(&priv->clk_lock);
priv->dev_up = true; priv->dev_up = true;
@@ -1004,40 +1036,6 @@ int bolero_register_wake_irq(struct snd_soc_component *component,
} }
EXPORT_SYMBOL(bolero_register_wake_irq); EXPORT_SYMBOL(bolero_register_wake_irq);
/**
* bolero_tx_clk_switch - Switch tx macro clock
*
* @component: pointer to codec component instance.
*
* @clk_src: 0 for TX_RCG and 1 for VA_RCG
*
* Returns 0 on success or -EINVAL on error.
*/
int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src)
{
struct bolero_priv *priv = NULL;
int ret = 0;
if (!component)
return -EINVAL;
priv = snd_soc_component_get_drvdata(component);
if (!priv)
return -EINVAL;
if (!bolero_is_valid_codec_dev(priv->dev)) {
dev_err(component->dev, "%s: invalid codec\n", __func__);
return -EINVAL;
}
if (priv->macro_params[TX_MACRO].clk_switch)
ret = priv->macro_params[TX_MACRO].clk_switch(component,
clk_src);
return ret;
}
EXPORT_SYMBOL(bolero_tx_clk_switch);
/** /**
* bolero_tx_mclk_enable - Enable/Disable TX Macro mclk * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk
* *

View File

@@ -37,11 +37,6 @@ enum {
BOLERO_ADC_MAX BOLERO_ADC_MAX
}; };
enum {
CLK_SRC_TX_RCG = 0,
CLK_SRC_VA_RCG,
};
enum { enum {
BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */ BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */ BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */
@@ -52,7 +47,9 @@ enum {
BOLERO_MACRO_EVT_CLK_RESET, BOLERO_MACRO_EVT_CLK_RESET,
BOLERO_MACRO_EVT_REG_WAKE_IRQ, BOLERO_MACRO_EVT_REG_WAKE_IRQ,
BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST,
BOLERO_MACRO_EVT_BCS_CLK_OFF BOLERO_MACRO_EVT_BCS_CLK_OFF,
BOLERO_MACRO_EVT_SSR_GFMUX_UP,
BOLERO_MACRO_EVT_PRE_SSR_UP,
}; };
enum { enum {
@@ -74,7 +71,6 @@ struct macro_ops {
int (*set_port_map)(struct snd_soc_component *component, u32 uc, int (*set_port_map)(struct snd_soc_component *component, u32 uc,
u32 size, void *data); u32 size, void *data);
int (*clk_div_get)(struct snd_soc_component *component); int (*clk_div_get)(struct snd_soc_component *component);
int (*clk_switch)(struct snd_soc_component *component, int clk_src);
int (*reg_evt_listener)(struct snd_soc_component *component, bool en); int (*reg_evt_listener)(struct snd_soc_component *component, bool en);
int (*clk_enable)(struct snd_soc_component *c, bool en); int (*clk_enable)(struct snd_soc_component *c, bool en);
char __iomem *io_base; char __iomem *io_base;
@@ -87,6 +83,7 @@ typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event);
#if IS_ENABLED(CONFIG_SND_SOC_BOLERO) #if IS_ENABLED(CONFIG_SND_SOC_BOLERO)
int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb); int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb);
void bolero_unregister_res_clk(struct device *dev); void bolero_unregister_res_clk(struct device *dev);
bool bolero_is_va_macro_registered(struct device *dev);
int bolero_register_macro(struct device *dev, u16 macro_id, int bolero_register_macro(struct device *dev, u16 macro_id,
struct macro_ops *ops); struct macro_ops *ops);
void bolero_unregister_macro(struct device *dev, u16 macro_id); void bolero_unregister_macro(struct device *dev, u16 macro_id);
@@ -100,7 +97,6 @@ void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n);
int bolero_runtime_resume(struct device *dev); int bolero_runtime_resume(struct device *dev);
int bolero_runtime_suspend(struct device *dev); int bolero_runtime_suspend(struct device *dev);
int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data);
int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src);
int bolero_register_event_listener(struct snd_soc_component *component, int bolero_register_event_listener(struct snd_soc_component *component,
bool enable); bool enable);
void bolero_wsa_pa_on(struct device *dev); void bolero_wsa_pa_on(struct device *dev);
@@ -118,6 +114,11 @@ static inline void bolero_unregister_res_clk(struct device *dev)
{ {
} }
static bool bolero_is_va_macro_registered(struct device *dev)
{
return false;
}
static inline int bolero_register_macro(struct device *dev, static inline int bolero_register_macro(struct device *dev,
u16 macro_id, u16 macro_id,
struct macro_ops *ops) struct macro_ops *ops)
@@ -168,12 +169,6 @@ static inline int bolero_set_port_map(struct snd_soc_component *component,
return 0; return 0;
} }
static inline int bolero_tx_clk_switch(struct snd_soc_component *component,
int clk_src)
{
return 0;
}
static inline int bolero_register_event_listener( static inline int bolero_register_event_listener(
struct snd_soc_component *component, struct snd_soc_component *component,
bool enable) bool enable)

View File

@@ -38,6 +38,7 @@ struct bolero_clk_rsc {
int reg_seq_en_cnt; int reg_seq_en_cnt;
int va_tx_clk_cnt; int va_tx_clk_cnt;
bool dev_up; bool dev_up;
bool dev_up_gfmux;
u32 num_fs_reg; u32 num_fs_reg;
u32 *fs_gen_seq; u32 *fs_gen_seq;
int default_clk_id[MAX_CLK]; int default_clk_id[MAX_CLK];
@@ -65,10 +66,14 @@ static int bolero_clk_rsc_cb(struct device *dev, u16 event)
} }
mutex_lock(&priv->rsc_clk_lock); mutex_lock(&priv->rsc_clk_lock);
if (event == BOLERO_MACRO_EVT_SSR_UP) if (event == BOLERO_MACRO_EVT_SSR_UP) {
priv->dev_up = true; priv->dev_up = true;
else if (event == BOLERO_MACRO_EVT_SSR_DOWN) } else if (event == BOLERO_MACRO_EVT_SSR_DOWN) {
priv->dev_up = false; priv->dev_up = false;
priv->dev_up_gfmux = false;
} else if (event == BOLERO_MACRO_EVT_SSR_GFMUX_UP) {
priv->dev_up_gfmux = true;
}
mutex_unlock(&priv->rsc_clk_lock); mutex_unlock(&priv->rsc_clk_lock);
return 0; return 0;
@@ -282,10 +287,12 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv,
* care in DSP itself * care in DSP itself
*/ */
if (clk_id != VA_CORE_CLK) { if (clk_id != VA_CORE_CLK) {
if (priv->dev_up_gfmux) {
iowrite32(0x1, clk_muxsel); iowrite32(0x1, clk_muxsel);
muxsel = ioread32(clk_muxsel); muxsel = ioread32(clk_muxsel);
trace_printk("%s: muxsel value after enable: %d\n", trace_printk("%s: muxsel value after enable: %d\n",
__func__, muxsel); __func__, muxsel);
}
bolero_clk_rsc_mux0_clk_request(priv, bolero_clk_rsc_mux0_clk_request(priv,
default_clk_id, default_clk_id,
false); false);
@@ -313,12 +320,14 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv,
* This configuration would be taken * This configuration would be taken
* care in DSP itself. * care in DSP itself.
*/ */
if (priv->dev_up_gfmux) {
iowrite32(0x0, clk_muxsel); iowrite32(0x0, clk_muxsel);
muxsel = ioread32(clk_muxsel); muxsel = ioread32(clk_muxsel);
trace_printk("%s: muxsel value after disable: %d\n", trace_printk("%s: muxsel value after disable: %d\n",
__func__, muxsel); __func__, muxsel);
} }
} }
}
if (priv->clk[clk_id + NPL_CLK_OFFSET]) if (priv->clk[clk_id + NPL_CLK_OFFSET])
clk_disable_unprepare( clk_disable_unprepare(
priv->clk[clk_id + NPL_CLK_OFFSET]); priv->clk[clk_id + NPL_CLK_OFFSET]);
@@ -706,6 +715,7 @@ static int bolero_clk_rsc_probe(struct platform_device *pdev)
} }
priv->dev = &pdev->dev; priv->dev = &pdev->dev;
priv->dev_up = true; priv->dev_up = true;
priv->dev_up_gfmux = true;
mutex_init(&priv->rsc_clk_lock); mutex_init(&priv->rsc_clk_lock);
mutex_init(&priv->fs_gen_lock); mutex_init(&priv->fs_gen_lock);
dev_set_drvdata(&pdev->dev, priv); dev_set_drvdata(&pdev->dev, priv);

View File

@@ -387,6 +387,7 @@ enum {
RX_MACRO_AIF3_PB, RX_MACRO_AIF3_PB,
RX_MACRO_AIF4_PB, RX_MACRO_AIF4_PB,
RX_MACRO_AIF_ECHO, RX_MACRO_AIF_ECHO,
RX_MACRO_AIF5_PB,
RX_MACRO_AIF6_PB, RX_MACRO_AIF6_PB,
RX_MACRO_MAX_DAIS, RX_MACRO_MAX_DAIS,
}; };
@@ -719,6 +720,20 @@ static struct snd_soc_dai_driver rx_macro_dai[] = {
}, },
.ops = &rx_macro_dai_ops, .ops = &rx_macro_dai_ops,
}, },
{
.name = "rx_macro_rx5",
.id = RX_MACRO_AIF5_PB,
.playback = {
.stream_name = "RX_MACRO_AIF5 Playback",
.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
.formats = RX_MACRO_FORMATS,
.rate_max = 384000,
.rate_min = 8000,
.channels_min = 1,
.channels_max = 4,
},
.ops = &rx_macro_dai_ops,
},
{ {
.name = "rx_macro_rx6", .name = "rx_macro_rx6",
.id = RX_MACRO_AIF6_PB, .id = RX_MACRO_AIF6_PB,
@@ -1138,6 +1153,13 @@ static int rx_macro_get_channel_map(struct snd_soc_dai *dai,
"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n", "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n",
__func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]); __func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]);
break; break;
case RX_MACRO_AIF5_PB:
*rx_slot = 0x1;
*rx_num = 0x01;
dev_dbg(rx_priv->dev,
"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
__func__, dai->id, *rx_slot, *rx_num);
break;
case RX_MACRO_AIF6_PB: case RX_MACRO_AIF6_PB:
*rx_slot = 0x1; *rx_slot = 0x1;
*rx_num = 0x01; *rx_num = 0x01;
@@ -1410,11 +1432,7 @@ static int rx_macro_event_handler(struct snd_soc_component *component,
} }
} }
break; break;
case BOLERO_MACRO_EVT_SSR_UP: case BOLERO_MACRO_EVT_PRE_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
rx_priv->dev_up = true;
/* reset swr after ssr/pdr */
rx_priv->reset_swr = true;
/* enable&disable RX_CORE_CLK to reset GFMUX reg */ /* enable&disable RX_CORE_CLK to reset GFMUX reg */
ret = bolero_clk_rsc_request_clock(rx_priv->dev, ret = bolero_clk_rsc_request_clock(rx_priv->dev,
rx_priv->default_clk_id, rx_priv->default_clk_id,
@@ -1427,6 +1445,12 @@ static int rx_macro_event_handler(struct snd_soc_component *component,
bolero_clk_rsc_request_clock(rx_priv->dev, bolero_clk_rsc_request_clock(rx_priv->dev,
rx_priv->default_clk_id, rx_priv->default_clk_id,
RX_CORE_CLK, false); RX_CORE_CLK, false);
break;
case BOLERO_MACRO_EVT_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
rx_priv->dev_up = true;
/* reset swr after ssr/pdr */
rx_priv->reset_swr = true;
if (rx_priv->swr_ctrl_data) if (rx_priv->swr_ctrl_data)
swrm_wcd_notify( swrm_wcd_notify(
@@ -1709,13 +1733,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component,
dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n", dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n",
__func__, event, comp + 1, rx_priv->comp_enabled[comp]); __func__, event, comp + 1, rx_priv->comp_enabled[comp]);
if (!rx_priv->comp_enabled[comp])
return 0;
comp_ctl0_reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
(comp * RX_MACRO_COMP_OFFSET);
rx_path_cfg0_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0 +
(comp * RX_MACRO_RX_PATH_OFFSET);
rx_path_cfg3_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG3 + rx_path_cfg3_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG3 +
(comp * RX_MACRO_RX_PATH_OFFSET); (comp * RX_MACRO_RX_PATH_OFFSET);
rx0_path_ctl_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + rx0_path_ctl_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL +
@@ -1731,6 +1748,19 @@ static int rx_macro_config_compander(struct snd_soc_component *component,
else else
val = 0x00; val = 0x00;
if (SND_SOC_DAPM_EVENT_ON(event))
snd_soc_component_update_bits(component, rx_path_cfg3_reg,
0x03, val);
if (SND_SOC_DAPM_EVENT_OFF(event))
snd_soc_component_update_bits(component, rx_path_cfg3_reg,
0x03, 0x03);
if (!rx_priv->comp_enabled[comp])
return 0;
comp_ctl0_reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
(comp * RX_MACRO_COMP_OFFSET);
rx_path_cfg0_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0 +
(comp * RX_MACRO_RX_PATH_OFFSET);
if (SND_SOC_DAPM_EVENT_ON(event)) { if (SND_SOC_DAPM_EVENT_ON(event)) {
/* Enable Compander Clock */ /* Enable Compander Clock */
snd_soc_component_update_bits(component, comp_ctl0_reg, snd_soc_component_update_bits(component, comp_ctl0_reg,
@@ -1741,8 +1771,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component,
0x02, 0x00); 0x02, 0x00);
snd_soc_component_update_bits(component, rx_path_cfg0_reg, snd_soc_component_update_bits(component, rx_path_cfg0_reg,
0x02, 0x02); 0x02, 0x02);
snd_soc_component_update_bits(component, rx_path_cfg3_reg,
0x03, val);
} }
if (SND_SOC_DAPM_EVENT_OFF(event)) { if (SND_SOC_DAPM_EVENT_OFF(event)) {
@@ -1754,8 +1782,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component,
0x01, 0x00); 0x01, 0x00);
snd_soc_component_update_bits(component, comp_ctl0_reg, snd_soc_component_update_bits(component, comp_ctl0_reg,
0x04, 0x00); 0x04, 0x00);
snd_soc_component_update_bits(component, rx_path_cfg3_reg,
0x03, 0x03);
} }
return 0; return 0;
@@ -1930,6 +1956,11 @@ static int rx_macro_config_classh(struct snd_soc_component *component,
0x40, 0x40); 0x40, 0x40);
break; break;
case INTERP_HPHR: case INTERP_HPHR:
if (rx_priv->is_ear_mode_on)
snd_soc_component_update_bits(component,
BOLERO_CDC_RX_CLSH_HPH_V_PA,
0x3F, 0x39);
else
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
BOLERO_CDC_RX_CLSH_HPH_V_PA, BOLERO_CDC_RX_CLSH_HPH_V_PA,
0x3F, 0x1C); 0x3F, 0x1C);
@@ -2988,21 +3019,24 @@ static int rx_macro_set_iir_gain(struct snd_soc_dapm_widget *w,
} }
static const struct snd_kcontrol_new rx_macro_snd_controls[] = { static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
SOC_SINGLE_SX_TLV("RX_RX0 Digital Volume", SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume",
BOLERO_CDC_RX_RX0_RX_VOL_CTL, BOLERO_CDC_RX_RX0_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX_RX1 Digital Volume", SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume",
BOLERO_CDC_RX_RX1_RX_VOL_CTL, BOLERO_CDC_RX_RX1_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX_RX2 Digital Volume", SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume",
BOLERO_CDC_RX_RX2_RX_VOL_CTL, BOLERO_CDC_RX_RX2_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX_RX0 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume",
BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL,
SOC_SINGLE_SX_TLV("RX_RX1 Mix Digital Volume", -84, 40, digital_gain),
BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume",
SOC_SINGLE_SX_TLV("RX_RX2 Mix Digital Volume", BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL,
BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume",
BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL,
-84, 40, digital_gain),
SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0, SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0,
rx_macro_get_compander, rx_macro_set_compander), rx_macro_get_compander, rx_macro_set_compander),
@@ -3031,29 +3065,29 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = {
rx_macro_aux_hpf_mode_get, rx_macro_aux_hpf_mode_get,
rx_macro_aux_hpf_mode_put), rx_macro_aux_hpf_mode_put),
SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40, BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0, SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
@@ -3179,6 +3213,9 @@ static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0, SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0,
SND_SOC_NOPM, 0, 0), SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0,
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0, SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0,
SND_SOC_NOPM, 0, 0), SND_SOC_NOPM, 0, 0),
@@ -3849,6 +3886,7 @@ static int rx_macro_init(struct snd_soc_component *component)
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback");
snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT"); snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT");
snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT"); snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT");
@@ -4016,6 +4054,12 @@ static int rx_macro_probe(struct platform_device *pdev)
u32 is_used_rx_swr_gpio = 1; u32 is_used_rx_swr_gpio = 1;
const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio"; const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
if (!bolero_is_va_macro_registered(&pdev->dev)) {
dev_err(&pdev->dev,
"%s: va-macro not registered yet, defer\n", __func__);
return -EPROBE_DEFER;
}
rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv), rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
GFP_KERNEL); GFP_KERNEL);
if (!rx_priv) if (!rx_priv)

View File

@@ -176,6 +176,7 @@ struct tx_macro_priv {
int bcs_ch; int bcs_ch;
bool bcs_clk_en; bool bcs_clk_en;
bool hs_slow_insert_complete; bool hs_slow_insert_complete;
int amic_sample_rate;
}; };
static bool tx_macro_get_data(struct snd_soc_component *component, static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -411,6 +412,9 @@ static int tx_macro_event_handler(struct snd_soc_component *component,
else else
tx_priv->hs_slow_insert_complete = false; tx_priv->hs_slow_insert_complete = false;
break; break;
default:
pr_debug("%s Invalid Event\n", __func__);
break;
} }
return 0; return 0;
} }
@@ -497,6 +501,29 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
hpf_cut_off_freq << 5); hpf_cut_off_freq << 5);
snd_soc_component_update_bits(component, hpf_gate_reg, snd_soc_component_update_bits(component, hpf_gate_reg,
0x03, 0x02); 0x03, 0x02);
/* Add delay between toggle hpf gate based on sample rate */
switch(tx_priv->amic_sample_rate) {
case 8000:
usleep_range(125, 130);
break;
case 16000:
usleep_range(62, 65);
break;
case 32000:
usleep_range(31, 32);
break;
case 48000:
usleep_range(20, 21);
break;
case 96000:
usleep_range(10, 11);
break;
case 192000:
usleep_range(5, 6);
break;
default:
usleep_range(125, 130);
}
snd_soc_component_update_bits(component, hpf_gate_reg, snd_soc_component_update_bits(component, hpf_gate_reg,
0x03, 0x01); 0x03, 0x01);
} else { } else {
@@ -932,6 +959,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
u16 dec_cfg_reg = 0; u16 dec_cfg_reg = 0;
u16 hpf_gate_reg = 0; u16 hpf_gate_reg = 0;
u16 tx_gain_ctl_reg = 0; u16 tx_gain_ctl_reg = 0;
u16 tx_fs_reg = 0;
u8 hpf_cut_off_freq = 0; u8 hpf_cut_off_freq = 0;
u16 adc_mux_reg = 0; u16 adc_mux_reg = 0;
int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
@@ -957,6 +985,11 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
TX_MACRO_TX_PATH_OFFSET * decimator; TX_MACRO_TX_PATH_OFFSET * decimator;
adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL +
TX_MACRO_TX_PATH_OFFSET * decimator;
tx_priv->amic_sample_rate = (snd_soc_component_read32(component,
tx_fs_reg) & 0x0F);
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
@@ -2362,18 +2395,18 @@ static const struct snd_soc_dapm_route tx_audio_map[] = {
}; };
static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = { static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = {
SOC_SINGLE_SX_TLV("TX_DEC0 Volume", SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
BOLERO_CDC_TX0_TX_VOL_CTL, BOLERO_CDC_TX0_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC1 Volume", SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
BOLERO_CDC_TX1_TX_VOL_CTL, BOLERO_CDC_TX1_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC2 Volume", SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
BOLERO_CDC_TX2_TX_VOL_CTL, BOLERO_CDC_TX2_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC3 Volume", SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
BOLERO_CDC_TX3_TX_VOL_CTL, BOLERO_CDC_TX3_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
tx_macro_dec_mode_get, tx_macro_dec_mode_put), tx_macro_dec_mode_get, tx_macro_dec_mode_put),
@@ -2398,18 +2431,18 @@ static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = {
}; };
static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = { static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = {
SOC_SINGLE_SX_TLV("TX_DEC4 Volume", SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
BOLERO_CDC_TX4_TX_VOL_CTL, BOLERO_CDC_TX4_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC5 Volume", SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
BOLERO_CDC_TX5_TX_VOL_CTL, BOLERO_CDC_TX5_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC6 Volume", SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
BOLERO_CDC_TX6_TX_VOL_CTL, BOLERO_CDC_TX6_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC7 Volume", SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
BOLERO_CDC_TX7_TX_VOL_CTL, BOLERO_CDC_TX7_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum, SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
tx_macro_dec_mode_get, tx_macro_dec_mode_put), tx_macro_dec_mode_get, tx_macro_dec_mode_put),
@@ -2425,30 +2458,30 @@ static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = {
}; };
static const struct snd_kcontrol_new tx_macro_snd_controls[] = { static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
SOC_SINGLE_SX_TLV("TX_DEC0 Volume", SOC_SINGLE_S8_TLV("TX_DEC0 Volume",
BOLERO_CDC_TX0_TX_VOL_CTL, BOLERO_CDC_TX0_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC1 Volume", SOC_SINGLE_S8_TLV("TX_DEC1 Volume",
BOLERO_CDC_TX1_TX_VOL_CTL, BOLERO_CDC_TX1_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC2 Volume", SOC_SINGLE_S8_TLV("TX_DEC2 Volume",
BOLERO_CDC_TX2_TX_VOL_CTL, BOLERO_CDC_TX2_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC3 Volume", SOC_SINGLE_S8_TLV("TX_DEC3 Volume",
BOLERO_CDC_TX3_TX_VOL_CTL, BOLERO_CDC_TX3_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC4 Volume", SOC_SINGLE_S8_TLV("TX_DEC4 Volume",
BOLERO_CDC_TX4_TX_VOL_CTL, BOLERO_CDC_TX4_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC5 Volume", SOC_SINGLE_S8_TLV("TX_DEC5 Volume",
BOLERO_CDC_TX5_TX_VOL_CTL, BOLERO_CDC_TX5_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC6 Volume", SOC_SINGLE_S8_TLV("TX_DEC6 Volume",
BOLERO_CDC_TX6_TX_VOL_CTL, BOLERO_CDC_TX6_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("TX_DEC7 Volume", SOC_SINGLE_S8_TLV("TX_DEC7 Volume",
BOLERO_CDC_TX7_TX_VOL_CTL, BOLERO_CDC_TX7_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
tx_macro_dec_mode_get, tx_macro_dec_mode_put), tx_macro_dec_mode_get, tx_macro_dec_mode_put),
@@ -2722,36 +2755,6 @@ static int tx_macro_clk_div_get(struct snd_soc_component *component)
return tx_priv->dmic_clk_div; return tx_priv->dmic_clk_div;
} }
static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src)
{
struct device *tx_dev = NULL;
struct tx_macro_priv *tx_priv = NULL;
int ret = 0;
if (!component)
return -EINVAL;
tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
if (!tx_dev) {
dev_err(component->dev,
"%s: null device for macro!\n", __func__);
return -EINVAL;
}
tx_priv = dev_get_drvdata(tx_dev);
if (!tx_priv) {
dev_err(component->dev,
"%s: priv is null for macro!\n", __func__);
return -EINVAL;
}
if (tx_priv->swr_ctrl_data) {
ret = swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_REQ_CLK_SWITCH, &clk_src);
}
return ret;
}
static int tx_macro_core_vote(void *handle, bool enable) static int tx_macro_core_vote(void *handle, bool enable)
{ {
struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
@@ -3233,7 +3236,6 @@ static void tx_macro_init_ops(struct macro_ops *ops,
ops->reg_wake_irq = tx_macro_reg_wake_irq; ops->reg_wake_irq = tx_macro_reg_wake_irq;
ops->set_port_map = tx_macro_set_port_map; ops->set_port_map = tx_macro_set_port_map;
ops->clk_div_get = tx_macro_clk_div_get; ops->clk_div_get = tx_macro_clk_div_get;
ops->clk_switch = tx_macro_clk_switch;
ops->reg_evt_listener = tx_macro_register_event_listener; ops->reg_evt_listener = tx_macro_register_event_listener;
ops->clk_enable = __tx_macro_mclk_enable; ops->clk_enable = __tx_macro_mclk_enable;
} }
@@ -3249,6 +3251,12 @@ static int tx_macro_probe(struct platform_device *pdev)
u32 is_used_tx_swr_gpio = 1; u32 is_used_tx_swr_gpio = 1;
const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio"; const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio";
if (!bolero_is_va_macro_registered(&pdev->dev)) {
dev_err(&pdev->dev,
"%s: va-macro not registered yet, defer\n", __func__);
return -EPROBE_DEFER;
}
tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv), tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv),
GFP_KERNEL); GFP_KERNEL);
if (!tx_priv) if (!tx_priv)

View File

@@ -298,8 +298,7 @@ static int va_macro_event_handler(struct snd_soc_component *component,
"%s: va_mclk_users is non-zero still, audio SSR fail!!\n", "%s: va_mclk_users is non-zero still, audio SSR fail!!\n",
__func__); __func__);
break; break;
case BOLERO_MACRO_EVT_SSR_UP: case BOLERO_MACRO_EVT_PRE_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
/* enable&disable VA_CORE_CLK to reset GFMUX reg */ /* enable&disable VA_CORE_CLK to reset GFMUX reg */
ret = bolero_clk_rsc_request_clock(va_priv->dev, ret = bolero_clk_rsc_request_clock(va_priv->dev,
va_priv->default_clk_id, va_priv->default_clk_id,
@@ -312,6 +311,9 @@ static int va_macro_event_handler(struct snd_soc_component *component,
bolero_clk_rsc_request_clock(va_priv->dev, bolero_clk_rsc_request_clock(va_priv->dev,
va_priv->default_clk_id, va_priv->default_clk_id,
VA_CORE_CLK, false); VA_CORE_CLK, false);
break;
case BOLERO_MACRO_EVT_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
/* reset swr after ssr/pdr */ /* reset swr after ssr/pdr */
va_priv->reset_swr = true; va_priv->reset_swr = true;
if (va_priv->swr_ctrl_data) if (va_priv->swr_ctrl_data)
@@ -378,7 +380,6 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
int ret = 0; int ret = 0;
struct device *va_dev = NULL; struct device *va_dev = NULL;
struct va_macro_priv *va_priv = NULL; struct va_macro_priv *va_priv = NULL;
int clk_src = 0;
if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
return -EINVAL; return -EINVAL;
@@ -391,30 +392,12 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
if (va_priv->swr_ctrl_data) {
clk_src = CLK_SRC_VA_RCG;
ret = swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
SWR_REQ_CLK_SWITCH, &clk_src);
if (ret)
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
}
msm_cdc_pinctrl_set_wakeup_capable( msm_cdc_pinctrl_set_wakeup_capable(
va_priv->va_swr_gpio_p, false); va_priv->va_swr_gpio_p, false);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
msm_cdc_pinctrl_set_wakeup_capable( msm_cdc_pinctrl_set_wakeup_capable(
va_priv->va_swr_gpio_p, true); va_priv->va_swr_gpio_p, true);
if (va_priv->swr_ctrl_data) {
clk_src = CLK_SRC_TX_RCG;
ret = swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
SWR_REQ_CLK_SWITCH, &clk_src);
if (ret)
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
}
break; break;
default: default:
dev_err(va_priv->dev, dev_err(va_priv->dev,
@@ -452,10 +435,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
"%s: lpass audio hw enable failed\n", "%s: lpass audio hw enable failed\n",
__func__); __func__);
} }
if (!ret)
if (bolero_tx_clk_switch(component, CLK_SRC_VA_RCG))
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
if (va_priv->lpi_enable) { if (va_priv->lpi_enable) {
bolero_register_event_listener(component, true); bolero_register_event_listener(component, true);
va_priv->register_event_listener = true; va_priv->register_event_listener = true;
@@ -466,8 +445,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
va_priv->register_event_listener = false; va_priv->register_event_listener = false;
bolero_register_event_listener(component, false); bolero_register_event_listener(component, false);
} }
if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG))
dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
if (va_priv->lpass_audio_hw_vote) if (va_priv->lpass_audio_hw_vote)
digital_cdc_rsc_mgr_hw_vote_disable( digital_cdc_rsc_mgr_hw_vote_disable(
va_priv->lpass_audio_hw_vote); va_priv->lpass_audio_hw_vote);
@@ -507,7 +484,6 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
int ret = 0; int ret = 0;
struct device *va_dev = NULL; struct device *va_dev = NULL;
struct va_macro_priv *va_priv = NULL; struct va_macro_priv *va_priv = NULL;
int clk_src = 0;
if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
return -EINVAL; return -EINVAL;
@@ -528,27 +504,10 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
ret = bolero_tx_mclk_enable(component, 1); ret = bolero_tx_mclk_enable(component, 1);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
if (va_priv->lpi_enable) { if (va_priv->lpi_enable)
if (va_priv->version == BOLERO_VERSION_2_1) {
if (va_priv->swr_ctrl_data) {
clk_src = CLK_SRC_TX_RCG;
ret = swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
SWR_REQ_CLK_SWITCH, &clk_src);
if (ret)
dev_dbg(va_dev,
"%s: clock switch failed\n",
__func__);
}
} else if (bolero_tx_clk_switch(component,
CLK_SRC_TX_RCG)) {
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
}
va_macro_mclk_enable(va_priv, 0, true); va_macro_mclk_enable(va_priv, 0, true);
} else { else
bolero_tx_mclk_enable(component, 0); bolero_tx_mclk_enable(component, 0);
}
if (va_priv->tx_clk_status > 0) { if (va_priv->tx_clk_status > 0) {
bolero_clk_rsc_request_clock(va_priv->dev, bolero_clk_rsc_request_clock(va_priv->dev,
@@ -2536,30 +2495,30 @@ static const struct soc_enum dec_mode_mux_enum =
dec_mode_mux_text); dec_mode_mux_text);
static const struct snd_kcontrol_new va_macro_snd_controls[] = { static const struct snd_kcontrol_new va_macro_snd_controls[] = {
SOC_SINGLE_SX_TLV("VA_DEC0 Volume", SOC_SINGLE_S8_TLV("VA_DEC0 Volume",
BOLERO_CDC_VA_TX0_TX_VOL_CTL, BOLERO_CDC_VA_TX0_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC1 Volume", SOC_SINGLE_S8_TLV("VA_DEC1 Volume",
BOLERO_CDC_VA_TX1_TX_VOL_CTL, BOLERO_CDC_VA_TX1_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC2 Volume", SOC_SINGLE_S8_TLV("VA_DEC2 Volume",
BOLERO_CDC_VA_TX2_TX_VOL_CTL, BOLERO_CDC_VA_TX2_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC3 Volume", SOC_SINGLE_S8_TLV("VA_DEC3 Volume",
BOLERO_CDC_VA_TX3_TX_VOL_CTL, BOLERO_CDC_VA_TX3_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC4 Volume", SOC_SINGLE_S8_TLV("VA_DEC4 Volume",
BOLERO_CDC_VA_TX4_TX_VOL_CTL, BOLERO_CDC_VA_TX4_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC5 Volume", SOC_SINGLE_S8_TLV("VA_DEC5 Volume",
BOLERO_CDC_VA_TX5_TX_VOL_CTL, BOLERO_CDC_VA_TX5_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC6 Volume", SOC_SINGLE_S8_TLV("VA_DEC6 Volume",
BOLERO_CDC_VA_TX6_TX_VOL_CTL, BOLERO_CDC_VA_TX6_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC7 Volume", SOC_SINGLE_S8_TLV("VA_DEC7 Volume",
BOLERO_CDC_VA_TX7_TX_VOL_CTL, BOLERO_CDC_VA_TX7_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
va_macro_lpi_get, va_macro_lpi_put), va_macro_lpi_get, va_macro_lpi_put),
@@ -2577,23 +2536,23 @@ static const struct snd_kcontrol_new va_macro_snd_controls[] = {
}; };
static const struct snd_kcontrol_new va_macro_snd_controls_common[] = { static const struct snd_kcontrol_new va_macro_snd_controls_common[] = {
SOC_SINGLE_SX_TLV("VA_DEC0 Volume", SOC_SINGLE_S8_TLV("VA_DEC0 Volume",
BOLERO_CDC_VA_TX0_TX_VOL_CTL, BOLERO_CDC_VA_TX0_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC1 Volume", SOC_SINGLE_S8_TLV("VA_DEC1 Volume",
BOLERO_CDC_VA_TX1_TX_VOL_CTL, BOLERO_CDC_VA_TX1_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
va_macro_lpi_get, va_macro_lpi_put), va_macro_lpi_get, va_macro_lpi_put),
}; };
static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = { static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = {
SOC_SINGLE_SX_TLV("VA_DEC2 Volume", SOC_SINGLE_S8_TLV("VA_DEC2 Volume",
BOLERO_CDC_VA_TX2_TX_VOL_CTL, BOLERO_CDC_VA_TX2_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("VA_DEC3 Volume", SOC_SINGLE_S8_TLV("VA_DEC3 Volume",
BOLERO_CDC_VA_TX3_TX_VOL_CTL, BOLERO_CDC_VA_TX3_TX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
}; };
static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,

View File

@@ -1022,10 +1022,7 @@ static int wsa_macro_event_handler(struct snd_soc_component *component,
} }
} }
break; break;
case BOLERO_MACRO_EVT_SSR_UP: case BOLERO_MACRO_EVT_PRE_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
/* reset swr after ssr/pdr */
wsa_priv->reset_swr = true;
/* enable&disable WSA_CORE_CLK to reset GFMUX reg */ /* enable&disable WSA_CORE_CLK to reset GFMUX reg */
ret = bolero_clk_rsc_request_clock(wsa_priv->dev, ret = bolero_clk_rsc_request_clock(wsa_priv->dev,
wsa_priv->default_clk_id, wsa_priv->default_clk_id,
@@ -1038,6 +1035,11 @@ static int wsa_macro_event_handler(struct snd_soc_component *component,
bolero_clk_rsc_request_clock(wsa_priv->dev, bolero_clk_rsc_request_clock(wsa_priv->dev,
wsa_priv->default_clk_id, wsa_priv->default_clk_id,
WSA_CORE_CLK, false); WSA_CORE_CLK, false);
break;
case BOLERO_MACRO_EVT_SSR_UP:
trace_printk("%s, enter SSR up\n", __func__);
/* reset swr after ssr/pdr */
wsa_priv->reset_swr = true;
if (wsa_priv->swr_ctrl_data) if (wsa_priv->swr_ctrl_data)
swrm_wcd_notify( swrm_wcd_notify(
wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
@@ -1178,45 +1180,6 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
u16 gain_reg;
int offset_val = 0;
int val = 0;
dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
switch (w->reg) {
case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL:
gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
break;
case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL:
gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
break;
default:
dev_err(component->dev, "%s: No gain register avail for %s\n",
__func__, w->name);
return 0;
}
switch (event) {
case SND_SOC_DAPM_POST_PMU:
val = snd_soc_component_read32(component, gain_reg);
val += offset_val;
snd_soc_component_write(component, gain_reg, val);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
w->reg, 0x20, 0x00);
break;
}
return 0;
}
static void wsa_macro_hd2_control(struct snd_soc_component *component, static void wsa_macro_hd2_control(struct snd_soc_component *component,
u16 reg, int event) u16 reg, int event)
{ {
@@ -1303,6 +1266,44 @@ static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
u16 gain_reg;
int offset_val = 0;
int val = 0;
dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name);
if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) {
gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL;
} else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) {
gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL;
} else {
dev_err(component->dev, "%s: No gain register avail for %s\n",
__func__, w->name);
return 0;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
wsa_macro_enable_swr(w, kcontrol, event);
val = snd_soc_component_read32(component, gain_reg);
val += offset_val;
snd_soc_component_write(component, gain_reg, val);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
w->reg, 0x20, 0x00);
wsa_macro_enable_swr(w, kcontrol, event);
break;
}
return 0;
}
static int wsa_macro_config_compander(struct snd_soc_component *component, static int wsa_macro_config_compander(struct snd_soc_component *component,
int comp, int event) int comp, int event)
{ {
@@ -2007,10 +2008,12 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
int value = ucontrol->value.integer.value[0]; int value = ucontrol->value.integer.value[0];
int wsa_rx_shift = ((struct soc_multi_mixer_control *) int wsa_rx_shift = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->shift; kcontrol->private_value)->shift;
int ret = 0;
if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
return -EINVAL; return -EINVAL;
pm_runtime_get_sync(wsa_priv->dev);
switch (wsa_rx_shift) { switch (wsa_rx_shift) {
case 0: case 0:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
@@ -2035,13 +2038,16 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
default: default:
pr_err("%s: invalid argument rx_shift = %d\n", __func__, pr_err("%s: invalid argument rx_shift = %d\n", __func__,
wsa_rx_shift); wsa_rx_shift);
return -EINVAL; ret = -EINVAL;
} }
pm_runtime_mark_last_busy(wsa_priv->dev);
pm_runtime_put_autosuspend(wsa_priv->dev);
dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n", dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n",
__func__, wsa_rx_shift, value); __func__, wsa_rx_shift, value);
wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value; wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value;
return 0;
return ret;
} }
static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol, static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
@@ -2370,12 +2376,12 @@ static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
WSA_MACRO_SOFTCLIP1, 1, 0, WSA_MACRO_SOFTCLIP1, 1, 0,
wsa_macro_soft_clip_enable_get, wsa_macro_soft_clip_enable_get,
wsa_macro_soft_clip_enable_put), wsa_macro_soft_clip_enable_put),
SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume", SOC_SINGLE_S8_TLV("WSA_RX0 Digital Volume",
BOLERO_CDC_WSA_RX0_RX_VOL_CTL, BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume", SOC_SINGLE_S8_TLV("WSA_RX1 Digital Volume",
BOLERO_CDC_WSA_RX1_RX_VOL_CTL, BOLERO_CDC_WSA_RX1_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX0, 1, SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX0, 1,
0, wsa_macro_get_rx_mute_status, 0, wsa_macro_get_rx_mute_status,
wsa_macro_set_rx_mute_status), wsa_macro_set_rx_mute_status),
@@ -2550,7 +2556,7 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
&rx0_prim_inp2_mux, wsa_macro_enable_swr, &rx0_prim_inp2_mux, wsa_macro_enable_swr,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL, SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM,
0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path, 0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
@@ -2562,7 +2568,7 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
&rx1_prim_inp2_mux, wsa_macro_enable_swr, &rx1_prim_inp2_mux, wsa_macro_enable_swr,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL, SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM,
0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path, 0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
@@ -3138,6 +3144,12 @@ static int wsa_macro_probe(struct platform_device *pdev)
u32 is_used_wsa_swr_gpio = 1; u32 is_used_wsa_swr_gpio = 1;
const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio"; const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
if (!bolero_is_va_macro_registered(&pdev->dev)) {
dev_err(&pdev->dev,
"%s: va-macro not registered yet, defer\n", __func__);
return -EPROBE_DEFER;
}
wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv), wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
GFP_KERNEL); GFP_KERNEL);
if (!wsa_priv) if (!wsa_priv)
@@ -3175,6 +3187,8 @@ static int wsa_macro_probe(struct platform_device *pdev)
__func__); __func__);
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
msm_cdc_pinctrl_set_wakeup_capable(
wsa_priv->wsa_swr_gpio_p, false);
wsa_io_base = devm_ioremap(&pdev->dev, wsa_io_base = devm_ioremap(&pdev->dev,
wsa_base_addr, WSA_MACRO_MAX_OFFSET); wsa_base_addr, WSA_MACRO_MAX_OFFSET);
@@ -3221,6 +3235,7 @@ static int wsa_macro_probe(struct platform_device *pdev)
wsa_macro_init_ops(&ops, wsa_io_base); wsa_macro_init_ops(&ops, wsa_io_base);
ops.clk_id_req = wsa_priv->default_clk_id; ops.clk_id_req = wsa_priv->default_clk_id;
ops.default_clk_id = wsa_priv->default_clk_id; ops.default_clk_id = wsa_priv->default_clk_id;
ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops); ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "%s: register macro failed\n", __func__); dev_err(&pdev->dev, "%s: register macro failed\n", __func__);

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
@@ -602,6 +602,25 @@ static const struct snd_soc_dapm_route csra66x0_dapm_routes[] = {
{"PGA", NULL, "DAC"}, {"PGA", NULL, "DAC"},
{"SPKR", NULL, "PGA"}, {"SPKR", NULL, "PGA"},
}; };
/*
* csra66x0_hw_free_mute - Update csra66x0 mute register
*
* @component - csra66x0 component
*
*/
void csra66x0_hw_free_mute(struct snd_soc_component *component)
{
int val = 0;
if (component == NULL)
return;
val = snd_soc_component_read32(component,
CSRA66X0_MISC_CONTROL_STATUS_1_FA);
snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_1_FA,
val | 0x04);
}
EXPORT_SYMBOL(csra66x0_hw_free_mute);
static int csra66x0_wait_for_config_state(struct snd_soc_component *component) static int csra66x0_wait_for_config_state(struct snd_soc_component *component)
{ {

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef _CSRA66X0_H #ifndef _CSRA66X0_H
@@ -226,4 +226,6 @@
#define FAULT_STATUS_TEMP 0x10 #define FAULT_STATUS_TEMP 0x10
#define FAULT_STATUS_PROTECT 0x20 #define FAULT_STATUS_PROTECT 0x20
void csra66x0_hw_free_mute(struct snd_soc_component *component);
#endif /* _CSRA66X0_H */ #endif /* _CSRA66X0_H */

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/init.h> #include <linux/init.h>
@@ -40,6 +40,10 @@ static const unsigned int ep92_samp_freq_table[8] = {
32000, 44100, 48000, 88200, 96000, 176400, 192000, 768000 32000, 44100, 48000, 88200, 96000, 176400, 192000, 768000
}; };
static const unsigned int ep92_dsd_freq_table[4] = {
64, 128, 256, 0
};
static bool ep92_volatile_register(struct device *dev, unsigned int reg) static bool ep92_volatile_register(struct device *dev, unsigned int reg)
{ {
/* do not cache register state in regmap */ /* do not cache register state in regmap */
@@ -549,6 +553,23 @@ static void ep92_read_audio_info(struct snd_soc_component *component,
send_uevent = true; send_uevent = true;
} }
old = ep92->ai.system_status_1;
ep92->ai.system_status_1 = snd_soc_read(codec,
EP92_AUDIO_INFO_SYSTEM_STATUS_1);
if (ep92->ai.system_status_1 == 0xff) {
dev_dbg(codec->dev,
"ep92 EP92_AUDIO_INFO_SYSTEM_STATUS_1 read 0xff\n");
ep92->ai.system_status_1 = old;
}
change = ep92->ai.system_status_1 ^ old;
if (change & EP92_AI_DSD_RATE_MASK) {
dev_dbg(codec->dev, "ep92 dsd rate changed to %d\n",
ep92_dsd_freq_table[(ep92->ai.system_status_1 &
EP92_AI_DSD_RATE_MASK)
>> EP92_AI_DSD_RATE_SHIFT]);
send_uevent = true;
}
old = ep92->ai.audio_status; old = ep92->ai.audio_status;
ep92->ai.audio_status = snd_soc_component_read32(component, ep92->ai.audio_status = snd_soc_component_read32(component,
EP92_AUDIO_INFO_AUDIO_STATUS); EP92_AUDIO_INFO_AUDIO_STATUS);
@@ -580,7 +601,9 @@ static void ep92_read_audio_info(struct snd_soc_component *component,
} }
new_mode = ep92->old_mode; new_mode = ep92->old_mode;
if (ep92->ai.audio_status & EP92_AI_STD_ADO_MASK) { if (ep92->ai.audio_status & EP92_AI_DSD_ADO_MASK)
new_mode = 2; /* One bit audio */
else if (ep92->ai.audio_status & EP92_AI_STD_ADO_MASK) {
if (ep92->ai.cs[0] & EP92_AI_NPCM_MASK) if (ep92->ai.cs[0] & EP92_AI_NPCM_MASK)
new_mode = 1; /* Compr */ new_mode = 1; /* Compr */
else else
@@ -897,6 +920,27 @@ static ssize_t ep92_sysfs_rda_audio_format(struct device *dev,
return ret; return ret;
} }
static ssize_t ep92_sysfs_rda_dsd_rate(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
int val;
struct ep92_pdata *ep92 = dev_get_drvdata(dev);
if (!ep92 || !ep92->codec) {
dev_err(dev, "%s: device error\n", __func__);
return -ENODEV;
}
val = ep92_dsd_freq_table[(ep92->ai.system_status_1 &
EP92_AI_DSD_RATE_MASK) >> EP92_AI_DSD_RATE_SHIFT];
ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val);
dev_dbg(dev, "%s: '%d'\n", __func__, val);
return ret;
}
static ssize_t ep92_sysfs_rda_audio_rate(struct device *dev, static ssize_t ep92_sysfs_rda_audio_rate(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
@@ -1621,6 +1665,7 @@ static DEVICE_ATTR(cec_volume, 0644, ep92_sysfs_rda_cec_volume,
static DEVICE_ATTR(runout, 0444, ep92_sysfs_rda_runout, NULL); static DEVICE_ATTR(runout, 0444, ep92_sysfs_rda_runout, NULL);
static DEVICE_ATTR(force_inactive, 0644, ep92_sysfs_rda_force_inactive, static DEVICE_ATTR(force_inactive, 0644, ep92_sysfs_rda_force_inactive,
ep92_sysfs_wta_force_inactive); ep92_sysfs_wta_force_inactive);
static DEVICE_ATTR(dsd_rate, 0444, ep92_sysfs_rda_dsd_rate, NULL);
static struct attribute *ep92_fs_attrs[] = { static struct attribute *ep92_fs_attrs[] = {
&dev_attr_chipid.attr, &dev_attr_chipid.attr,
@@ -1647,6 +1692,7 @@ static struct attribute *ep92_fs_attrs[] = {
&dev_attr_cec_volume.attr, &dev_attr_cec_volume.attr,
&dev_attr_runout.attr, &dev_attr_runout.attr,
&dev_attr_force_inactive.attr, &dev_attr_force_inactive.attr,
&dev_attr_dsd_rate.attr,
NULL, NULL,
}; };

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef __EP92_H__ #ifndef __EP92_H__
@@ -175,6 +175,10 @@ static struct reg_default ep92_reg_defaults[] = {
#define EP92_AI_PREEMPH_MASK 0x38 #define EP92_AI_PREEMPH_MASK 0x38
#define EP92_AI_CH_COUNT_MASK 0x07 #define EP92_AI_CH_COUNT_MASK 0x07
#define EP92_AI_CH_ALLOC_MASK 0xff #define EP92_AI_CH_ALLOC_MASK 0xff
#define EP92_AI_DSD_ADO_SHIFT 4
#define EP92_AI_DSD_ADO_MASK 0x10
#define EP92_AI_DSD_RATE_SHIFT 4
#define EP92_AI_DSD_RATE_MASK 0x30
#define EP92_2CHOICE_MASK 1 #define EP92_2CHOICE_MASK 1
#define EP92_GC_CEC_VOLUME_MIN 0 #define EP92_GC_CEC_VOLUME_MIN 0

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@@ -21,6 +21,7 @@ struct msm_cdc_pinctrl_info {
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
struct pinctrl_state *pinctrl_active; struct pinctrl_state *pinctrl_active;
struct pinctrl_state *pinctrl_sleep; struct pinctrl_state *pinctrl_sleep;
struct pinctrl_state *pinctrl_alt_active;
int gpio; int gpio;
bool state; bool state;
u32 tlmm_gpio[MAX_GPIOS]; u32 tlmm_gpio[MAX_GPIOS];
@@ -104,6 +105,31 @@ int msm_cdc_pinctrl_select_sleep_state(struct device_node *np)
} }
EXPORT_SYMBOL(msm_cdc_pinctrl_select_sleep_state); EXPORT_SYMBOL(msm_cdc_pinctrl_select_sleep_state);
/*
* msm_cdc_pinctrl_select_alt_active_state: select pinctrl alt_active state
* @np: pointer to struct device_node
*
* Returns error code for failure
*/
int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np)
{
struct msm_cdc_pinctrl_info *gpio_data;
gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
if (!gpio_data)
return -EINVAL;
if (!gpio_data->pinctrl_alt_active) {
pr_err("%s: pinctrl alt_active state is null\n", __func__);
return -EINVAL;
}
gpio_data->state = true;
return pinctrl_select_state(gpio_data->pinctrl,
gpio_data->pinctrl_alt_active);
}
EXPORT_SYMBOL(msm_cdc_pinctrl_select_alt_active_state);
/* /*
* msm_cdc_pinctrl_select_active_state: select pinctrl active state * msm_cdc_pinctrl_select_active_state: select pinctrl active state
* @np: pointer to struct device_node * @np: pointer to struct device_node
@@ -231,6 +257,14 @@ static int msm_cdc_pinctrl_probe(struct platform_device *pdev)
ret = PTR_ERR(gpio_data->pinctrl_sleep); ret = PTR_ERR(gpio_data->pinctrl_sleep);
goto err_lookup_state; goto err_lookup_state;
} }
gpio_data->pinctrl_alt_active = pinctrl_lookup_state(
gpio_data->pinctrl, "aud_alt_active");
if (IS_ERR_OR_NULL(gpio_data->pinctrl_alt_active)) {
dev_dbg(&pdev->dev, "%s: Cannot get aud_alt_active pinctrl state:%ld\n",
__func__, PTR_ERR(gpio_data->pinctrl_alt_active));
}
/* skip setting to sleep state for LPI_TLMM GPIOs */ /* skip setting to sleep state for LPI_TLMM GPIOs */
if (!of_property_read_bool(pdev->dev.of_node, "qcom,lpi-gpios")) { if (!of_property_read_bool(pdev->dev.of_node, "qcom,lpi-gpios")) {
/* Set pinctrl state to aud_sleep by default */ /* Set pinctrl state to aud_sleep by default */

View File

@@ -60,9 +60,22 @@ static int msm_cdc_dt_parse_vreg_info(struct device *dev,
} }
cdc_vreg->optimum_uA = prop_val; cdc_vreg->optimum_uA = prop_val;
dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", /* Parse supply - LPM or NOM mode(default NOM) */
snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-lpm-supported", name);
rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
if (rc) {
dev_dbg(dev, "%s: Looking up %s property in node %s failed",
__func__, prop_name, dev->of_node->full_name);
cdc_vreg->lpm_supported = 0;
rc = 0;
} else {
cdc_vreg->lpm_supported = prop_val;
}
dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d\n",
__func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV, __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
cdc_vreg->optimum_uA, cdc_vreg->ondemand); cdc_vreg->optimum_uA, cdc_vreg->ondemand,
cdc_vreg->lpm_supported);
done: done:
return rc; return rc;
@@ -260,6 +273,59 @@ int msm_cdc_enable_ondemand_supply(struct device *dev,
} }
EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply); EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply);
/*
* msm_cdc_set_supplies_lpm_mode:
* Update load for given supply string
*
* @dev: pointer to codec device
* @supplies: pointer to regulator bulk data
* @cdc_vreg: pointer to platform regulator data
* @num_supplies: number of supplies
* @supply_name: supply name to be checked
* @min_max: Apply optimum or 0 current
*
* Return error code if set current fail
*/
int msm_cdc_set_supplies_lpm_mode(struct device *dev,
struct regulator_bulk_data *supplies,
struct cdc_regulator *cdc_vreg,
int num_supplies,
bool flag)
{
int rc = 0, i;
if (!supplies) {
pr_err("%s: supplies is NULL\n",
__func__);
return -EINVAL;
}
/* input parameter validation */
rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
if (rc)
return rc;
for (i = 0; i < num_supplies; i++) {
if (cdc_vreg[i].lpm_supported) {
rc = regulator_set_load(
supplies[i].consumer,
flag ? 0 : cdc_vreg[i].optimum_uA);
if (rc)
dev_err(dev,
"%s: failed to set supply %s to %s, err:%d\n",
__func__, supplies[i].supply,
flag ? "LPM" : "NOM",
rc);
else
dev_dbg(dev, "%s: regulator %s load set to %s\n",
__func__, supplies[i].supply,
flag ? "LPM" : "NOM");
}
}
return rc;
}
EXPORT_SYMBOL(msm_cdc_set_supplies_lpm_mode);
/* /*
* msm_cdc_disable_static_supplies: * msm_cdc_disable_static_supplies:
* Disable codec static supplies * Disable codec static supplies

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
@@ -25,8 +25,8 @@
static SOC_ENUM_SINGLE_DECL(ext_disp_audio_ack_state##index, \ static SOC_ENUM_SINGLE_DECL(ext_disp_audio_ack_state##index, \
SND_SOC_NOPM, index, ext_disp_audio_ack_text) SND_SOC_NOPM, index, ext_disp_audio_ack_text)
#define SWITCH_DP_CODEC(codec_info, codec_data, dai_id) \ #define SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type) \
codec_info.type = EXT_DISPLAY_TYPE_DP; \ codec_info.type = type; \
codec_info.ctrl_id = codec_data->ctl[dai_id]; \ codec_info.ctrl_id = codec_data->ctl[dai_id]; \
codec_info.stream_id = codec_data->stream[dai_id]; \ codec_info.stream_id = codec_data->stream[dai_id]; \
@@ -38,6 +38,7 @@ enum {
enum { enum {
DP_STREAM0 = 0, DP_STREAM0 = 0,
DP_STREAM1, DP_STREAM1,
HDMI,
DP_STREAM_MAX, DP_STREAM_MAX,
}; };
@@ -49,6 +50,7 @@ enum {
DP_DAI1 = 1, DP_DAI1 = 1,
DP_DAI2, DP_DAI2,
HDMI_DAI, HDMI_DAI,
HDMI_MS_DAI,
DP_DAI_MAX, DP_DAI_MAX,
}; };
@@ -60,6 +62,8 @@ SOC_EXT_DISP_AUDIO_TYPE(1);
SOC_EXT_DISP_AUDIO_ACK_STATE(1); SOC_EXT_DISP_AUDIO_ACK_STATE(1);
SOC_EXT_DISP_AUDIO_TYPE(2); SOC_EXT_DISP_AUDIO_TYPE(2);
SOC_EXT_DISP_AUDIO_ACK_STATE(2); SOC_EXT_DISP_AUDIO_ACK_STATE(2);
SOC_EXT_DISP_AUDIO_TYPE(3);
SOC_EXT_DISP_AUDIO_ACK_STATE(3);
struct msm_ext_disp_audio_codec_rx_data { struct msm_ext_disp_audio_codec_rx_data {
struct platform_device *ext_disp_core_pdev; struct platform_device *ext_disp_core_pdev;
@@ -80,6 +84,7 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
int rc = 0; int rc = 0;
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
int dai_id = kcontrol->private_value; int dai_id = kcontrol->private_value;
int type;
codec_data = snd_soc_component_get_drvdata(component); codec_data = snd_soc_component_get_drvdata(component);
if (!codec_data) { if (!codec_data) {
@@ -91,7 +96,11 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
codec_data->ctl[dai_id], codec_data->stream[dai_id]); codec_data->ctl[dai_id], codec_data->stream[dai_id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai_id); if (dai_id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) { if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
@@ -126,6 +135,7 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
int rc = 0; int rc = 0;
int dai_id = kcontrol->private_value; int dai_id = kcontrol->private_value;
int type;
codec_data = snd_soc_component_get_drvdata(component); codec_data = snd_soc_component_get_drvdata(component);
if (!codec_data) { if (!codec_data) {
@@ -138,7 +148,11 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
codec_data->ctl[dai_id], codec_data->stream[dai_id]); codec_data->ctl[dai_id], codec_data->stream[dai_id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai_id); if (dai_id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) { if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
@@ -147,7 +161,6 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec_data->dp_ops_lock); mutex_unlock(&codec_data->dp_ops_lock);
return -EINVAL; return -EINVAL;
} }
rc = codec_data->ext_disp_ops.get_audio_edid_blk( rc = codec_data->ext_disp_ops.get_audio_edid_blk(
codec_data->ext_disp_core_pdev, &edid_blk); codec_data->ext_disp_core_pdev, &edid_blk);
mutex_unlock(&codec_data->dp_ops_lock); mutex_unlock(&codec_data->dp_ops_lock);
@@ -188,6 +201,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
int rc = 0; int rc = 0;
int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l; int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
int type;
codec_data = snd_soc_component_get_drvdata(component); codec_data = snd_soc_component_get_drvdata(component);
if (!codec_data) { if (!codec_data) {
@@ -200,7 +214,11 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
codec_data->ctl[dai_id], codec_data->stream[dai_id]); codec_data->ctl[dai_id], codec_data->stream[dai_id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai_id); if (dai_id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
@@ -274,6 +292,7 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
int rc = 0; int rc = 0;
int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l; int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
int type;
codec_data = snd_soc_component_get_drvdata(component); codec_data = snd_soc_component_get_drvdata(component);
if (!codec_data) { if (!codec_data) {
@@ -287,7 +306,11 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
codec_data->ctl[dai_id], codec_data->stream[dai_id]); codec_data->ctl[dai_id], codec_data->stream[dai_id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai_id); if (dai_id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
@@ -421,6 +444,15 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
.get = msm_ext_disp_edid_get, .get = msm_ext_disp_edid_get,
.private_value = HDMI_DAI, .private_value = HDMI_DAI,
}, },
{
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "HDMI MS EDID",
.info = msm_ext_disp_edid_ctl_info,
.get = msm_ext_disp_edid_get,
.private_value = HDMI_MS_DAI,
},
{ {
.access = SNDRV_CTL_ELEM_ACCESS_READ | .access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE, SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -445,12 +477,18 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
SOC_ENUM_EXT("External Display1 Type", SOC_ENUM_EXT("External Display1 Type",
ext_disp_audio_type2, ext_disp_audio_type2,
msm_ext_disp_audio_type_get, NULL), msm_ext_disp_audio_type_get, NULL),
SOC_ENUM_EXT("External HDMI Type",
ext_disp_audio_type3,
msm_ext_disp_audio_type_get, NULL),
SOC_ENUM_EXT("External Display Audio Ack", SOC_ENUM_EXT("External Display Audio Ack",
ext_disp_audio_ack_state1, ext_disp_audio_ack_state1,
NULL, msm_ext_disp_audio_ack_set), NULL, msm_ext_disp_audio_ack_set),
SOC_ENUM_EXT("External Display1 Audio Ack", SOC_ENUM_EXT("External Display1 Audio Ack",
ext_disp_audio_ack_state2, ext_disp_audio_ack_state2,
NULL, msm_ext_disp_audio_ack_set), NULL, msm_ext_disp_audio_ack_set),
SOC_ENUM_EXT("External HDMI Audio Ack",
ext_disp_audio_ack_state3,
NULL, msm_ext_disp_audio_ack_set),
SOC_SINGLE_MULTI_EXT("External Display Audio Device", SOC_SINGLE_MULTI_EXT("External Display Audio Device",
SND_SOC_NOPM, DP_DAI1, DP_STREAM_MAX - 1, 0, 2, SND_SOC_NOPM, DP_DAI1, DP_STREAM_MAX - 1, 0, 2,
@@ -460,6 +498,11 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2, SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2,
msm_ext_disp_audio_device_get, msm_ext_disp_audio_device_get,
msm_ext_disp_audio_device_set), 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,
msm_ext_disp_audio_device_get,
msm_ext_disp_audio_device_set),
}; };
static int msm_ext_disp_audio_codec_rx_dai_startup( static int msm_ext_disp_audio_codec_rx_dai_startup(
@@ -470,6 +513,7 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
struct msm_ext_disp_audio_codec_rx_data *codec_data = struct msm_ext_disp_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->component->dev); dev_get_drvdata(dai->component->dev);
int type;
if (!codec_data) { if (!codec_data) {
dev_err(dai->dev, "%s() codec_data is null\n", dev_err(dai->dev, "%s() codec_data is null\n",
@@ -482,7 +526,11 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
codec_data->ctl[dai->id], codec_data->stream[dai->id]); codec_data->ctl[dai->id], codec_data->stream[dai->id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai->id); if (dai->id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
@@ -524,7 +572,7 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_codec_id codec_info;
int rc = 0; int rc = 0;
struct msm_ext_disp_audio_setup_params audio_setup_params = {0}; struct msm_ext_disp_audio_setup_params audio_setup_params = {0};
int type;
struct msm_ext_disp_audio_codec_rx_data *codec_data = struct msm_ext_disp_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->component->dev); dev_get_drvdata(dai->component->dev);
@@ -539,7 +587,11 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
codec_data->ctl[dai->id], codec_data->stream[dai->id]); codec_data->ctl[dai->id], codec_data->stream[dai->id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai->id); if (dai->id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
@@ -609,7 +661,7 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
audio_setup_params.down_mix = down_mix; audio_setup_params.down_mix = down_mix;
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai->id); SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
if (rc) if (rc)
@@ -636,6 +688,7 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
struct msm_ext_disp_audio_codec_rx_data *codec_data = struct msm_ext_disp_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->component->dev); dev_get_drvdata(dai->component->dev);
int type;
if (!codec_data) { if (!codec_data) {
dev_err(dai->dev, "%s() codec_data is null\n", dev_err(dai->dev, "%s() codec_data is null\n",
@@ -648,7 +701,11 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
codec_data->ctl[dai->id], codec_data->stream[dai->id]); codec_data->ctl[dai->id], codec_data->stream[dai->id]);
mutex_lock(&codec_data->dp_ops_lock); mutex_lock(&codec_data->dp_ops_lock);
SWITCH_DP_CODEC(codec_info, codec_data, dai->id); if (dai->id == HDMI_MS_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, rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
&codec_info); &codec_info);
@@ -754,6 +811,20 @@ static struct snd_soc_dai_driver msm_ext_disp_audio_codec_rx_dais[] = {
}, },
.ops = &msm_ext_disp_audio_codec_rx_dai_ops, .ops = &msm_ext_disp_audio_codec_rx_dai_ops,
}, },
{
.name = "msm_hdmi_ms_audio_codec_rx_dai",
.id = HDMI_MS_DAI,
.playback = {
.stream_name = "HDMI MS Playback",
.channels_min = 1,
.channels_max = 8,
.rate_min = 48000,
.rate_max = 48000,
.rates = MSM_EXT_DISP_PCM_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
},
{ {
.name = "msm_dp_audio_codec_rx_dai", .name = "msm_dp_audio_codec_rx_dai",
.id = DP_DAI1, .id = DP_DAI1,

View File

@@ -50,6 +50,7 @@ struct rouleur_priv {
bool comp1_enable; bool comp1_enable;
bool comp2_enable; bool comp2_enable;
bool dapm_bias_off;
struct irq_domain *virq; struct irq_domain *virq;
struct wcd_irq_info irq_info; struct wcd_irq_info irq_info;
@@ -82,6 +83,8 @@ struct rouleur_priv {
int mbias_cnt; int mbias_cnt;
struct mutex rx_clk_lock; struct mutex rx_clk_lock;
struct mutex main_bias_lock; struct mutex main_bias_lock;
bool dev_up;
bool usbc_hs_status;
}; };
struct rouleur_micbias_setting { struct rouleur_micbias_setting {
@@ -169,4 +172,6 @@ extern int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv); extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv);
extern int rouleur_micbias_control(struct snd_soc_component *component, extern int rouleur_micbias_control(struct snd_soc_component *component,
int micb_num, int req, bool is_dapm); int micb_num, int req, bool is_dapm);
extern int rouleur_global_mbias_enable(struct snd_soc_component *component);
extern int rouleur_global_mbias_disable(struct snd_soc_component *component);
#endif #endif

View File

@@ -22,20 +22,19 @@
#define ROULEUR_ZDET_SUPPORTED true #define ROULEUR_ZDET_SUPPORTED true
/* Z value defined in milliohm */ /* Z value defined in milliohm */
#define ROULEUR_ZDET_VAL_32 32000
#define ROULEUR_ZDET_VAL_400 400000
#define ROULEUR_ZDET_VAL_1200 1200000
#define ROULEUR_ZDET_VAL_100K 100000000 #define ROULEUR_ZDET_VAL_100K 100000000
/* Z floating defined in ohms */ /* Z floating defined in ohms */
#define ROULEUR_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE #define ROULEUR_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE
#define ROULEUR_ZDET_NUM_MEASUREMENTS 900 #define ROULEUR_ZDET_NUM_MEASUREMENTS 100
#define ROULEUR_MBHC_GET_C1(c) ((c & 0xC000) >> 14) #define ROULEUR_ZDET_RMAX 1280000
#define ROULEUR_MBHC_GET_X1(x) (x & 0x3FFF) #define ROULEUR_ZDET_C1 7500000
/* Z value compared in milliOhm */ #define ROULEUR_ZDET_C2 187
#define ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) #define ROULEUR_ZDET_C3 4500
#define ROULEUR_MBHC_ZDET_CONST (86 * 16384)
#define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM /* Cross connection thresholds in mV */
#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 350
#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 350
static struct wcd_mbhc_register static struct wcd_mbhc_register
wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = { wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
@@ -88,7 +87,7 @@ static struct wcd_mbhc_register
WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT", WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
ROULEUR_ANA_MBHC_RESULT_3, 0xFF, 0, 0), ROULEUR_ANA_MBHC_RESULT_3, 0xFF, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL", WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x04, 2, 0), ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x06, 1, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME", WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
SND_SOC_NOPM, 0x00, 0, 0), SND_SOC_NOPM, 0x00, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN", WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
@@ -153,9 +152,6 @@ struct rouleur_mbhc_zdet_param {
u16 ldo_ctl; u16 ldo_ctl;
u16 noff; u16 noff;
u16 nshift; u16 nshift;
u16 btn5;
u16 btn6;
u16 btn7;
}; };
static int rouleur_mbhc_request_irq(struct snd_soc_component *component, static int rouleur_mbhc_request_irq(struct snd_soc_component *component,
@@ -320,11 +316,11 @@ static void rouleur_mbhc_micb_ramp_control(struct snd_soc_component *component,
0x1C, 0x0C); 0x1C, 0x0C);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP, ROULEUR_ANA_MBHC_MICB2_RAMP,
0xA0, 0x80); 0x80, 0x80);
} else { } else {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP, ROULEUR_ANA_MBHC_MICB2_RAMP,
0xA0, 0x00); 0x80, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP, ROULEUR_ANA_MBHC_MICB2_RAMP,
0x1C, 0x00); 0x1C, 0x00);
@@ -376,174 +372,180 @@ static int rouleur_mbhc_micb_ctrl_threshold_mic(
return rc; return rc;
} }
static inline void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur, static void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur,
s16 *d1_a, u16 noff, struct snd_soc_component *component,
int32_t *zdet) int32_t *zdet)
{ {
int i; int i;
int val = 0, val1 = 0; int zcode = 0, zcode1 = 0, zdet_cal_result = 0, zdet_est_range = 0;
s16 c1 = 0; int noff = 0, ndac = 14;
s32 x1 = 0, d1 = 0; int zdet_cal_coeff = 0, div_ratio = 0;
int32_t denom; int num = 0, denom = 0;
int minCode_param[] = {
3277, 1639, 820, 410, 205, 103, 52, 26
};
/* Charge enable and wait for zcode to be updated */
regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x20); regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x20);
for (i = 0; i < ROULEUR_ZDET_NUM_MEASUREMENTS; i++) { for (i = 0; i < ROULEUR_ZDET_NUM_MEASUREMENTS; i++) {
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val); regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode);
if (val & 0x80) if (zcode & 0x80)
break;
usleep_range(200, 210);
}
/* If zcode updation is not complete, give additional 10ms */
if (!(zcode & 0x80))
usleep_range(10000, 10100);
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode);
if (!(zcode & 0x80)) {
dev_dbg(rouleur->dev,
"%s: Impedance detect calculation error, zcode=0x%x\n",
__func__, zcode);
regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET,
0x20, 0x00);
return;
}
zcode = zcode << 0x8;
zcode = zcode & 0x3FFF;
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &zcode1);
zcode |= zcode1;
dev_dbg(rouleur->dev,
"%s: zcode: %d, zcode1: %d\n", __func__, zcode, zcode1);
/* Calculate calibration coefficient */
zdet_cal_result = (snd_soc_component_read32(component,
ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)) & 0x1F;
zdet_cal_coeff = ROULEUR_ZDET_C1 /
((ROULEUR_ZDET_C2 * zdet_cal_result) + ROULEUR_ZDET_C3);
/* Rload calculation */
zdet_est_range = (snd_soc_component_read32(component,
ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT) & 0x60) >> 5;
dev_dbg(rouleur->dev,
"%s: zdet_cal_result: %d, zdet_cal_coeff: %d, zdet_est_range: %d\n",
__func__, zdet_cal_result, zdet_cal_coeff, zdet_est_range);
switch (zdet_est_range) {
case 0:
default:
noff = 0;
div_ratio = 320;
break;
case 1:
noff = 0;
div_ratio = 64;
break;
case 2:
noff = 4;
div_ratio = 64;
break;
case 3:
noff = 5;
div_ratio = 40;
break; break;
} }
val = val << 0x8;
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val1);
val |= val1;
regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00);
x1 = ROULEUR_MBHC_GET_X1(val);
c1 = ROULEUR_MBHC_GET_C1(val);
/* If ramp is not complete, give additional 5ms */
if ((c1 < 2) && x1)
usleep_range(5000, 5050);
if (!c1 || !x1) { num = zdet_cal_coeff * ROULEUR_ZDET_RMAX;
denom = ((zcode * div_ratio * 100) - (1 << (ndac - noff)) * 1000);
dev_dbg(rouleur->dev, dev_dbg(rouleur->dev,
"%s: Impedance detect ramp error, c1=%d, x1=0x%x\n", "%s: num: %d, denom: %d\n", __func__, num, denom);
__func__, c1, x1);
goto ramp_down;
}
d1 = d1_a[c1];
denom = (x1 * d1) - (1 << (14 - noff));
if (denom > 0) if (denom > 0)
*zdet = (ROULEUR_MBHC_ZDET_CONST * 1000) / denom; *zdet = (int32_t) ((num / denom) * 1000);
else if (x1 < minCode_param[noff]) else
*zdet = ROULEUR_ZDET_FLOATING_IMPEDANCE; *zdet = ROULEUR_ZDET_FLOATING_IMPEDANCE;
dev_dbg(rouleur->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n", dev_dbg(rouleur->dev, "%s: z_val=%d(milliOhm)\n",
__func__, d1, c1, x1, *zdet); __func__, *zdet);
ramp_down: /* Start discharge */
i = 0; regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00);
while (x1) {
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val);
regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val1);
val = val << 0x8;
val |= val1;
x1 = ROULEUR_MBHC_GET_X1(val);
i++;
if (i == ROULEUR_ZDET_NUM_MEASUREMENTS)
break;
}
} }
#if 0 static void rouleur_mbhc_zdet_start(struct snd_soc_component *component,
static void rouleur_mbhc_zdet_ramp(struct snd_soc_component *component, int32_t *zl, int32_t *zr)
struct rouleur_mbhc_zdet_param *zdet_param,
int32_t *zl, int32_t *zr, s16 *d1_a)
{ {
struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
int32_t zdet = 0; int32_t zdet = 0;
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL,
0x70, zdet_param->ldo_ctl << 4);
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN5, 0xFC,
zdet_param->btn5);
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN6, 0xFC,
zdet_param->btn6);
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN7, 0xFC,
zdet_param->btn7);
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL,
0x0F, zdet_param->noff);
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_RAMP_CTL,
0x0F, zdet_param->nshift);
if (!zl) if (!zl)
goto z_right; goto z_right;
/* Start impedance measurement for HPH_L */
/* HPHL pull down switch to force OFF */
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x00);
/* Averaging enable for reliable results */
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80);
/* ZDET left measurement enable */
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET, 0x80, 0x80); ROULEUR_ANA_MBHC_ZDET, 0x80, 0x80);
dev_dbg(rouleur->dev, "%s: ramp for HPH_L, noff = %d\n", /* Calculate the left Rload result */
__func__, zdet_param->noff); rouleur_mbhc_get_result_params(rouleur, component, &zdet);
rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet);
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET, 0x80, 0x00); ROULEUR_ANA_MBHC_ZDET, 0x80, 0x00);
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00);
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x20);
*zl = zdet; *zl = zdet;
z_right: z_right:
if (!zr) if (!zr)
return; return;
/* Start impedance measurement for HPH_R */ /* HPHR pull down switch to force OFF */
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x00);
/* Averaging enable for reliable results */
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80);
/* ZDET right measurement enable */
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET, 0x40, 0x40); ROULEUR_ANA_MBHC_ZDET, 0x40, 0x40);
dev_dbg(rouleur->dev, "%s: ramp for HPH_R, noff = %d\n",
__func__, zdet_param->noff); /* Calculate the right Rload result */
rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet); rouleur_mbhc_get_result_params(rouleur, component, &zdet);
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET, 0x40, 0x00); ROULEUR_ANA_MBHC_ZDET, 0x40, 0x00);
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00);
regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x08);
*zr = zdet; *zr = zdet;
} }
static inline void rouleur_wcd_mbhc_qfuse_cal(
struct snd_soc_component *component,
int32_t *z_val, int flag_l_r)
{
s16 q1;
int q1_cal;
if (*z_val < (ROULEUR_ZDET_VAL_400/1000))
q1 = snd_soc_component_read32(component,
ROULEUR_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));
else
q1 = snd_soc_component_read32(component,
ROULEUR_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r));
if (q1 & 0x80)
q1_cal = (10000 - ((q1 & 0x7F) * 25));
else
q1_cal = (10000 + (q1 * 25));
if (q1_cal > 0)
*z_val = ((*z_val) * 10000) / q1_cal;
}
static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
uint32_t *zr) uint32_t *zr)
{ {
struct snd_soc_component *component = mbhc->component; struct snd_soc_component *component = mbhc->component;
struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); struct rouleur_priv *rouleur = dev_get_drvdata(component->dev);
s16 reg0, reg1, reg2, reg3, reg4; s16 reg0;
int32_t z1L, z1R, z1Ls; int32_t z1L, z1R, z1Ls;
int zMono, z_diff1, z_diff2; int zMono, z_diff1, z_diff2;
bool is_fsm_disable = false; bool is_fsm_disable = false;
struct rouleur_mbhc_zdet_param zdet_param[] = {
{4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
{2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
{1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
{1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
};
struct rouleur_mbhc_zdet_param *zdet_param_ptr = NULL;
s16 d1_a[][4] = {
{0, 30, 90, 30},
{0, 30, 30, 5},
{0, 30, 30, 5},
{0, 30, 30, 5},
};
s16 *d1 = NULL;
WCD_MBHC_RSC_ASSERT_LOCKED(mbhc); WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN5); reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT);
reg1 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN6);
reg2 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN7);
reg3 = snd_soc_component_read32(component, ROULEUR_MBHC_CTL_CLK);
reg4 = snd_soc_component_read32(component,
ROULEUR_ANA_MBHC_ZDET_ANA_CTL);
if (snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT) & if (reg0 & 0x80) {
0x80) {
is_fsm_disable = true; is_fsm_disable = true;
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ELECT, 0x80, 0x00); ROULEUR_ANA_MBHC_ELECT, 0x80, 0x00);
} }
/* Enable electrical bias */
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT,
0x01, 0x01);
/* Enable codec main bias */
rouleur_global_mbias_enable(component);
/* Enable RCO clock */
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1,
0x80, 0x80);
/* For NO-jack, disable L_DET_EN before Z-det measurements */ /* For NO-jack, disable L_DET_EN before Z-det measurements */
if (mbhc->hphl_swh) if (mbhc->hphl_swh)
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
@@ -553,79 +555,34 @@ static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_MECH, 0x01, 0x00); ROULEUR_ANA_MBHC_MECH, 0x01, 0x00);
/* Disable surge protection before impedance detection. /*
* Disable surge protection before impedance detection.
* This is done to give correct value for high impedance. * This is done to give correct value for high impedance.
*/ */
regmap_update_bits(rouleur->regmap, snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); 0xC0, 0x00);
/* 1ms delay needed after disable surge protection */ /* 1ms delay needed after disable surge protection */
usleep_range(1000, 1010); usleep_range(1000, 1010);
/* First get impedance on Left */ /* Start of left ch impedance calculation */
d1 = d1_a[1]; rouleur_mbhc_zdet_start(component, &z1L, NULL);
zdet_param_ptr = &zdet_param[1];
rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
if (!ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
goto left_ch_impedance;
/* Second ramp for left ch */
if (z1L < ROULEUR_ZDET_VAL_32) {
zdet_param_ptr = &zdet_param[0];
d1 = d1_a[0];
} else if ((z1L > ROULEUR_ZDET_VAL_400) &&
(z1L <= ROULEUR_ZDET_VAL_1200)) {
zdet_param_ptr = &zdet_param[2];
d1 = d1_a[2];
} else if (z1L > ROULEUR_ZDET_VAL_1200) {
zdet_param_ptr = &zdet_param[3];
d1 = d1_a[3];
}
rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
left_ch_impedance:
if ((z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) || if ((z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
(z1L > ROULEUR_ZDET_VAL_100K)) { (z1L > ROULEUR_ZDET_VAL_100K))
*zl = ROULEUR_ZDET_FLOATING_IMPEDANCE; *zl = ROULEUR_ZDET_FLOATING_IMPEDANCE;
zdet_param_ptr = &zdet_param[1]; else
d1 = d1_a[1];
} else {
*zl = z1L/1000; *zl = z1L/1000;
rouleur_wcd_mbhc_qfuse_cal(component, zl, 0);
}
dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n", dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
__func__, *zl); __func__, *zl);
/* Start of right impedance ramp and calculation */ /* Start of right ch impedance calculation */
rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); rouleur_mbhc_zdet_start(component, NULL, &z1R);
if (ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
if (((z1R > ROULEUR_ZDET_VAL_1200) &&
(zdet_param_ptr->noff == 0x6)) ||
((*zl) != ROULEUR_ZDET_FLOATING_IMPEDANCE))
goto right_ch_impedance;
/* Second ramp for right ch */
if (z1R < ROULEUR_ZDET_VAL_32) {
zdet_param_ptr = &zdet_param[0];
d1 = d1_a[0];
} else if ((z1R > ROULEUR_ZDET_VAL_400) &&
(z1R <= ROULEUR_ZDET_VAL_1200)) {
zdet_param_ptr = &zdet_param[2];
d1 = d1_a[2];
} else if (z1R > ROULEUR_ZDET_VAL_1200) {
zdet_param_ptr = &zdet_param[3];
d1 = d1_a[3];
}
rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL,
&z1R, d1);
}
right_ch_impedance:
if ((z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) || if ((z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
(z1R > ROULEUR_ZDET_VAL_100K)) { (z1R > ROULEUR_ZDET_VAL_100K))
*zr = ROULEUR_ZDET_FLOATING_IMPEDANCE; *zr = ROULEUR_ZDET_FLOATING_IMPEDANCE;
} else { else
*zr = z1R/1000; *zr = z1R/1000;
rouleur_wcd_mbhc_qfuse_cal(component, zr, 1);
}
dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n", dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
__func__, *zr); __func__, *zr);
@@ -647,24 +604,10 @@ right_ch_impedance:
mbhc->hph_type = WCD_MBHC_HPH_MONO; mbhc->hph_type = WCD_MBHC_HPH_MONO;
goto zdet_complete; goto zdet_complete;
} }
snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST,
0x02, 0x02); z1Ls = z1L/1000;
snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2, /* Parallel of left Z and 20 ohm pull down resistor */
0x40, 0x01); zMono = ((*zl) * 20) / ((*zl) + 20);
if (*zl < (ROULEUR_ZDET_VAL_32/1000))
rouleur_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls,
NULL, d1);
else
rouleur_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls,
NULL, d1);
snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2,
0x40, 0x00);
snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST,
0x02, 0x00);
z1Ls /= 1000;
rouleur_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);
/* Parallel of left Z and 9 ohm pull down resistor */
zMono = ((*zl) * 9) / ((*zl) + 9);
z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls); z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl)); z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) { if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
@@ -677,13 +620,10 @@ right_ch_impedance:
mbhc->hph_type = WCD_MBHC_HPH_MONO; mbhc->hph_type = WCD_MBHC_HPH_MONO;
} }
zdet_complete:
/* Enable surge protection again after impedance detection */ /* Enable surge protection again after impedance detection */
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
zdet_complete:
snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN5, reg0);
snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN6, reg1);
snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN7, reg2);
/* Turn on 100k pull down on HPHL */ /* Turn on 100k pull down on HPHL */
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_MECH, 0x01, 0x01); ROULEUR_ANA_MBHC_MECH, 0x01, 0x01);
@@ -693,13 +633,14 @@ zdet_complete:
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_MECH, 0x80, 0x80); ROULEUR_ANA_MBHC_MECH, 0x80, 0x80);
snd_soc_component_write(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, reg4); /* Restore electrical bias state */
snd_soc_component_write(component, ROULEUR_MBHC_CTL_CLK, reg3); snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, 0x01,
reg0 >> 7);
if (is_fsm_disable) if (is_fsm_disable)
regmap_update_bits(rouleur->regmap, regmap_update_bits(rouleur->regmap,
ROULEUR_ANA_MBHC_ELECT, 0x80, 0x80); ROULEUR_ANA_MBHC_ELECT, 0x80, 0x80);
rouleur_global_mbias_disable(component);
} }
#endif
static void rouleur_mbhc_gnd_det_ctrl(struct snd_soc_component *component, static void rouleur_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
bool enable) bool enable)
@@ -723,10 +664,10 @@ static void rouleur_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
if (enable) { if (enable) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2, ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x30, 0x10); 0x30, 0x20);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2, ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x0C, 0x04); 0x0C, 0x08);
} else { } else {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2, ROULEUR_ANA_HPHPA_CNP_CTL_2,
@@ -820,6 +761,54 @@ static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
rouleur_disable_bcs_before_slow_insert(mbhc->component, true); rouleur_disable_bcs_before_slow_insert(mbhc->component, true);
} }
static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb)
{
u8 vout_ctl = 0;
/* Read MBHC Micbias (Mic Bias2) voltage */
WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
/* Formula for getting micbias from vout
* micbias = 1.6V + VOUT_CTL * 50mV
*/
*mb = 1600 + (vout_ctl * 50);
pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb);
}
static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc,
bool az_enable)
{
if (az_enable)
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x08);
else
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x00);
}
static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc,
bool surge_enable)
{
if (surge_enable)
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
else
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_SURGE_EN, 0xC0, 0x00);
}
static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc)
{
mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD;
mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD;
pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n",
__func__, mbhc->hphl_cross_conn_thr,
mbhc->hphr_cross_conn_thr);
}
static const struct wcd_mbhc_cb mbhc_cb = { static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = rouleur_mbhc_request_irq, .request_irq = rouleur_mbhc_request_irq,
.irq_control = rouleur_mbhc_irq_control, .irq_control = rouleur_mbhc_irq_control,
@@ -837,13 +826,17 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.mbhc_micb_ramp_control = rouleur_mbhc_micb_ramp_control, .mbhc_micb_ramp_control = rouleur_mbhc_micb_ramp_control,
.get_hwdep_fw_cal = rouleur_get_hwdep_fw_cal, .get_hwdep_fw_cal = rouleur_get_hwdep_fw_cal,
.mbhc_micb_ctrl_thr_mic = rouleur_mbhc_micb_ctrl_threshold_mic, .mbhc_micb_ctrl_thr_mic = rouleur_mbhc_micb_ctrl_threshold_mic,
//.compute_impedance = rouleur_wcd_mbhc_calc_impedance, .compute_impedance = rouleur_wcd_mbhc_calc_impedance,
.mbhc_gnd_det_ctrl = rouleur_mbhc_gnd_det_ctrl, .mbhc_gnd_det_ctrl = rouleur_mbhc_gnd_det_ctrl,
.hph_pull_down_ctrl = rouleur_mbhc_hph_pull_down_ctrl, .hph_pull_down_ctrl = rouleur_mbhc_hph_pull_down_ctrl,
.mbhc_moisture_config = rouleur_mbhc_moisture_config, .mbhc_moisture_config = rouleur_mbhc_moisture_config,
.mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status, .mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status,
.mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en, .mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en,
.bcs_enable = rouleur_mbhc_bcs_enable, .bcs_enable = rouleur_mbhc_bcs_enable,
.get_micbias_val = rouleur_mbhc_get_micbias_val,
.mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control,
.mbhc_surge_ctl = rouleur_mbhc_surge_control,
.update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr,
}; };
static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol, static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol,

View File

@@ -45,7 +45,7 @@ enum {
#define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL (ROULEUR_ANA_BASE_ADDR+0x06A) #define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL (ROULEUR_ANA_BASE_ADDR+0x06A)
#define ROULEUR_ANA_MBHC_FSM_STATUS (ROULEUR_ANA_BASE_ADDR+0x06B) #define ROULEUR_ANA_MBHC_FSM_STATUS (ROULEUR_ANA_BASE_ADDR+0x06B)
#define ROULEUR_ANA_MBHC_ADC_RESULT (ROULEUR_ANA_BASE_ADDR+0x06C) #define ROULEUR_ANA_MBHC_ADC_RESULT (ROULEUR_ANA_BASE_ADDR+0x06C)
#define ROULEUR_ANA_MBHC_MCLK (ROULEUR_ANA_BASE_ADDR+0x06D) #define ROULEUR_ANA_MBHC_CTL_CLK (ROULEUR_ANA_BASE_ADDR+0x06D)
#define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT (ROULEUR_ANA_BASE_ADDR+0x072) #define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT (ROULEUR_ANA_BASE_ADDR+0x072)
#define ROULEUR_ANA_NCP_EN (ROULEUR_ANA_BASE_ADDR+0x077) #define ROULEUR_ANA_NCP_EN (ROULEUR_ANA_BASE_ADDR+0x077)
#define ROULEUR_ANA_HPHPA_CNP_CTL_1 (ROULEUR_ANA_BASE_ADDR+0x083) #define ROULEUR_ANA_HPHPA_CNP_CTL_1 (ROULEUR_ANA_BASE_ADDR+0x083)

View File

@@ -38,13 +38,15 @@ static const struct reg_default rouleur_defaults[] = {
{ ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, 0x00 }, { ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, 0x00 },
{ ROULEUR_ANA_MBHC_FSM_STATUS, 0x00 }, { ROULEUR_ANA_MBHC_FSM_STATUS, 0x00 },
{ ROULEUR_ANA_MBHC_ADC_RESULT, 0x00 }, { ROULEUR_ANA_MBHC_ADC_RESULT, 0x00 },
{ ROULEUR_ANA_MBHC_MCLK, 0x30 }, { ROULEUR_ANA_MBHC_CTL_CLK, 0x30 },
{ ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 }, { ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 },
{ ROULEUR_ANA_NCP_EN, 0x00 }, { ROULEUR_ANA_NCP_EN, 0x00 },
{ ROULEUR_ANA_HPHPA_CNP_CTL_1, 0x54 }, { ROULEUR_ANA_HPHPA_CNP_CTL_1, 0x54 },
{ ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x2B }, { ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x2B },
{ ROULEUR_ANA_HPHPA_PA_STATUS, 0x00 }, { ROULEUR_ANA_HPHPA_PA_STATUS, 0x00 },
{ ROULEUR_ANA_HPHPA_FSM_CLK, 0x12 }, { ROULEUR_ANA_HPHPA_FSM_CLK, 0x12 },
{ ROULEUR_ANA_HPHPA_L_GAIN, 0x00 },
{ ROULEUR_ANA_HPHPA_R_GAIN, 0x00 },
{ ROULEUR_SWR_HPHPA_HD2, 0x1B }, { ROULEUR_SWR_HPHPA_HD2, 0x1B },
{ ROULEUR_ANA_HPHPA_SPARE_CTL, 0x02 }, { ROULEUR_ANA_HPHPA_SPARE_CTL, 0x02 },
{ ROULEUR_ANA_SURGE_EN, 0x38 }, { ROULEUR_ANA_SURGE_EN, 0x38 },

View File

@@ -33,13 +33,15 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG(
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_MCLK)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_CLK)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_FSM_CLK)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_FSM_CLK)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_L_GAIN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_R_GAIN)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_HPHPA_SPARE_CTL)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_SPARE_CTL)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_SWR_HPHPA_HD2)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_SWR_HPHPA_HD2)] = RD_WR_REG,
[ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG,

View File

@@ -46,6 +46,7 @@ enum {
HPH_COMP_DELAY, HPH_COMP_DELAY,
HPH_PA_DELAY, HPH_PA_DELAY,
AMIC2_BCS_ENABLE, AMIC2_BCS_ENABLE,
WCD_SUPPLIES_LPM_MODE,
}; };
/* TODO: Check on the step values */ /* TODO: Check on the step values */
@@ -107,6 +108,9 @@ static int rouleur_handle_post_irq(void *data)
static int rouleur_init_reg(struct snd_soc_component *component) static int rouleur_init_reg(struct snd_soc_component *component)
{ {
/* Disable HPH OCP */
snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x03, 0x00);
/* Enable surge protection */ /* Enable surge protection */
snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN, snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
0xC0, 0xC0); 0xC0, 0xC0);
@@ -301,7 +305,7 @@ static int rouleur_rx_connect_port(struct snd_soc_component *component,
return ret; return ret;
} }
static int rouleur_global_mbias_enable(struct snd_soc_component *component) int rouleur_global_mbias_enable(struct snd_soc_component *component)
{ {
struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
@@ -319,7 +323,7 @@ static int rouleur_global_mbias_enable(struct snd_soc_component *component)
return 0; return 0;
} }
static int rouleur_global_mbias_disable(struct snd_soc_component *component) int rouleur_global_mbias_disable(struct snd_soc_component *component)
{ {
struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
@@ -354,7 +358,7 @@ static int rouleur_rx_clk_enable(struct snd_soc_component *component)
usleep_range(5000, 5100); usleep_range(5000, 5100);
rouleur_global_mbias_enable(component); rouleur_global_mbias_enable(component);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x11); ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80); ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
@@ -382,14 +386,14 @@ static int rouleur_rx_clk_disable(struct snd_soc_component *component)
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00); ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x00); ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_NCP_EN, 0x01, 0x00); ROULEUR_ANA_NCP_EN, 0x01, 0x00);
rouleur_global_mbias_disable(component);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00); ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00); ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00);
rouleur_global_mbias_disable(component);
} }
mutex_unlock(&rouleur->rx_clk_lock); mutex_unlock(&rouleur->rx_clk_lock);
@@ -469,23 +473,27 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
} }
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX0_CTL, ROULEUR_DIG_SWR_CDC_RX0_CTL,
0x7C, 0x7C); 0x80, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x04); 0x04, 0x04);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x01); ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x01);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x00); 0x01, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX0_CTL,
0x80, 0x80);
if (rouleur->comp1_enable)
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
0x02, 0x00);
break; break;
} }
@@ -540,22 +548,26 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
} }
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX1_CTL, ROULEUR_DIG_SWR_CDC_RX1_CTL,
0x7C, 0x7C); 0x80, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x08, 0x08); 0x08, 0x08);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x02); ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x02);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL1,
0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL1,
0x03, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00); ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x08, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX1_CTL,
0x80, 0x80);
if (rouleur->comp2_enable)
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
0x01, 0x00);
break; break;
} }
@@ -578,25 +590,25 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w,
rouleur_rx_clk_enable(component); rouleur_rx_clk_enable(component);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX0_CTL, ROULEUR_DIG_SWR_CDC_RX0_CTL,
0x7C, 0x7C); 0x80, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x01);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x03);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x04); 0x04, 0x04);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x01);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x00); 0x01, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX0_CTL,
0x80, 0x80);
break; break;
}; };
@@ -622,14 +634,11 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
rouleur->rx_swr_dev->dev_num, rouleur->rx_swr_dev->dev_num,
true); true);
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x40, 0x40);
set_bit(HPH_PA_DELAY, &rouleur->status_mask); set_bit(HPH_PA_DELAY, &rouleur->status_mask);
/* TODO: WHY SECOND TIME */ usleep_range(5000, 5100);
ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, snd_soc_component_update_bits(component,
rouleur->rx_swr_dev->dev_num, ROULEUR_DIG_SWR_PDM_WD_CTL1,
true); 0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
/* /*
@@ -676,8 +685,8 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
WCD_EVENT_POST_HPHR_PA_OFF, WCD_EVENT_POST_HPHR_PA_OFF,
&rouleur->mbhc->wcd_mbhc); &rouleur->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2, ROULEUR_DIG_SWR_PDM_WD_CTL1,
0x40, 0x00); 0x03, 0x00);
break; break;
}; };
return ret; return ret;
@@ -700,10 +709,11 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
rouleur->rx_swr_dev->dev_num, rouleur->rx_swr_dev->dev_num,
true); true);
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x80, 0x80);
set_bit(HPH_PA_DELAY, &rouleur->status_mask); set_bit(HPH_PA_DELAY, &rouleur->status_mask);
usleep_range(5000, 5100);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
/* /*
@@ -748,8 +758,8 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
WCD_EVENT_POST_HPHL_PA_OFF, WCD_EVENT_POST_HPHL_PA_OFF,
&rouleur->mbhc->wcd_mbhc); &rouleur->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_CNP_CTL_2, ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x80, 0x00); 0x03, 0x00);
break; break;
}; };
@@ -773,10 +783,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
rouleur->rx_swr_dev->dev_num, rouleur->rx_swr_dev->dev_num,
true); true);
snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL,
0x80, 0x80);
usleep_range(5000, 5100); usleep_range(5000, 5100);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
if (rouleur->update_wcd_event) if (rouleur->update_wcd_event)
@@ -795,10 +805,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
(WCD_RX1 << 0x10 | 0x1)); (WCD_RX1 << 0x10 | 0x1));
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL,
0x80, 0x00);
usleep_range(5000, 5100); usleep_range(5000, 5100);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x00);
}; };
return ret; return ret;
} }
@@ -823,10 +833,10 @@ static int rouleur_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL, ROULEUR_ANA_COMBOPA_CTL,
0x40, 0x40); 0x40, 0x40);
snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL,
0x80, 0x80);
usleep_range(5000, 5100); usleep_range(5000, 5100);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x03);
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
if (rouleur->update_wcd_event) if (rouleur->update_wcd_event)
@@ -845,13 +855,13 @@ static int rouleur_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
(WCD_RX1 << 0x10 | 0x1)); (WCD_RX1 << 0x10 | 0x1));
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL,
0x80, 0x00);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
ROULEUR_ANA_COMBOPA_CTL, ROULEUR_ANA_COMBOPA_CTL,
0x40, 0x00); 0x40, 0x00);
usleep_range(5000, 5100); usleep_range(5000, 5100);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_PDM_WD_CTL0,
0x03, 0x00);
}; };
return ret; return ret;
} }
@@ -1166,6 +1176,7 @@ int rouleur_micbias_control(struct snd_soc_component *component,
int post_on_event = 0, post_dapm_off = 0; int post_on_event = 0, post_dapm_off = 0;
int post_dapm_on = 0; int post_dapm_on = 0;
u8 pullup_mask = 0, enable_mask = 0; u8 pullup_mask = 0, enable_mask = 0;
int ret = 0;
if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) { if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) {
dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n", dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n",
@@ -1201,6 +1212,12 @@ int rouleur_micbias_control(struct snd_soc_component *component,
switch (req) { switch (req) {
case MICB_PULLUP_ENABLE: case MICB_PULLUP_ENABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
rouleur->pullup_ref[micb_index]++; rouleur->pullup_ref[micb_index]++;
if ((rouleur->pullup_ref[micb_index] == 1) && if ((rouleur->pullup_ref[micb_index] == 1) &&
(rouleur->micb_ref[micb_index] == 0)) (rouleur->micb_ref[micb_index] == 0))
@@ -1208,6 +1225,12 @@ int rouleur_micbias_control(struct snd_soc_component *component,
pullup_mask, pullup_mask); pullup_mask, pullup_mask);
break; break;
case MICB_PULLUP_DISABLE: case MICB_PULLUP_DISABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
if (rouleur->pullup_ref[micb_index] > 0) if (rouleur->pullup_ref[micb_index] > 0)
rouleur->pullup_ref[micb_index]--; rouleur->pullup_ref[micb_index]--;
if ((rouleur->pullup_ref[micb_index] == 0) && if ((rouleur->pullup_ref[micb_index] == 0) &&
@@ -1216,11 +1239,15 @@ int rouleur_micbias_control(struct snd_soc_component *component,
pullup_mask, 0x00); pullup_mask, 0x00);
break; break;
case MICB_ENABLE: case MICB_ENABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
rouleur->micb_ref[micb_index]++; rouleur->micb_ref[micb_index]++;
if (rouleur->micb_ref[micb_index] == 1) { if (rouleur->micb_ref[micb_index] == 1) {
rouleur_global_mbias_enable(component); rouleur_global_mbias_enable(component);
snd_soc_component_update_bits(component, micb_reg,
0x80, 0x80);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
micb_reg, enable_mask, enable_mask); micb_reg, enable_mask, enable_mask);
if (post_on_event) if (post_on_event)
@@ -1236,7 +1263,20 @@ int rouleur_micbias_control(struct snd_soc_component *component,
case MICB_DISABLE: case MICB_DISABLE:
if (rouleur->micb_ref[micb_index] > 0) if (rouleur->micb_ref[micb_index] > 0)
rouleur->micb_ref[micb_index]--; rouleur->micb_ref[micb_index]--;
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
if ((rouleur->micb_ref[micb_index] == 0) && if ((rouleur->micb_ref[micb_index] == 0) &&
(rouleur->pullup_ref[micb_index] > 0)) {
snd_soc_component_update_bits(component, micb_reg,
pullup_mask, pullup_mask);
snd_soc_component_update_bits(component, micb_reg,
enable_mask, 0x00);
rouleur_global_mbias_disable(component);
} else if ((rouleur->micb_ref[micb_index] == 0) &&
(rouleur->pullup_ref[micb_index] == 0)) { (rouleur->pullup_ref[micb_index] == 0)) {
if (pre_off_event && rouleur->mbhc) if (pre_off_event && rouleur->mbhc)
blocking_notifier_call_chain( blocking_notifier_call_chain(
@@ -1244,8 +1284,6 @@ int rouleur_micbias_control(struct snd_soc_component *component,
&rouleur->mbhc->wcd_mbhc); &rouleur->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, micb_reg, snd_soc_component_update_bits(component, micb_reg,
enable_mask, 0x00); enable_mask, 0x00);
snd_soc_component_update_bits(component, micb_reg,
0x80, 0x00);
rouleur_global_mbias_disable(component); rouleur_global_mbias_disable(component);
if (post_off_event && rouleur->mbhc) if (post_off_event && rouleur->mbhc)
blocking_notifier_call_chain( blocking_notifier_call_chain(
@@ -1263,8 +1301,8 @@ int rouleur_micbias_control(struct snd_soc_component *component,
dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n", dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
__func__, micb_num, rouleur->micb_ref[micb_index], __func__, micb_num, rouleur->micb_ref[micb_index],
rouleur->pullup_ref[micb_index]); rouleur->pullup_ref[micb_index]);
done:
mutex_unlock(&rouleur->micb_lock); mutex_unlock(&rouleur->micb_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(rouleur_micbias_control); EXPORT_SYMBOL(rouleur_micbias_control);
@@ -1304,6 +1342,17 @@ static int rouleur_get_logical_addr(struct swr_device *swr_dev)
return 0; return 0;
} }
static bool get_usbc_hs_status(struct snd_soc_component *component,
struct wcd_mbhc_config *mbhc_cfg)
{
if (mbhc_cfg->enable_usbc_analog) {
if (!(snd_soc_component_read32(component, ROULEUR_ANA_MBHC_MECH)
& 0x20))
return true;
}
return false;
}
static int rouleur_event_notify(struct notifier_block *block, static int rouleur_event_notify(struct notifier_block *block,
unsigned long val, unsigned long val,
void *data) void *data)
@@ -1333,8 +1382,11 @@ static int rouleur_event_notify(struct notifier_block *block,
0x80, 0x00); 0x80, 0x00);
break; break;
case BOLERO_WCD_EVT_SSR_DOWN: case BOLERO_WCD_EVT_SSR_DOWN:
rouleur->dev_up = false;
rouleur->mbhc->wcd_mbhc.deinit_in_progress = true; rouleur->mbhc->wcd_mbhc.deinit_in_progress = true;
mbhc = &rouleur->mbhc->wcd_mbhc; mbhc = &rouleur->mbhc->wcd_mbhc;
rouleur->usbc_hs_status = get_usbc_hs_status(component,
mbhc->mbhc_cfg);
rouleur_mbhc_ssr_down(rouleur->mbhc, component); rouleur_mbhc_ssr_down(rouleur->mbhc, component);
rouleur_reset(rouleur->dev, 0x01); rouleur_reset(rouleur->dev, 0x01);
break; break;
@@ -1356,8 +1408,11 @@ static int rouleur_event_notify(struct notifier_block *block,
__func__); __func__);
} else { } else {
rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg); rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg);
if (rouleur->usbc_hs_status)
mdelay(500);
} }
rouleur->mbhc->wcd_mbhc.deinit_in_progress = false; rouleur->mbhc->wcd_mbhc.deinit_in_progress = false;
rouleur->dev_up = true;
break; break;
default: default:
dev_err(component->dev, "%s: invalid event %d\n", __func__, dev_err(component->dev, "%s: invalid event %d\n", __func__,
@@ -1552,6 +1607,9 @@ static int rouleur_codec_enable_pa_vpos(struct snd_soc_dapm_widget *w,
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
set_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask); set_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
rouleur->rx_swr_dev->dev_num,
false);
break; break;
} }
return 0; return 0;
@@ -1822,7 +1880,7 @@ static ssize_t rouleur_version_read(struct snd_info_entry *entry,
switch (priv->version) { switch (priv->version) {
case ROULEUR_VERSION_1_0: case ROULEUR_VERSION_1_0:
len = snprintf(buffer, sizeof(buffer), "rouleur_1_0\n"); len = snprintf(buffer, sizeof(buffer), "ROULEUR_1_0\n");
break; break;
default: default:
len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n"); len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
@@ -1986,6 +2044,7 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
return ret; return ret;
} }
} }
rouleur->dev_up = true;
done: done:
return ret; return ret;
} }
@@ -2003,6 +2062,26 @@ static void rouleur_soc_codec_remove(struct snd_soc_component *component)
false); false);
} }
static int rouleur_soc_codec_suspend(struct snd_soc_component *component)
{
struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
if (!rouleur)
return 0;
rouleur->dapm_bias_off = true;
return 0;
}
static int rouleur_soc_codec_resume(struct snd_soc_component *component)
{
struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
if (!rouleur)
return 0;
rouleur->dapm_bias_off = false;
return 0;
}
static const struct snd_soc_component_driver soc_codec_dev_rouleur = { static const struct snd_soc_component_driver soc_codec_dev_rouleur = {
.name = DRV_NAME, .name = DRV_NAME,
.probe = rouleur_soc_codec_probe, .probe = rouleur_soc_codec_probe,
@@ -2013,6 +2092,8 @@ static const struct snd_soc_component_driver soc_codec_dev_rouleur = {
.num_dapm_widgets = ARRAY_SIZE(rouleur_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(rouleur_dapm_widgets),
.dapm_routes = rouleur_audio_map, .dapm_routes = rouleur_audio_map,
.num_dapm_routes = ARRAY_SIZE(rouleur_audio_map), .num_dapm_routes = ARRAY_SIZE(rouleur_audio_map),
.suspend = rouleur_soc_codec_suspend,
.resume = rouleur_soc_codec_resume,
}; };
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
@@ -2049,11 +2130,45 @@ static int rouleur_suspend(struct device *dev)
} }
clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask); clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask);
} }
if (rouleur->dapm_bias_off) {
msm_cdc_set_supplies_lpm_mode(rouleur->dev,
rouleur->supplies,
pdata->regulator,
pdata->num_supplies,
true);
set_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask);
}
return 0; return 0;
} }
static int rouleur_resume(struct device *dev) static int rouleur_resume(struct device *dev)
{ {
struct rouleur_priv *rouleur = NULL;
struct rouleur_pdata *pdata = NULL;
if (!dev)
return -ENODEV;
rouleur = dev_get_drvdata(dev);
if (!rouleur)
return -EINVAL;
pdata = dev_get_platdata(rouleur->dev);
if (!pdata) {
dev_err(dev, "%s: pdata is NULL\n", __func__);
return -EINVAL;
}
if (test_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask)) {
msm_cdc_set_supplies_lpm_mode(rouleur->dev,
rouleur->supplies,
pdata->regulator,
pdata->num_supplies,
false);
clear_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask);
}
return 0; return 0;
} }
#endif #endif
@@ -2484,10 +2599,8 @@ static int rouleur_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static const struct dev_pm_ops rouleur_dev_pm_ops = { static const struct dev_pm_ops rouleur_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS( .suspend_late = rouleur_suspend,
rouleur_suspend, .resume_early = rouleur_resume
rouleur_resume
)
}; };
#endif #endif

View File

@@ -11,15 +11,276 @@
#include <linux/component.h> #include <linux/component.h>
#include <soc/soundwire.h> #include <soc/soundwire.h>
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#define SWR_SLV_MAX_REG_ADDR 0x2009
#define SWR_SLV_START_REG_ADDR 0x40
#define SWR_SLV_MAX_BUF_LEN 20
#define BYTES_PER_LINE 12
#define SWR_SLV_RD_BUF_LEN 8
#define SWR_SLV_WR_BUF_LEN 32
#define SWR_SLV_MAX_DEVICES 2
#endif /* CONFIG_DEBUG_FS */
struct rouleur_slave_priv { struct rouleur_slave_priv {
struct swr_device *swr_slave; struct swr_device *swr_slave;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_rouleur_dent;
struct dentry *debugfs_peek;
struct dentry *debugfs_poke;
struct dentry *debugfs_reg_dump;
unsigned int read_data;
#endif
}; };
#ifdef CONFIG_DEBUG_FS
static int codec_debug_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static int get_parameters(char *buf, u32 *param1, int num_of_par)
{
char *token = NULL;
int base = 0, cnt = 0;
token = strsep(&buf, " ");
for (cnt = 0; cnt < num_of_par; cnt++) {
if (token) {
if ((token[1] == 'x') || (token[1] == 'X'))
base = 16;
else
base = 10;
if (kstrtou32(token, base, &param1[cnt]) != 0)
return -EINVAL;
token = strsep(&buf, " ");
} else {
return -EINVAL;
}
}
return 0;
}
static bool is_swr_slv_reg_readable(int reg)
{
int ret = true;
if (((reg > 0x46) && (reg < 0x4A)) ||
((reg > 0x4A) && (reg < 0x50)) ||
((reg > 0x55) && (reg < 0xD0)) ||
((reg > 0xD0) && (reg < 0xE0)) ||
((reg > 0xE0) && (reg < 0xF0)) ||
((reg > 0xF0) && (reg < 0x100)) ||
((reg > 0x105) && (reg < 0x120)) ||
((reg > 0x205) && (reg < 0x220)) ||
((reg > 0x305) && (reg < 0x320)) ||
((reg > 0x405) && (reg < 0x420)) ||
((reg > 0x128) && (reg < 0x130)) ||
((reg > 0x228) && (reg < 0x230)) ||
((reg > 0x328) && (reg < 0x330)) ||
((reg > 0x428) && (reg < 0x430)) ||
((reg > 0x138) && (reg < 0x205)) ||
((reg > 0x238) && (reg < 0x305)) ||
((reg > 0x338) && (reg < 0x405)) ||
((reg > 0x405) && (reg < 0xF00)) ||
((reg > 0xF05) && (reg < 0xF20)) ||
((reg > 0xF25) && (reg < 0xF30)) ||
((reg > 0xF35) && (reg < 0x2000)))
ret = false;
return ret;
}
static ssize_t rouleur_swrslave_reg_show(struct swr_device *pdev,
char __user *ubuf,
size_t count, loff_t *ppos)
{
int i, reg_val, len;
ssize_t total = 0;
char tmp_buf[SWR_SLV_MAX_BUF_LEN];
if (!ubuf || !ppos)
return 0;
for (i = (((int) *ppos/BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR);
i <= SWR_SLV_MAX_REG_ADDR; i++) {
if (!is_swr_slv_reg_readable(i))
continue;
swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
(reg_val & 0xFF));
if (len < 0) {
pr_err("%s: fail to fill the buffer\n", __func__);
total = -EFAULT;
goto copy_err;
}
if (((total + len) >= count - 1) || (len < 0))
break;
if (copy_to_user((ubuf + total), tmp_buf, len)) {
pr_err("%s: fail to copy reg dump\n", __func__);
total = -EFAULT;
goto copy_err;
}
total += len;
*ppos += len;
}
copy_err:
*ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE;
return total;
}
static ssize_t codec_debug_dump(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
struct swr_device *pdev;
if (!count || !file || !ppos || !ubuf)
return -EINVAL;
pdev = file->private_data;
if (!pdev)
return -EINVAL;
if (*ppos < 0)
return -EINVAL;
return rouleur_swrslave_reg_show(pdev, ubuf, count, ppos);
}
static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
char lbuf[SWR_SLV_RD_BUF_LEN];
struct swr_device *pdev = NULL;
struct rouleur_slave_priv *rouleur_slave = NULL;
if (!count || !file || !ppos || !ubuf)
return -EINVAL;
pdev = file->private_data;
if (!pdev)
return -EINVAL;
rouleur_slave = swr_get_dev_data(pdev);
if (!rouleur_slave)
return -EINVAL;
if (*ppos < 0)
return -EINVAL;
snprintf(lbuf, sizeof(lbuf), "0x%x\n",
(rouleur_slave->read_data & 0xFF));
return simple_read_from_buffer(ubuf, count, ppos, lbuf,
strnlen(lbuf, 7));
}
static ssize_t codec_debug_peek_write(struct file *file,
const char __user *ubuf, size_t cnt, loff_t *ppos)
{
char lbuf[SWR_SLV_WR_BUF_LEN];
int rc = 0;
u32 param[5];
struct swr_device *pdev = NULL;
struct rouleur_slave_priv *rouleur_slave = NULL;
if (!cnt || !file || !ppos || !ubuf)
return -EINVAL;
pdev = file->private_data;
if (!pdev)
return -EINVAL;
rouleur_slave = swr_get_dev_data(pdev);
if (!rouleur_slave)
return -EINVAL;
if (*ppos < 0)
return -EINVAL;
if (cnt > sizeof(lbuf) - 1)
return -EINVAL;
rc = copy_from_user(lbuf, ubuf, cnt);
if (rc)
return -EFAULT;
lbuf[cnt] = '\0';
rc = get_parameters(lbuf, param, 1);
if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)))
return -EINVAL;
swr_read(pdev, pdev->dev_num, param[0], &rouleur_slave->read_data, 1);
if (rc == 0)
rc = cnt;
else
pr_err("%s: rc = %d\n", __func__, rc);
return rc;
}
static ssize_t codec_debug_write(struct file *file,
const char __user *ubuf, size_t cnt, loff_t *ppos)
{
char lbuf[SWR_SLV_WR_BUF_LEN];
int rc = 0;
u32 param[5];
struct swr_device *pdev;
if (!file || !ppos || !ubuf)
return -EINVAL;
pdev = file->private_data;
if (!pdev)
return -EINVAL;
if (cnt > sizeof(lbuf) - 1)
return -EINVAL;
rc = copy_from_user(lbuf, ubuf, cnt);
if (rc)
return -EFAULT;
lbuf[cnt] = '\0';
rc = get_parameters(lbuf, param, 2);
if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) &&
(param[1] <= 0xFF) && (rc == 0)))
return -EINVAL;
swr_write(pdev, pdev->dev_num, param[0], &param[1]);
if (rc == 0)
rc = cnt;
else
pr_err("%s: rc = %d\n", __func__, rc);
return rc;
}
static const struct file_operations codec_debug_write_ops = {
.open = codec_debug_open,
.write = codec_debug_write,
};
static const struct file_operations codec_debug_read_ops = {
.open = codec_debug_open,
.read = codec_debug_read,
.write = codec_debug_peek_write,
};
static const struct file_operations codec_debug_dump_ops = {
.open = codec_debug_open,
.read = codec_debug_dump,
};
#endif
static int rouleur_slave_bind(struct device *dev, static int rouleur_slave_bind(struct device *dev,
struct device *master, void *data) struct device *master, void *data)
{ {
int ret = 0; int ret = 0;
struct rouleur_slave_priv *rouleur_slave = NULL;
uint8_t devnum = 0; uint8_t devnum = 0;
struct swr_device *pdev = to_swr_device(dev); struct swr_device *pdev = to_swr_device(dev);
@@ -28,15 +289,6 @@ static int rouleur_slave_bind(struct device *dev,
return -EINVAL; return -EINVAL;
} }
rouleur_slave = devm_kzalloc(&pdev->dev,
sizeof(struct rouleur_slave_priv), GFP_KERNEL);
if (!rouleur_slave)
return -ENOMEM;
swr_set_dev_data(pdev, rouleur_slave);
rouleur_slave->swr_slave = pdev;
ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, dev_dbg(&pdev->dev,
@@ -67,7 +319,6 @@ static void rouleur_slave_unbind(struct device *dev,
return; return;
} }
swr_set_dev_data(pdev, NULL);
} }
static const struct swr_device_id rouleur_swr_id[] = { static const struct swr_device_id rouleur_swr_id[] = {
@@ -104,12 +355,61 @@ static int rouleur_swr_reset(struct swr_device *pdev)
static int rouleur_swr_probe(struct swr_device *pdev) static int rouleur_swr_probe(struct swr_device *pdev)
{ {
struct rouleur_slave_priv *rouleur_slave = NULL;
rouleur_slave = devm_kzalloc(&pdev->dev,
sizeof(struct rouleur_slave_priv), GFP_KERNEL);
if (!rouleur_slave)
return -ENOMEM;
swr_set_dev_data(pdev, rouleur_slave);
rouleur_slave->swr_slave = pdev;
#ifdef CONFIG_DEBUG_FS
if (!rouleur_slave->debugfs_rouleur_dent) {
rouleur_slave->debugfs_rouleur_dent = debugfs_create_dir(
dev_name(&pdev->dev), 0);
if (!IS_ERR(rouleur_slave->debugfs_rouleur_dent)) {
rouleur_slave->debugfs_peek =
debugfs_create_file("swrslave_peek",
S_IFREG | 0444,
rouleur_slave->debugfs_rouleur_dent,
(void *) pdev,
&codec_debug_read_ops);
rouleur_slave->debugfs_poke =
debugfs_create_file("swrslave_poke",
S_IFREG | 0444,
rouleur_slave->debugfs_rouleur_dent,
(void *) pdev,
&codec_debug_write_ops);
rouleur_slave->debugfs_reg_dump =
debugfs_create_file(
"swrslave_reg_dump",
S_IFREG | 0444,
rouleur_slave->debugfs_rouleur_dent,
(void *) pdev,
&codec_debug_dump_ops);
}
}
#endif
return component_add(&pdev->dev, &rouleur_slave_comp_ops); return component_add(&pdev->dev, &rouleur_slave_comp_ops);
} }
static int rouleur_swr_remove(struct swr_device *pdev) static int rouleur_swr_remove(struct swr_device *pdev)
{ {
#ifdef CONFIG_DEBUG_FS
struct rouleur_slave_priv *rouleur_slave = swr_get_dev_data(pdev);
if (rouleur_slave) {
debugfs_remove_recursive(rouleur_slave->debugfs_rouleur_dent);
rouleur_slave->debugfs_rouleur_dent = NULL;
}
#endif
component_del(&pdev->dev, &rouleur_slave_comp_ops); component_del(&pdev->dev, &rouleur_slave_comp_ops);
swr_set_dev_data(pdev, NULL);
swr_remove_device(pdev);
return 0; return 0;
} }
@@ -140,5 +440,5 @@ static void __exit rouleur_slave_exit(void)
module_init(rouleur_slave_init); module_init(rouleur_slave_init);
module_exit(rouleur_slave_exit); module_exit(rouleur_slave_exit);
MODULE_DESCRIPTION("WCD937X Swr Slave driver"); MODULE_DESCRIPTION("Rouleur Swr Slave driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -30,6 +30,9 @@
#include "wcd938x/wcd938x.h" #include "wcd938x/wcd938x.h"
#include "swr-dmic.h" #include "swr-dmic.h"
#define NUM_ATTEMPTS 5
#define SWRS_SCP_CONTROL 0x44
static int swr_master_channel_map[] = { static int swr_master_channel_map[] = {
ZERO, ZERO,
SWRM_TX1_CH1, SWRM_TX1_CH1,
@@ -64,6 +67,7 @@ struct swr_dmic_priv {
int is_en_supply; int is_en_supply;
int port_type; int port_type;
u8 tx_master_port_map[SWR_DMIC_MAX_PORTS]; u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
struct notifier_block nblock;
}; };
const char *codec_name_list[] = { const char *codec_name_list[] = {
@@ -243,38 +247,6 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
return ret; return ret;
} }
static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct swr_dmic_priv *swr_dmic =
snd_soc_component_get_drvdata(component);
int ret = 0;
dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = swr_dmic_up(swr_dmic->swr_slave);
break;
case SND_SOC_DAPM_POST_PMU:
ret = swr_dmic_reset(swr_dmic->swr_slave);
break;
case SND_SOC_DAPM_POST_PMD:
ret = swr_dmic_down(swr_dmic->swr_slave);
break;
}
if (ret)
dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n",
__func__, w->name, event, ret);
return ret;
}
static const char * const tx_master_port_text[] = { static const char * const tx_master_port_text[] = {
"ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4",
"SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4",
@@ -304,10 +276,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("SWR_DMIC"), SND_SOC_DAPM_INPUT("SWR_DMIC"),
SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0,
swr_dmic_enable_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0, SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0,
swr_dmic_port_enable, swr_dmic_port_enable,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -315,7 +283,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
}; };
static const struct snd_soc_dapm_route swr_dmic_audio_map[] = { static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
{"SWR_DMIC", NULL, "SMIC_SUPPLY"},
{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"}, {"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
{"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"}, {"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"},
{"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"}, {"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"},
@@ -325,11 +292,38 @@ static int swr_dmic_codec_probe(struct snd_soc_component *component)
{ {
struct swr_dmic_priv *swr_dmic = struct swr_dmic_priv *swr_dmic =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
char w_name[100];
if (!swr_dmic) if (!swr_dmic)
return -EINVAL; return -EINVAL;
swr_dmic->component = component; swr_dmic->component = component;
snd_soc_dapm_ignore_suspend(dapm,
swr_dmic->dai_driver->capture.stream_name);
memset(w_name, 0, 100);
strlcpy(w_name, component->name_prefix, 100);
strlcat(w_name, " SWR_DMIC", 100);
snd_soc_dapm_ignore_suspend(dapm, w_name);
memset(w_name, 0, 100);
strlcpy(w_name, component->name_prefix, 100);
strlcat(w_name, " SMIC_SUPPLY", 100);
snd_soc_dapm_ignore_suspend(dapm, w_name);
memset(w_name, 0, 100);
strlcpy(w_name, component->name_prefix, 100);
strlcat(w_name, " SMIC_PORT_EN", 100);
snd_soc_dapm_ignore_suspend(dapm, w_name);
memset(w_name, 0, 100);
strlcpy(w_name, component->name_prefix, 100);
strlcat(w_name, " SWR_DMIC_OUTPUT", 100);
snd_soc_dapm_ignore_suspend(dapm, w_name);
snd_soc_dapm_sync(dapm);
return 0; return 0;
} }
@@ -364,6 +358,8 @@ static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable)
pr_err("%s: component is NULL\n", __func__); pr_err("%s: component is NULL\n", __func__);
return -EINVAL; return -EINVAL;
} }
dev_dbg(component->dev, "%s: supply %d micbias: %d enable: %d\n",
__func__, swr_dmic->is_en_supply, micb_num, enable);
if (enable) if (enable)
rc = wcd938x_codec_force_enable_micbias_v2(component, rc = wcd938x_codec_force_enable_micbias_v2(component,
@@ -412,6 +408,29 @@ static struct snd_soc_dai_driver swr_dmic_dai[] = {
}, },
}; };
static int swr_dmic_event_notify(struct notifier_block *block,
unsigned long val,
void *data)
{
u16 event = (val & 0xffff);
int ret = 0;
struct swr_dmic_priv *swr_dmic = container_of(block,
struct swr_dmic_priv,
nblock);
switch (event) {
case WCD938X_EVT_SSR_DOWN:
ret = swr_dmic_down(swr_dmic->swr_slave);
break;
case WCD938X_EVT_SSR_UP:
ret = swr_dmic_up(swr_dmic->swr_slave);
if (!ret)
ret = swr_dmic_reset(swr_dmic->swr_slave);
break;
}
return ret;
}
static int swr_dmic_probe(struct swr_device *pdev) static int swr_dmic_probe(struct swr_device *pdev)
{ {
int ret = 0; int ret = 0;
@@ -423,6 +442,7 @@ static int swr_dmic_probe(struct swr_device *pdev)
const char *swr_dmic_name_prefix_of = NULL; const char *swr_dmic_name_prefix_of = NULL;
const char *swr_dmic_codec_name_of = NULL; const char *swr_dmic_codec_name_of = NULL;
struct snd_soc_component *component = NULL; struct snd_soc_component *component = NULL;
int num_retry = NUM_ATTEMPTS;
swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv), swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv),
GFP_KERNEL); GFP_KERNEL);
@@ -485,13 +505,18 @@ static int swr_dmic_probe(struct swr_device *pdev)
* as per HW requirement. * as per HW requirement.
*/ */
usleep_range(5000, 5010); usleep_range(5000, 5010);
do {
/* Add delay for soundwire enumeration */
usleep_range(100, 110);
ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum); ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum);
} while (ret && --num_retry);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, dev_info(&pdev->dev,
"%s get devnum %d for dev addr %lx failed\n", "%s get devnum %d for dev addr %llx failed\n",
__func__, swr_devnum, pdev->addr); __func__, swr_devnum, pdev->addr);
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto err; goto dev_err;
} }
pdev->dev_num = swr_devnum; pdev->dev_num = swr_devnum;
@@ -561,10 +586,9 @@ static int swr_dmic_probe(struct swr_device *pdev)
strlen(swr_dmic_name_prefix_of) + 1); strlen(swr_dmic_name_prefix_of) + 1);
component->name_prefix = prefix_name; component->name_prefix = prefix_name;
if (swr_dmic->is_en_supply == 1) { swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
enable_wcd_codec_supply(swr_dmic, false); wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
--swr_dmic->is_en_supply; &swr_dmic->nblock, true);
}
return 0; return 0;
@@ -589,7 +613,10 @@ static int swr_dmic_remove(struct swr_device *pdev)
dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (swr_dmic->is_en_supply == 1) {
enable_wcd_codec_supply(swr_dmic, false);
--swr_dmic->is_en_supply;
}
snd_soc_unregister_component(&pdev->dev); snd_soc_unregister_component(&pdev->dev);
swr_set_dev_data(pdev, NULL); swr_set_dev_data(pdev, NULL);
return 0; return 0;
@@ -624,6 +651,8 @@ static int swr_dmic_down(struct swr_device *pdev)
return -EINVAL; return -EINVAL;
} }
dev_dbg(&pdev->dev, "%s: is_en_supply: %d\n",
__func__, swr_dmic->is_en_supply);
--swr_dmic->is_en_supply; --swr_dmic->is_en_supply;
if (swr_dmic->is_en_supply < 0) { if (swr_dmic->is_en_supply < 0) {
dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n", dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n",
@@ -641,7 +670,7 @@ done:
static int swr_dmic_reset(struct swr_device *pdev) static int swr_dmic_reset(struct swr_device *pdev)
{ {
struct swr_dmic_priv *swr_dmic; struct swr_dmic_priv *swr_dmic;
u8 retry = 5; u8 retry = NUM_ATTEMPTS;
u8 devnum = 0; u8 devnum = 0;
swr_dmic = swr_get_dev_data(pdev); swr_dmic = swr_get_dev_data(pdev);
@@ -706,7 +735,6 @@ static struct swr_driver swr_dmic_driver = {
.probe = swr_dmic_probe, .probe = swr_dmic_probe,
.remove = swr_dmic_remove, .remove = swr_dmic_remove,
.id_table = swr_dmic_id, .id_table = swr_dmic_id,
.device_down = swr_dmic_down,
}; };
static int __init swr_dmic_init(void) static int __init swr_dmic_init(void)

View File

@@ -186,12 +186,6 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
} }
break; break;
case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_PRE_PMD:
swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port,
&ch_mask, &port_type);
break;
case SND_SOC_DAPM_POST_PMD:
swr_slvdev_datapath_control(swr_hap->swr_slave,
swr_hap->swr_slave->dev_num, false);
/* stop SWR play */ /* stop SWR play */
val = 0; val = 0;
rc = regmap_write(swr_hap->regmap, SWR_PLAY_REG, val); rc = regmap_write(swr_hap->regmap, SWR_PLAY_REG, val);
@@ -200,6 +194,12 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
__func__, rc); __func__, rc);
return rc; return rc;
} }
break;
case SND_SOC_DAPM_POST_PMD:
swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port,
&ch_mask, &port_type);
swr_slvdev_datapath_control(swr_hap->swr_slave,
swr_hap->swr_slave->dev_num, false);
swr_device_wakeup_unvote(swr_hap->swr_slave); swr_device_wakeup_unvote(swr_hap->swr_slave);
break; break;
default: default:
@@ -314,6 +314,7 @@ static int swr_haptics_probe(struct swr_device *sdev)
struct swr_haptics_dev *swr_hap; struct swr_haptics_dev *swr_hap;
int rc; int rc;
u8 devnum; u8 devnum;
int retry = 5;
swr_hap = devm_kzalloc(&sdev->dev, swr_hap = devm_kzalloc(&sdev->dev,
sizeof(struct swr_haptics_dev), GFP_KERNEL); sizeof(struct swr_haptics_dev), GFP_KERNEL);
@@ -346,8 +347,12 @@ static int swr_haptics_probe(struct swr_device *sdev)
__func__, rc); __func__, rc);
goto clean; goto clean;
} }
do {
/* Add delay for soundwire enumeration */
usleep_range(500, 510);
rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum); rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum);
} while (rc && --retry);
if (rc) { if (rc) {
dev_err(swr_hap->dev, "%s: failed to get devnum for swr-haptics, rc=%d\n", dev_err(swr_hap->dev, "%s: failed to get devnum for swr-haptics, rc=%d\n",
__func__, rc); __func__, rc);

View File

@@ -33,6 +33,10 @@ static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
int micbias = 0; int micbias = 0;
u8 vout_ctl = 0; u8 vout_ctl = 0;
if (mbhc->mbhc_cb->get_micbias_val) {
mbhc->mbhc_cb->get_micbias_val(mbhc, &micbias);
pr_debug("%s: micbias: %d\n", __func__, micbias);
} else {
/* Read MBHC Micbias (Mic Bias2) voltage */ /* Read MBHC Micbias (Mic Bias2) voltage */
WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
@@ -42,7 +46,7 @@ static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
micbias = 1000 + (vout_ctl * 50); micbias = 1000 + (vout_ctl * 50);
pr_debug("%s: vout_ctl: %d, micbias: %d\n", pr_debug("%s: vout_ctl: %d, micbias: %d\n",
__func__, vout_ctl, micbias); __func__, vout_ctl, micbias);
}
return micbias; return micbias;
} }
@@ -76,8 +80,22 @@ static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc)
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
/* Set the MUX selection to IN2P */ /* Set the MUX selection to IN2P */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
/*
* Current source mode requires Auto zeroing to be enabled
* automatically. If HW doesn't do it, SW has to take care of this
* for button interrupts to work fine and to avoid
* fake electrical removal interrupts by enabling autozero before FSM
* enable and disable it after FSM enable
*/
if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
true);
/* Enable MBHC FSM */ /* Enable MBHC FSM */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
false);
/* Enable ADC_ENABLE bit */ /* Enable ADC_ENABLE bit */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1);
@@ -290,6 +308,10 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
/* Disable surge detection before ADC measurement */
if (mbhc->mbhc_cb->mbhc_surge_ctl)
mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, false);
/* Read and set ADC to single measurement */ /* Read and set ADC to single measurement */
WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode); WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode);
/* Read ADC Enable bit to restore after adc measurement */ /* Read ADC Enable bit to restore after adc measurement */
@@ -313,7 +335,12 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
goto done; goto done;
} }
if (hphl_adc_res > 100 || hphr_adc_res > 100) { /* Update cross connection threshold voltages if needed */
if (mbhc->mbhc_cb->update_cross_conn_thr)
mbhc->mbhc_cb->update_cross_conn_thr(mbhc);
if (hphl_adc_res > mbhc->hphl_cross_conn_thr ||
hphr_adc_res > mbhc->hphr_cross_conn_thr) {
plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP; plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
pr_debug("%s: Cross connection identified\n", __func__); pr_debug("%s: Cross connection identified\n", __func__);
} else { } else {
@@ -335,6 +362,10 @@ done:
/* Restore FSM state */ /* Restore FSM state */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en);
/* Restore surge detection */
if (mbhc->mbhc_cb->mbhc_surge_ctl)
mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, true);
/* Restore electrical detection */ /* Restore electrical detection */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);

View File

@@ -80,10 +80,12 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
struct snd_soc_component *component = mbhc->component; struct snd_soc_component *component = mbhc->component;
u32 reg_val; u32 reg_val;
plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration); plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(
mbhc->mbhc_cfg->calibration);
reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
dev_dbg(component->dev, "%s: reg_val = %x\n", __func__, reg_val); dev_dbg(component->dev, "%s: reg_val = %x\n",
__func__, reg_val);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
} }
@@ -1619,6 +1621,8 @@ static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc)
static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb, static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb,
unsigned long mode, void *ptr) unsigned long mode, void *ptr)
{ {
unsigned int l_det_en = 0;
unsigned int detection_type = 0;
struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, fsa_nb); struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, fsa_nb);
if (!mbhc) if (!mbhc)
@@ -1631,6 +1635,23 @@ static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb,
mbhc->mbhc_cb->clk_setup(mbhc->component, true); mbhc->mbhc_cb->clk_setup(mbhc->component, true);
/* insertion detected, enable L_DET_EN */ /* insertion detected, enable L_DET_EN */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
} else {
WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type);
WCD_MBHC_REG_READ(WCD_MBHC_L_DET_EN, l_det_en);
/* If both l_det_en and detection type are set, it means device was
* unplugged during SSR and detection interrupt was not handled.
* So trigger device disconnect */
if (detection_type && l_det_en) {
/* Set the detection type appropriately */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
!detection_type);
/* Set current plug type to the state before SSR */
mbhc->current_plug = mbhc->plug_before_ssr;
wcd_mbhc_swch_irq_handler(mbhc);
mbhc->mbhc_cb->lock_sleep(mbhc, false);
mbhc->plug_before_ssr = MBHC_PLUG_TYPE_NONE;
}
} }
return 0; return 0;
} }
@@ -1838,6 +1859,8 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_component *component,
mbhc->hph_type = WCD_MBHC_HPH_NONE; mbhc->hph_type = WCD_MBHC_HPH_NONE;
mbhc->wcd_mbhc_regs = wcd_mbhc_regs; mbhc->wcd_mbhc_regs = wcd_mbhc_regs;
mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD; mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD;
mbhc->hphl_cross_conn_thr = HPHL_CROSS_CONN_THRESHOLD;
mbhc->hphr_cross_conn_thr = HPHR_CROSS_CONN_THRESHOLD;
if (mbhc->intr_ids == NULL) { if (mbhc->intr_ids == NULL) {
pr_err("%s: Interrupt mapping not provided\n", __func__); pr_err("%s: Interrupt mapping not provided\n", __func__);

View File

@@ -8608,95 +8608,95 @@ static const struct soc_enum amic_pwr_lvl_enum =
amic_pwr_lvl_text); amic_pwr_lvl_text);
static const struct snd_kcontrol_new tasha_snd_controls[] = { static const struct snd_kcontrol_new tasha_snd_controls[] = {
SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume",
WCD9335_CDC_RX0_RX_VOL_MIX_CTL, WCD9335_CDC_RX0_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume",
WCD9335_CDC_RX1_RX_VOL_MIX_CTL, WCD9335_CDC_RX1_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume",
WCD9335_CDC_RX2_RX_VOL_MIX_CTL, WCD9335_CDC_RX2_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume",
WCD9335_CDC_RX3_RX_VOL_MIX_CTL, WCD9335_CDC_RX3_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume",
WCD9335_CDC_RX4_RX_VOL_MIX_CTL, WCD9335_CDC_RX4_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX5 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX5 Mix Digital Volume",
WCD9335_CDC_RX5_RX_VOL_MIX_CTL, WCD9335_CDC_RX5_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX6 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX6 Mix Digital Volume",
WCD9335_CDC_RX6_RX_VOL_MIX_CTL, WCD9335_CDC_RX6_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume",
WCD9335_CDC_RX7_RX_VOL_MIX_CTL, WCD9335_CDC_RX7_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume",
WCD9335_CDC_RX8_RX_VOL_MIX_CTL, WCD9335_CDC_RX8_RX_VOL_MIX_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("DEC0 Volume", WCD9335_CDC_TX0_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC0 Volume", WCD9335_CDC_TX0_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC1 Volume", WCD9335_CDC_TX1_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC1 Volume", WCD9335_CDC_TX1_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC2 Volume", WCD9335_CDC_TX2_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC2 Volume", WCD9335_CDC_TX2_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC3 Volume", WCD9335_CDC_TX3_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC3 Volume", WCD9335_CDC_TX3_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC4 Volume", WCD9335_CDC_TX4_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC4 Volume", WCD9335_CDC_TX4_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC5 Volume", WCD9335_CDC_TX5_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC5 Volume", WCD9335_CDC_TX5_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC6 Volume", WCD9335_CDC_TX6_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC6 Volume", WCD9335_CDC_TX6_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC7 Volume", WCD9335_CDC_TX7_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC7 Volume", WCD9335_CDC_TX7_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC8 Volume", WCD9335_CDC_TX8_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC8 Volume", WCD9335_CDC_TX8_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84,
40, digital_gain), 40, digital_gain),
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tasha_get_anc_slot, SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tasha_get_anc_slot,

View File

@@ -6548,77 +6548,77 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = {
SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain), SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain),
SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain), SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain),
SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL,
0, -84, 40, digital_gain), /* -84dB min - 40dB max */ -84, 40, digital_gain), /* -84dB min - 40dB max */
SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL, SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL,
0, -84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume",
WCD934X_CDC_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX0_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume",
WCD934X_CDC_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX1_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume",
WCD934X_CDC_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX2_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume",
WCD934X_CDC_RX3_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX3_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume",
WCD934X_CDC_RX4_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX4_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume",
WCD934X_CDC_RX7_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX7_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume", SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume",
WCD934X_CDC_RX8_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), WCD934X_CDC_RX8_RX_VOL_MIX_CTL, -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, 0, SOC_SINGLE_S8_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL,
-84, 40, digital_gain), -84, 40, digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40, WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
digital_gain), digital_gain),
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot, SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot,

View File

@@ -17,6 +17,7 @@
#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) #define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50)
#define MAX_PORT 8 #define MAX_PORT 8
#define MAX_CH_PER_PORT 8 #define MAX_CH_PER_PORT 8
#define MAX_TX_PWR_CH 2
#define WCD937X_MAX_SLAVE_PORT_TYPES 10 #define WCD937X_MAX_SLAVE_PORT_TYPES 10
extern struct regmap_config wcd937x_regmap_config; extern struct regmap_config wcd937x_regmap_config;
@@ -91,6 +92,7 @@ struct wcd937x_priv {
struct mutex ana_tx_clk_lock; struct mutex ana_tx_clk_lock;
u8 tx_master_ch_map[WCD937X_MAX_SLAVE_CH_TYPES]; u8 tx_master_ch_map[WCD937X_MAX_SLAVE_CH_TYPES];
bool usbc_hs_status; bool usbc_hs_status;
u32 tx_ch_pwr[MAX_TX_PWR_CH];
}; };
struct wcd937x_micbias_setting { struct wcd937x_micbias_setting {

View File

@@ -1777,6 +1777,48 @@ static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static int wcd937x_tx_ch_pwr_level_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
if (strnstr(kcontrol->id.name, "CH1", sizeof(kcontrol->id.name)))
ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[0];
else if (strnstr(kcontrol->id.name, "CH3", sizeof(kcontrol->id.name)))
ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[1];
return 0;
}
static int wcd937x_tx_ch_pwr_level_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
u32 pwr_level = ucontrol->value.enumerated.item[0];
dev_dbg(component->dev, "%s: tx ch pwr_level: %d\n",
__func__, pwr_level);
if (strnstr(kcontrol->id.name, "CH1",
sizeof(kcontrol->id.name))) {
snd_soc_component_update_bits(component,
WCD937X_ANA_TX_CH1, 0x60,
pwr_level << 0x5);
wcd937x->tx_ch_pwr[0] = pwr_level;
} else if (strnstr(kcontrol->id.name, "CH3",
sizeof(kcontrol->id.name))) {
snd_soc_component_update_bits(component,
WCD937X_ANA_TX_CH3, 0x60,
pwr_level << 0x5);
wcd937x->tx_ch_pwr[1] = pwr_level;
}
return 0;
}
static int wcd937x_ear_pa_gain_get(struct snd_kcontrol *kcontrol, static int wcd937x_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
@@ -2001,6 +2043,10 @@ static int wcd937x_tx_master_ch_put(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static const char * const wcd937x_tx_ch_pwr_level_text[] = {
"L0", "L1", "L2", "L3",
};
static const char * const wcd937x_ear_pa_gain_text[] = { static const char * const wcd937x_ear_pa_gain_text[] = {
"G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", "G_0_DB", "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", "G_0_DB",
"G_M1P5_DB", "G_M3_DB", "G_M4P5_DB", "G_M1P5_DB", "G_M3_DB", "G_M4P5_DB",
@@ -2016,6 +2062,9 @@ static const struct soc_enum rx_hph_mode_mux_enum =
static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_ear_pa_gain_enum, static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_ear_pa_gain_enum,
wcd937x_ear_pa_gain_text); wcd937x_ear_pa_gain_text);
static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_tx_ch_pwr_level_enum,
wcd937x_tx_ch_pwr_level_text);
static const struct snd_kcontrol_new wcd937x_snd_controls[] = { static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
SOC_ENUM_EXT("EAR PA GAIN", wcd937x_ear_pa_gain_enum, SOC_ENUM_EXT("EAR PA GAIN", wcd937x_ear_pa_gain_enum,
wcd937x_ear_pa_gain_get, wcd937x_ear_pa_gain_put), wcd937x_ear_pa_gain_get, wcd937x_ear_pa_gain_put),
@@ -2054,6 +2103,10 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put), wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put),
SOC_ENUM_EXT("DMIC5 ChMap", tx_master_ch_enum, SOC_ENUM_EXT("DMIC5 ChMap", tx_master_ch_enum,
wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put), wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put),
SOC_ENUM_EXT("TX CH1 PWR", wcd937x_tx_ch_pwr_level_enum,
wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put),
SOC_ENUM_EXT("TX CH3 PWR", wcd937x_tx_ch_pwr_level_enum,
wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put),
}; };
static const struct snd_kcontrol_new adc1_switch[] = { static const struct snd_kcontrol_new adc1_switch[] = {
@@ -3114,7 +3167,9 @@ static int wcd937x_bind(struct device *dev)
dev_err(dev, "%s: bad micbias pdata\n", __func__); dev_err(dev, "%s: bad micbias pdata\n", __func__);
goto err_irq; goto err_irq;
} }
/* default L1 power setting */
wcd937x->tx_ch_pwr[0] = 1;
wcd937x->tx_ch_pwr[1] = 1;
mutex_init(&wcd937x->micb_lock); mutex_init(&wcd937x->micb_lock);
mutex_init(&wcd937x->ana_tx_clk_lock); mutex_init(&wcd937x->ana_tx_clk_lock);
/* Request for watchdog interrupt */ /* Request for watchdog interrupt */

View File

@@ -73,6 +73,7 @@ struct wcd938x_priv {
bool comp2_enable; bool comp2_enable;
bool ldoh; bool ldoh;
bool bcs_dis; bool bcs_dis;
bool dapm_bias_off;
struct irq_domain *virq; struct irq_domain *virq;
struct wcd_irq_info irq_info; struct wcd_irq_info irq_info;
u32 rx_clk_cnt; u32 rx_clk_cnt;
@@ -105,6 +106,9 @@ struct wcd938x_priv {
bool dev_up; bool dev_up;
u8 tx_master_ch_map[WCD938X_MAX_SLAVE_CH_TYPES]; u8 tx_master_ch_map[WCD938X_MAX_SLAVE_CH_TYPES];
bool usbc_hs_status; bool usbc_hs_status;
/* wcd to swr dmic notification */
bool notify_swr_dmic;
struct blocking_notifier_head notifier;
}; };
struct wcd938x_micbias_setting { struct wcd938x_micbias_setting {

View File

@@ -24,6 +24,8 @@
#define SWR_SLV_MAX_DEVICES 2 #define SWR_SLV_MAX_DEVICES 2
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
#define SWR_MAX_RETRY 5
struct wcd938x_slave_priv { struct wcd938x_slave_priv {
struct swr_device *swr_slave; struct swr_device *swr_slave;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
@@ -278,17 +280,24 @@ static int wcd938x_slave_bind(struct device *dev,
int ret = 0; int ret = 0;
uint8_t devnum = 0; uint8_t devnum = 0;
struct swr_device *pdev = to_swr_device(dev); struct swr_device *pdev = to_swr_device(dev);
int retry = SWR_MAX_RETRY;
if (!pdev) { if (!pdev) {
pr_err("%s: invalid swr device handle\n", __func__); pr_err("%s: invalid swr device handle\n", __func__);
return -EINVAL; return -EINVAL;
} }
do {
/* Add delay for soundwire enumeration */
usleep_range(100, 110);
ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
} while (ret && --retry);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, dev_dbg(&pdev->dev,
"%s get devnum %d for dev addr %lx failed\n", "%s get devnum %d for dev addr %llx failed\n",
__func__, devnum, pdev->addr); __func__, devnum, pdev->addr);
ret = -EPROBE_DEFER;
return ret; return ret;
} }
pdev->dev_num = devnum; pdev->dev_num = devnum;

View File

@@ -72,6 +72,11 @@ enum {
HPH_COMP_DELAY, HPH_COMP_DELAY,
HPH_PA_DELAY, HPH_PA_DELAY,
AMIC2_BCS_ENABLE, AMIC2_BCS_ENABLE,
WCD_SUPPLIES_LPM_MODE,
WCD_ADC1_MODE,
WCD_ADC2_MODE,
WCD_ADC3_MODE,
WCD_ADC4_MODE,
}; };
enum { enum {
@@ -1540,13 +1545,17 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
if (strnstr(w->name, "ADC", sizeof("ADC"))) { if (strnstr(w->name, "ADC", sizeof("ADC"))) {
if (test_bit(WCD_ADC1, &wcd938x->status_mask)) if (test_bit(WCD_ADC1, &wcd938x->status_mask) ||
test_bit(WCD_ADC1_MODE, &wcd938x->status_mask))
mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]]; mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];
if (test_bit(WCD_ADC2, &wcd938x->status_mask)) if (test_bit(WCD_ADC2, &wcd938x->status_mask) ||
test_bit(WCD_ADC2_MODE, &wcd938x->status_mask))
mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]]; mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];
if (test_bit(WCD_ADC3, &wcd938x->status_mask)) if (test_bit(WCD_ADC3, &wcd938x->status_mask) ||
test_bit(WCD_ADC3_MODE, &wcd938x->status_mask))
mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]]; mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];
if (test_bit(WCD_ADC4, &wcd938x->status_mask)) if (test_bit(WCD_ADC4, &wcd938x->status_mask) ||
test_bit(WCD_ADC4_MODE, &wcd938x->status_mask))
mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]]; mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];
if (mode != 0) { if (mode != 0) {
@@ -1593,6 +1602,14 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
if (strnstr(w->name, "ADC", sizeof("ADC"))) if (strnstr(w->name, "ADC", sizeof("ADC")))
wcd938x_set_swr_clk_rate(component, rate, bank); wcd938x_set_swr_clk_rate(component, rate, bank);
if (strnstr(w->name, "ADC1", sizeof("ADC1")))
clear_bit(WCD_ADC1_MODE, &wcd938x->status_mask);
else if (strnstr(w->name, "ADC2", sizeof("ADC2")))
clear_bit(WCD_ADC2_MODE, &wcd938x->status_mask);
else if (strnstr(w->name, "ADC3", sizeof("ADC3")))
clear_bit(WCD_ADC3_MODE, &wcd938x->status_mask);
else if (strnstr(w->name, "ADC4", sizeof("ADC4")))
clear_bit(WCD_ADC4_MODE, &wcd938x->status_mask);
break; break;
}; };
@@ -1633,57 +1650,6 @@ static int wcd938x_get_adc_mode(int val)
return ret; return ret;
} }
static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event){
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
int clk_rate = 0, ret = 0;
dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
set_bit(w->shift, &wcd938x->status_mask);
clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]);
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
true);
break;
case SND_SOC_DAPM_POST_PMD:
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
false);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00);
clear_bit(w->shift, &wcd938x->status_mask);
break;
};
return ret;
}
void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
bool bcs_disable)
{
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->update_wcd_event) {
if (bcs_disable)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
else
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
}
}
int wcd938x_tx_channel_config(struct snd_soc_component *component, int wcd938x_tx_channel_config(struct snd_soc_component *component,
int channel, int mode) int channel, int mode)
{ {
@@ -1724,14 +1690,14 @@ int wcd938x_tx_channel_config(struct snd_soc_component *component,
return ret; return ret;
} }
static int wcd938x_enable_req(struct snd_soc_dapm_widget *w, static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol,
{ int event){
struct snd_soc_component *component = struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm); snd_soc_dapm_to_component(w->dapm);
int mode;
int ret = 0;
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
int clk_rate = 0, ret = 0;
int mode;
dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
w->name, event); w->name, event);
@@ -1739,9 +1705,14 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02); WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00); WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
set_bit(w->shift, &wcd938x->status_mask);
clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]);
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
true);
ret = wcd938x_tx_channel_config(component, w->shift, 1); ret = wcd938x_tx_channel_config(component, w->shift, 1);
mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]); mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
if (mode < 0) { if (mode < 0) {
@@ -1817,6 +1788,51 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
default: default:
break; break;
} }
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
false);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00);
clear_bit(w->shift, &wcd938x->status_mask);
break;
};
return ret;
}
void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
bool bcs_disable)
{
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->update_wcd_event) {
if (bcs_disable)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
else
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
}
}
static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
int ret = 0;
dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00); WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
break; break;
@@ -1991,15 +2007,16 @@ static int wcd938x_get_logical_addr(struct swr_device *swr_dev)
int num_retry = NUM_ATTEMPTS; int num_retry = NUM_ATTEMPTS;
do { do {
ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
if (ret) {
dev_err(&swr_dev->dev,
"%s get devnum %d for dev addr %lx failed\n",
__func__, devnum, swr_dev->addr);
/* retry after 1ms */ /* retry after 1ms */
usleep_range(1000, 1010); usleep_range(1000, 1010);
} ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
} while (ret && --num_retry); } while (ret && --num_retry);
if (ret)
dev_err(&swr_dev->dev,
"%s get devnum %d for dev addr %llx failed\n",
__func__, devnum, swr_dev->addr);
swr_dev->dev_num = devnum; swr_dev->dev_num = devnum;
return 0; return 0;
} }
@@ -2015,6 +2032,27 @@ static bool get_usbc_hs_status(struct snd_soc_component *component,
return false; return false;
} }
int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *component,
struct notifier_block *nblock,
bool enable)
{
struct wcd938x_priv *wcd938x_priv;
if(NULL == component) {
pr_err("%s: wcd938x component is NULL\n", __func__);
return -EINVAL;
}
wcd938x_priv = snd_soc_component_get_drvdata(component);
wcd938x_priv->notify_swr_dmic = enable;
if (enable)
return blocking_notifier_chain_register(&wcd938x_priv->notifier,
nblock);
else
return blocking_notifier_chain_unregister(
&wcd938x_priv->notifier, nblock);
}
EXPORT_SYMBOL(wcd938x_swr_dmic_register_notifier);
static int wcd938x_event_notify(struct notifier_block *block, static int wcd938x_event_notify(struct notifier_block *block,
unsigned long val, unsigned long val,
void *data) void *data)
@@ -2030,21 +2068,25 @@ static int wcd938x_event_notify(struct notifier_block *block,
if (test_bit(WCD_ADC1, &wcd938x->status_mask)) { if (test_bit(WCD_ADC1, &wcd938x->status_mask)) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_ANA_TX_CH2, 0x40, 0x00); WCD938X_ANA_TX_CH2, 0x40, 0x00);
set_bit(WCD_ADC1_MODE, &wcd938x->status_mask);
clear_bit(WCD_ADC1, &wcd938x->status_mask); clear_bit(WCD_ADC1, &wcd938x->status_mask);
} }
if (test_bit(WCD_ADC2, &wcd938x->status_mask)) { if (test_bit(WCD_ADC2, &wcd938x->status_mask)) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_ANA_TX_CH2, 0x20, 0x00); WCD938X_ANA_TX_CH2, 0x20, 0x00);
set_bit(WCD_ADC2_MODE, &wcd938x->status_mask);
clear_bit(WCD_ADC2, &wcd938x->status_mask); clear_bit(WCD_ADC2, &wcd938x->status_mask);
} }
if (test_bit(WCD_ADC3, &wcd938x->status_mask)) { if (test_bit(WCD_ADC3, &wcd938x->status_mask)) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_ANA_TX_CH4, 0x40, 0x00); WCD938X_ANA_TX_CH4, 0x40, 0x00);
set_bit(WCD_ADC3_MODE, &wcd938x->status_mask);
clear_bit(WCD_ADC3, &wcd938x->status_mask); clear_bit(WCD_ADC3, &wcd938x->status_mask);
} }
if (test_bit(WCD_ADC4, &wcd938x->status_mask)) { if (test_bit(WCD_ADC4, &wcd938x->status_mask)) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_ANA_TX_CH4, 0x20, 0x00); WCD938X_ANA_TX_CH4, 0x20, 0x00);
set_bit(WCD_ADC4_MODE, &wcd938x->status_mask);
clear_bit(WCD_ADC4, &wcd938x->status_mask); clear_bit(WCD_ADC4, &wcd938x->status_mask);
} }
break; break;
@@ -2058,7 +2100,13 @@ static int wcd938x_event_notify(struct notifier_block *block,
break; break;
case BOLERO_WCD_EVT_SSR_DOWN: case BOLERO_WCD_EVT_SSR_DOWN:
wcd938x->dev_up = false; wcd938x->dev_up = false;
if(wcd938x->notify_swr_dmic)
blocking_notifier_call_chain(&wcd938x->notifier,
WCD938X_EVT_SSR_DOWN,
NULL);
wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true; wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true;
wcd938x->mbhc->wcd_mbhc.plug_before_ssr =
wcd938x->mbhc->wcd_mbhc.current_plug;
mbhc = &wcd938x->mbhc->wcd_mbhc; mbhc = &wcd938x->mbhc->wcd_mbhc;
wcd938x->usbc_hs_status = get_usbc_hs_status(component, wcd938x->usbc_hs_status = get_usbc_hs_status(component,
mbhc->mbhc_cfg); mbhc->mbhc_cfg);
@@ -2089,6 +2137,10 @@ static int wcd938x_event_notify(struct notifier_block *block,
} }
wcd938x->mbhc->wcd_mbhc.deinit_in_progress = false; wcd938x->mbhc->wcd_mbhc.deinit_in_progress = false;
wcd938x->dev_up = true; wcd938x->dev_up = true;
if(wcd938x->notify_swr_dmic)
blocking_notifier_call_chain(&wcd938x->notifier,
WCD938X_EVT_SSR_UP,
NULL);
break; break;
case BOLERO_WCD_EVT_CLK_NOTIFY: case BOLERO_WCD_EVT_CLK_NOTIFY:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
@@ -2272,6 +2324,9 @@ static int wcd938x_enable_micbias(struct wcd938x_priv *wcd938x,
return -EINVAL; return -EINVAL;
}; };
pr_debug("%s: req: %d micb_num: %d micb_ref: %d pullup_ref: %d\n",
__func__, req, micb_num, wcd938x->micb_ref[micb_index],
wcd938x->pullup_ref[micb_index]);
mutex_lock(&wcd938x->micb_lock); mutex_lock(&wcd938x->micb_lock);
switch (req) { switch (req) {
@@ -2336,6 +2391,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
int event, int micb_num) int event, int micb_num)
{ {
struct wcd938x_priv *wcd938x_priv = NULL; struct wcd938x_priv *wcd938x_priv = NULL;
int ret = 0;
int micb_index = micb_num - 1;
if(NULL == component) { if(NULL == component) {
pr_err("%s: wcd938x component is NULL\n", __func__); pr_err("%s: wcd938x component is NULL\n", __func__);
@@ -2352,6 +2409,15 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
wcd938x_priv = snd_soc_component_get_drvdata(component); wcd938x_priv = snd_soc_component_get_drvdata(component);
if (!wcd938x_priv->dev_up) {
if ((wcd938x_priv->pullup_ref[micb_index] > 0) &&
(event == SND_SOC_DAPM_POST_PMD)) {
wcd938x_priv->pullup_ref[micb_index]--;
ret = -ENODEV;
goto done;
}
}
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
wcd938x_wakeup(wcd938x_priv, true); wcd938x_wakeup(wcd938x_priv, true);
@@ -2365,7 +2431,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
break; break;
} }
return 0; done:
return ret;
} }
EXPORT_SYMBOL(wcd938x_codec_force_enable_micbias_v2); EXPORT_SYMBOL(wcd938x_codec_force_enable_micbias_v2);
@@ -3050,9 +3117,17 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("AMIC5"), SND_SOC_DAPM_INPUT("AMIC5"),
SND_SOC_DAPM_INPUT("AMIC6"), SND_SOC_DAPM_INPUT("AMIC6"),
SND_SOC_DAPM_INPUT("AMIC7"), SND_SOC_DAPM_INPUT("AMIC7"),
SND_SOC_DAPM_INPUT("IN1_HPHL"), SND_SOC_DAPM_INPUT("IN1_HPHL"),
SND_SOC_DAPM_INPUT("IN2_HPHR"), SND_SOC_DAPM_INPUT("IN2_HPHR"),
SND_SOC_DAPM_INPUT("IN3_AUX"), SND_SOC_DAPM_INPUT("IN3_AUX"),
/*
* These dummy widgets are null connected to WCD938x dapm input and
* output widgets which are not actual path endpoints. This ensures
* dapm doesnt set these dapm input and output widgets as endpoints.
*/
SND_SOC_DAPM_INPUT("WCD_TX_DUMMY"),
SND_SOC_DAPM_OUTPUT("WCD_RX_DUMMY"),
/*tx widgets*/ /*tx widgets*/
SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
@@ -3289,6 +3364,7 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
static const struct snd_soc_dapm_route wcd938x_audio_map[] = { static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
{"WCD_TX_DUMMY", NULL, "WCD_TX_OUTPUT"},
{"WCD_TX_OUTPUT", NULL, "ADC1_MIXER"}, {"WCD_TX_OUTPUT", NULL, "ADC1_MIXER"},
{"ADC1_MIXER", "Switch", "ADC1 REQ"}, {"ADC1_MIXER", "Switch", "ADC1 REQ"},
{"ADC1 REQ", NULL, "ADC1"}, {"ADC1 REQ", NULL, "ADC1"},
@@ -3343,6 +3419,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
{"WCD_TX_OUTPUT", NULL, "DMIC8_MIXER"}, {"WCD_TX_OUTPUT", NULL, "DMIC8_MIXER"},
{"DMIC8_MIXER", "Switch", "DMIC8"}, {"DMIC8_MIXER", "Switch", "DMIC8"},
{"IN1_HPHL", NULL, "WCD_RX_DUMMY"},
{"IN1_HPHL", NULL, "VDD_BUCK"}, {"IN1_HPHL", NULL, "VDD_BUCK"},
{"IN1_HPHL", NULL, "CLS_H_PORT"}, {"IN1_HPHL", NULL, "CLS_H_PORT"},
{"RX1", NULL, "IN1_HPHL"}, {"RX1", NULL, "IN1_HPHL"},
@@ -3351,6 +3428,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
{"HPHL PGA", NULL, "HPHL_RDAC"}, {"HPHL PGA", NULL, "HPHL_RDAC"},
{"HPHL", NULL, "HPHL PGA"}, {"HPHL", NULL, "HPHL PGA"},
{"IN2_HPHR", NULL, "WCD_RX_DUMMY"},
{"IN2_HPHR", NULL, "VDD_BUCK"}, {"IN2_HPHR", NULL, "VDD_BUCK"},
{"IN2_HPHR", NULL, "CLS_H_PORT"}, {"IN2_HPHR", NULL, "CLS_H_PORT"},
{"RX2", NULL, "IN2_HPHR"}, {"RX2", NULL, "IN2_HPHR"},
@@ -3359,6 +3437,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
{"HPHR PGA", NULL, "HPHR_RDAC"}, {"HPHR PGA", NULL, "HPHR_RDAC"},
{"HPHR", NULL, "HPHR PGA"}, {"HPHR", NULL, "HPHR PGA"},
{"IN3_AUX", NULL, "WCD_RX_DUMMY"},
{"IN3_AUX", NULL, "VDD_BUCK"}, {"IN3_AUX", NULL, "VDD_BUCK"},
{"IN3_AUX", NULL, "CLS_H_PORT"}, {"IN3_AUX", NULL, "CLS_H_PORT"},
{"RX3", NULL, "IN3_AUX"}, {"RX3", NULL, "IN3_AUX"},
@@ -3634,6 +3713,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
goto err_hwdep; goto err_hwdep;
} }
snd_soc_dapm_ignore_suspend(dapm, "WCD938X_AIF Playback");
snd_soc_dapm_ignore_suspend(dapm, "WCD938X_AIF Capture");
snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
@@ -3649,6 +3730,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
snd_soc_dapm_ignore_suspend(dapm, "AUX"); snd_soc_dapm_ignore_suspend(dapm, "AUX");
snd_soc_dapm_ignore_suspend(dapm, "HPHL"); snd_soc_dapm_ignore_suspend(dapm, "HPHL");
snd_soc_dapm_ignore_suspend(dapm, "HPHR"); snd_soc_dapm_ignore_suspend(dapm, "HPHR");
snd_soc_dapm_ignore_suspend(dapm, "WCD_TX_DUMMY");
snd_soc_dapm_ignore_suspend(dapm, "WCD_RX_DUMMY");
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
wcd_cls_h_init(&wcd938x->clsh_info); wcd_cls_h_init(&wcd938x->clsh_info);
@@ -3688,7 +3771,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
return ret; return ret;
} }
} }
wcd938x->dev_up = true;
return ret; return ret;
err_hwdep: err_hwdep:
@@ -3713,6 +3795,26 @@ static void wcd938x_soc_codec_remove(struct snd_soc_component *component)
false); false);
} }
static int wcd938x_soc_codec_suspend(struct snd_soc_component *component)
{
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (!wcd938x)
return 0;
wcd938x->dapm_bias_off = true;
return 0;
}
static int wcd938x_soc_codec_resume(struct snd_soc_component *component)
{
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (!wcd938x)
return 0;
wcd938x->dapm_bias_off = false;
return 0;
}
static struct snd_soc_component_driver soc_codec_dev_wcd938x = { static struct snd_soc_component_driver soc_codec_dev_wcd938x = {
.name = WCD938X_DRV_NAME, .name = WCD938X_DRV_NAME,
.probe = wcd938x_soc_codec_probe, .probe = wcd938x_soc_codec_probe,
@@ -3723,6 +3825,8 @@ static struct snd_soc_component_driver soc_codec_dev_wcd938x = {
.num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),
.dapm_routes = wcd938x_audio_map, .dapm_routes = wcd938x_audio_map,
.num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map), .num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),
.suspend = wcd938x_soc_codec_suspend,
.resume = wcd938x_soc_codec_resume,
}; };
static int wcd938x_reset(struct device *dev) static int wcd938x_reset(struct device *dev)
@@ -4026,6 +4130,7 @@ static int wcd938x_bind(struct device *dev)
__func__); __func__);
goto err_irq; goto err_irq;
} }
wcd938x->dev_up = true;
return ret; return ret;
err_irq: err_irq:
@@ -4242,19 +4347,51 @@ static int wcd938x_suspend(struct device *dev)
} }
clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
} }
if (wcd938x->dapm_bias_off) {
msm_cdc_set_supplies_lpm_mode(wcd938x->dev,
wcd938x->supplies,
pdata->regulator,
pdata->num_supplies,
true);
set_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask);
}
return 0; return 0;
} }
static int wcd938x_resume(struct device *dev) static int wcd938x_resume(struct device *dev)
{ {
struct wcd938x_priv *wcd938x = NULL;
struct wcd938x_pdata *pdata = NULL;
if (!dev)
return -ENODEV;
wcd938x = dev_get_drvdata(dev);
if (!wcd938x)
return -EINVAL;
pdata = dev_get_platdata(wcd938x->dev);
if (!pdata) {
dev_err(dev, "%s: pdata is NULL\n", __func__);
return -EINVAL;
}
if (test_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask)) {
msm_cdc_set_supplies_lpm_mode(wcd938x->dev,
wcd938x->supplies,
pdata->regulator,
pdata->num_supplies,
false);
clear_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask);
}
return 0; return 0;
} }
static const struct dev_pm_ops wcd938x_dev_pm_ops = { static const struct dev_pm_ops wcd938x_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS( .suspend_late = wcd938x_suspend,
wcd938x_suspend, .resume_early = wcd938x_resume,
wcd938x_resume
)
}; };
#endif #endif

View File

@@ -17,6 +17,12 @@ enum {
WCD9385 = 5, WCD9385 = 5,
}; };
/* from WCD to SWR DMIC events */
enum {
WCD938X_EVT_SSR_DOWN,
WCD938X_EVT_SSR_UP,
};
struct swr_slave_ch_map { struct swr_slave_ch_map {
u8 ch_type; u8 ch_type;
u8 index; u8 index;
@@ -62,6 +68,9 @@ int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root,
int wcd938x_get_codec_variant(struct snd_soc_component *component); int wcd938x_get_codec_variant(struct snd_soc_component *component);
int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *wcd938x, int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *wcd938x,
int event, int micb_num); int event, int micb_num);
int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *wcd938x,
struct notifier_block *nblock,
bool enable);
static inline int wcd938x_slave_get_master_ch_val(int ch) static inline int wcd938x_slave_get_master_ch_val(int ch)
{ {

View File

@@ -1083,6 +1083,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
0x80, 0x00); 0x80, 0x00);
if (wsa881x->visense_enable) { if (wsa881x->visense_enable) {
wsa881x_visense_adc_ctrl(component, DISABLE); wsa881x_visense_adc_ctrl(component, DISABLE);
snd_soc_component_update_bits(component,
WSA881X_ADC_EN_SEL_IBAIS,
0x07, 0x00);
wsa881x_visense_txfe_ctrl(component, DISABLE, wsa881x_visense_txfe_ctrl(component, DISABLE,
0x00, 0x01, 0x01); 0x00, 0x01, 0x01);
} }
@@ -1614,8 +1617,6 @@ static int wsa881x_swr_down(struct swr_device *pdev)
else else
wsa881x->state = WSA881X_DEV_DOWN; wsa881x->state = WSA881X_DEV_DOWN;
if (delayed_work_pending(&wsa881x->ocp_ctl_work))
cancel_delayed_work_sync(&wsa881x->ocp_ctl_work);
return ret; return ret;
} }

View File

@@ -97,6 +97,7 @@ struct wsa883x_priv {
bool comp_enable; bool comp_enable;
bool visense_enable; bool visense_enable;
bool ext_vdd_spk; bool ext_vdd_spk;
bool dapm_bias_off;
struct swr_port port[WSA883X_MAX_SWR_PORTS]; struct swr_port port[WSA883X_MAX_SWR_PORTS];
int global_pa_cnt; int global_pa_cnt;
int dev_mode; int dev_mode;

View File

@@ -123,6 +123,7 @@ static const struct wsa_reg_mask_val reg_init[] = {
{WSA883X_GMAMP_SUP1, 0x60, 0x60}, {WSA883X_GMAMP_SUP1, 0x60, 0x60},
}; };
static int wsa883x_handle_post_irq(void *data);
static int wsa883x_get_temperature(struct snd_soc_component *component, static int wsa883x_get_temperature(struct snd_soc_component *component,
int *temp); int *temp);
enum { enum {
@@ -132,6 +133,7 @@ enum {
enum { enum {
SPKR_STATUS = 0, SPKR_STATUS = 0,
WSA_SUPPLIES_LPM_MODE,
}; };
enum { enum {
@@ -172,9 +174,24 @@ static struct regmap_irq_chip wsa883x_regmap_irq_chip = {
.ack_base = WSA883X_INTR_CLEAR0, .ack_base = WSA883X_INTR_CLEAR0,
.use_ack = 1, .use_ack = 1,
.runtime_pm = false, .runtime_pm = false,
.handle_post_irq = wsa883x_handle_post_irq,
.irq_drv_data = NULL, .irq_drv_data = NULL,
}; };
static int wsa883x_handle_post_irq(void *data)
{
struct wsa883x_priv *wsa883x = data;
u32 sts1 = 0, sts2 = 0;
regmap_read(wsa883x->regmap, WSA883X_INTR_STATUS0, &sts1);
regmap_read(wsa883x->regmap, WSA883X_INTR_STATUS1, &sts2);
wsa883x->swr_slave->slave_irq_pending =
((sts1 || sts2) ? true : false);
return IRQ_HANDLED;
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static int codec_debug_open(struct inode *inode, struct file *file) static int codec_debug_open(struct inode *inode, struct file *file)
{ {
@@ -253,7 +270,12 @@ static ssize_t swr_slave_reg_show(struct swr_device *pdev, char __user *ubuf,
swr_read(pdev, pdev->dev_num, i, &reg_val, 1); swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i, len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
(reg_val & 0xFF)); (reg_val & 0xFF));
if (((total + len) >= count - 1) || (len < 0)) if (len < 0) {
pr_err("%s: fail to fill the buffer\n", __func__);
total = -EFAULT;
goto copy_err;
}
if ((total + len) >= count - 1)
break; break;
if (copy_to_user((ubuf + total), tmp_buf, len)) { if (copy_to_user((ubuf + total), tmp_buf, len)) {
pr_err("%s: fail to copy reg dump\n", __func__); pr_err("%s: fail to copy reg dump\n", __func__);
@@ -598,9 +620,14 @@ static int wsa_get_temp(struct snd_kcontrol *kcontrol,
{ {
struct snd_soc_component *component = struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol); snd_soc_kcontrol_component(kcontrol);
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
int temp = 0; int temp = 0;
if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
temp = wsa883x->curr_temp;
else
wsa883x_get_temperature(component, &temp); wsa883x_get_temperature(component, &temp);
ucontrol->value.integer.value[0] = temp; ucontrol->value.integer.value[0] = temp;
return 0; return 0;
@@ -989,6 +1016,7 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
wsa883x->swr_slave->dev_num, wsa883x->swr_slave->dev_num,
true); true);
wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD); wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO);
/* Force remove group */ /* Force remove group */
swr_remove_from_group(wsa883x->swr_slave, swr_remove_from_group(wsa883x->swr_slave,
wsa883x->swr_slave->dev_num); wsa883x->swr_slave->dev_num);
@@ -998,6 +1026,7 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
0x01, 0x00); 0x01, 0x00);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD); wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO);
clear_bit(SPKR_STATUS, &wsa883x->status_mask); clear_bit(SPKR_STATUS, &wsa883x->status_mask);
break; break;
} }
@@ -1186,6 +1215,8 @@ static int wsa883x_codec_probe(struct snd_soc_component *component)
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
struct swr_device *dev; struct swr_device *dev;
int variant = 0, version = 0; int variant = 0, version = 0;
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
if (!wsa883x) if (!wsa883x)
return -EINVAL; return -EINVAL;
@@ -1205,6 +1236,10 @@ static int wsa883x_codec_probe(struct snd_soc_component *component)
wsa883x_codec_init(component); wsa883x_codec_init(component);
wsa883x->global_pa_cnt = 0; wsa883x->global_pa_cnt = 0;
snd_soc_dapm_ignore_suspend(dapm,
wsa883x->dai_driver->playback.stream_name);
snd_soc_dapm_sync(dapm);
return 0; return 0;
} }
@@ -1220,6 +1255,28 @@ static void wsa883x_codec_remove(struct snd_soc_component *component)
return; return;
} }
static int wsa883x_soc_codec_suspend(struct snd_soc_component *component)
{
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
if (!wsa883x)
return 0;
wsa883x->dapm_bias_off = true;
return 0;
}
static int wsa883x_soc_codec_resume(struct snd_soc_component *component)
{
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
if (!wsa883x)
return 0;
wsa883x->dapm_bias_off = false;
return 0;
}
static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = { static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = {
.name = "", .name = "",
.probe = wsa883x_codec_probe, .probe = wsa883x_codec_probe,
@@ -1230,6 +1287,8 @@ static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = {
.num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets),
.dapm_routes = wsa883x_audio_map, .dapm_routes = wsa883x_audio_map,
.num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map), .num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map),
.suspend = wsa883x_soc_codec_suspend,
.resume = wsa883x_soc_codec_resume,
}; };
static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable) static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable)
@@ -1454,12 +1513,18 @@ static int wsa883x_swr_probe(struct swr_device *pdev)
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR,
"WSA SAF2WAR", wsa883x_saf2war_handle_irq, NULL); "WSA SAF2WAR", wsa883x_saf2war_handle_irq, NULL);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR);
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF,
"WSA WAR2SAF", wsa883x_war2saf_handle_irq, NULL); "WSA WAR2SAF", wsa883x_war2saf_handle_irq, NULL);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF);
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE,
"WSA OTP", wsa883x_otp_handle_irq, NULL); "WSA OTP", wsa883x_otp_handle_irq, NULL);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE);
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP,
"WSA OCP", wsa883x_ocp_handle_irq, NULL); "WSA OCP", wsa883x_ocp_handle_irq, NULL);
@@ -1483,10 +1548,14 @@ static int wsa883x_swr_probe(struct swr_device *pdev)
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN,
"WSA EXT INT", wsa883x_ext_int_handle_irq, NULL); "WSA EXT INT", wsa883x_ext_int_handle_irq, NULL);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN);
/* Under Voltage Lock out (UVLO) interrupt handle */ /* Under Voltage Lock out (UVLO) interrupt handle */
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO,
"WSA UVLO", wsa883x_uvlo_handle_irq, NULL); "WSA UVLO", wsa883x_uvlo_handle_irq, NULL);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO);
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR,
"WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL); "WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL);
@@ -1692,7 +1761,20 @@ static int wsa883x_swr_remove(struct swr_device *pdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int wsa883x_swr_suspend(struct device *dev) static int wsa883x_swr_suspend(struct device *dev)
{ {
struct wsa883x_priv *wsa883x = swr_get_dev_data(to_swr_device(dev));
if (!wsa883x) {
dev_err(dev, "%s: wsa883x private data is NULL\n", __func__);
return -EINVAL;
}
dev_dbg(dev, "%s: system suspend\n", __func__); dev_dbg(dev, "%s: system suspend\n", __func__);
if (wsa883x->dapm_bias_off) {
msm_cdc_set_supplies_lpm_mode(dev, wsa883x->supplies,
wsa883x->regulator,
wsa883x->num_supplies,
true);
set_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask);
}
return 0; return 0;
} }
@@ -1704,13 +1786,21 @@ static int wsa883x_swr_resume(struct device *dev)
dev_err(dev, "%s: wsa883x private data is NULL\n", __func__); dev_err(dev, "%s: wsa883x private data is NULL\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (test_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask)) {
msm_cdc_set_supplies_lpm_mode(dev, wsa883x->supplies,
wsa883x->regulator,
wsa883x->num_supplies,
false);
clear_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask);
}
dev_dbg(dev, "%s: system resume\n", __func__); dev_dbg(dev, "%s: system resume\n", __func__);
return 0; return 0;
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops wsa883x_swr_pm_ops = { static const struct dev_pm_ops wsa883x_swr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(wsa883x_swr_suspend, wsa883x_swr_resume) .suspend_late = wsa883x_swr_suspend,
.resume_early = wsa883x_swr_resume,
}; };
static const struct swr_device_id wsa883x_swr_id[] = { static const struct swr_device_id wsa883x_swr_id[] = {

View File

@@ -47,9 +47,11 @@
#define DEV_NAME_STR_LEN 32 #define DEV_NAME_STR_LEN 32
#define WCD_MBHC_HS_V_MAX 1600 #define WCD_MBHC_HS_V_MAX 1600
#define WSA8810_NAME_1 "wsa881x.20170211" #define WSA8810_NAME_1 "wsa881x.1020170211"
#define WSA8810_NAME_2 "wsa881x.20170212" #define WSA8810_NAME_2 "wsa881x.1020170212"
#define WSA8815_NAME_1 "wsa881x.1021170213"
#define WSA8815_NAME_2 "wsa881x.1021170214"
#define WCN_CDC_SLIM_RX_CH_MAX 2 #define WCN_CDC_SLIM_RX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX 2

View File

@@ -384,9 +384,6 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
{ {
.name = LPASS_BE_RT_PROXY_PCM_TX, .name = LPASS_BE_RT_PROXY_PCM_TX,
.stream_name = LPASS_BE_RT_PROXY_PCM_TX, .stream_name = LPASS_BE_RT_PROXY_PCM_TX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -398,9 +395,6 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
{ {
.name = LPASS_BE_RT_PROXY_PCM_RX, .name = LPASS_BE_RT_PROXY_PCM_RX,
.stream_name = LPASS_BE_RT_PROXY_PCM_RX, .stream_name = LPASS_BE_RT_PROXY_PCM_RX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -412,9 +406,6 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
{ {
.name = LPASS_BE_USB_AUDIO_RX, .name = LPASS_BE_USB_AUDIO_RX,
.stream_name = LPASS_BE_USB_AUDIO_RX, .stream_name = LPASS_BE_USB_AUDIO_RX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -426,9 +417,6 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
{ {
.name = LPASS_BE_USB_AUDIO_TX, .name = LPASS_BE_USB_AUDIO_TX,
.stream_name = LPASS_BE_USB_AUDIO_TX, .stream_name = LPASS_BE_USB_AUDIO_TX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -442,9 +430,6 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{ {
.name = LPASS_BE_SLIMBUS_7_RX, .name = LPASS_BE_SLIMBUS_7_RX,
.stream_name = LPASS_BE_SLIMBUS_7_RX, .stream_name = LPASS_BE_SLIMBUS_7_RX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -458,9 +443,6 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{ {
.name = LPASS_BE_SLIMBUS_7_TX, .name = LPASS_BE_SLIMBUS_7_TX,
.stream_name = LPASS_BE_SLIMBUS_7_TX, .stream_name = LPASS_BE_SLIMBUS_7_TX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -476,9 +458,6 @@ static struct snd_soc_dai_link ext_disp_be_dai_link[] = {
{ {
.name = LPASS_BE_DISPLAY_PORT_RX, .name = LPASS_BE_DISPLAY_PORT_RX,
.stream_name = LPASS_BE_DISPLAY_PORT_RX, .stream_name = LPASS_BE_DISPLAY_PORT_RX,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -486,22 +465,6 @@ static struct snd_soc_dai_link ext_disp_be_dai_link[] = {
.ignore_suspend = 1, .ignore_suspend = 1,
SND_SOC_DAILINK_REG(display_port), SND_SOC_DAILINK_REG(display_port),
}, },
#if 0
/* DISP PORT 1 BACK END DAI Link */
{
.name = LPASS_BE_DISPLAY_PORT1,
.stream_name = LPASS_BE_DISPLAY_PORT1,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(display_port1),
},
#endif
}; };
#endif #endif
@@ -510,9 +473,6 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_WSA_CDC_DMA_RX_0, .name = LPASS_BE_WSA_CDC_DMA_RX_0,
.stream_name = LPASS_BE_WSA_CDC_DMA_RX_0, .stream_name = LPASS_BE_WSA_CDC_DMA_RX_0,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -525,9 +485,6 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_WSA_CDC_DMA_RX_1, .name = LPASS_BE_WSA_CDC_DMA_RX_1,
.stream_name = LPASS_BE_WSA_CDC_DMA_RX_1, .stream_name = LPASS_BE_WSA_CDC_DMA_RX_1,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -539,9 +496,6 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_WSA_CDC_DMA_TX_1, .name = LPASS_BE_WSA_CDC_DMA_TX_1,
.stream_name = LPASS_BE_WSA_CDC_DMA_TX_1, .stream_name = LPASS_BE_WSA_CDC_DMA_TX_1,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -556,9 +510,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_RX_CDC_DMA_RX_0, .name = LPASS_BE_RX_CDC_DMA_RX_0,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_0, .stream_name = LPASS_BE_RX_CDC_DMA_RX_0,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -571,9 +522,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_RX_CDC_DMA_RX_1, .name = LPASS_BE_RX_CDC_DMA_RX_1,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_1, .stream_name = LPASS_BE_RX_CDC_DMA_RX_1,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -581,13 +529,11 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
.ignore_suspend = 1, .ignore_suspend = 1,
.ops = &msm_common_be_ops, .ops = &msm_common_be_ops,
SND_SOC_DAILINK_REG(rx_dma_rx1), SND_SOC_DAILINK_REG(rx_dma_rx1),
.init = &msm_int_audrx_init,
}, },
{ {
.name = LPASS_BE_RX_CDC_DMA_RX_2, .name = LPASS_BE_RX_CDC_DMA_RX_2,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_2, .stream_name = LPASS_BE_RX_CDC_DMA_RX_2,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -599,9 +545,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_RX_CDC_DMA_RX_3, .name = LPASS_BE_RX_CDC_DMA_RX_3,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_3, .stream_name = LPASS_BE_RX_CDC_DMA_RX_3,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -610,12 +553,20 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
.ops = &msm_common_be_ops, .ops = &msm_common_be_ops,
SND_SOC_DAILINK_REG(rx_dma_rx3), SND_SOC_DAILINK_REG(rx_dma_rx3),
}, },
{
.name = LPASS_BE_RX_CDC_DMA_RX_5,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_5,
.playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
.ops = &msm_common_be_ops,
SND_SOC_DAILINK_REG(rx_dma_rx5),
},
{ {
.name = LPASS_BE_RX_CDC_DMA_RX_6, .name = LPASS_BE_RX_CDC_DMA_RX_6,
.stream_name = LPASS_BE_RX_CDC_DMA_RX_6, .stream_name = LPASS_BE_RX_CDC_DMA_RX_6,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.playback_only = 1, .playback_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -628,9 +579,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_TX_CDC_DMA_TX_3, .name = LPASS_BE_TX_CDC_DMA_TX_3,
.stream_name = LPASS_BE_TX_CDC_DMA_TX_3, .stream_name = LPASS_BE_TX_CDC_DMA_TX_3,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -641,9 +589,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_TX_CDC_DMA_TX_4, .name = LPASS_BE_TX_CDC_DMA_TX_4,
.stream_name = LPASS_BE_TX_CDC_DMA_TX_4, .stream_name = LPASS_BE_TX_CDC_DMA_TX_4,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -657,9 +602,6 @@ static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_VA_CDC_DMA_TX_0, .name = LPASS_BE_VA_CDC_DMA_TX_0,
.stream_name = LPASS_BE_VA_CDC_DMA_TX_0, .stream_name = LPASS_BE_VA_CDC_DMA_TX_0,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -670,9 +612,6 @@ static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_VA_CDC_DMA_TX_1, .name = LPASS_BE_VA_CDC_DMA_TX_1,
.stream_name = LPASS_BE_VA_CDC_DMA_TX_1, .stream_name = LPASS_BE_VA_CDC_DMA_TX_1,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -683,9 +622,6 @@ static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
{ {
.name = LPASS_BE_VA_CDC_DMA_TX_2, .name = LPASS_BE_VA_CDC_DMA_TX_2,
.stream_name = LPASS_BE_VA_CDC_DMA_TX_2, .stream_name = LPASS_BE_VA_CDC_DMA_TX_2,
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
#endif /* CONFIG_AUDIO_QGKI */
.capture_only = 1, .capture_only = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, .trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST}, SND_SOC_DPCM_TRIGGER_POST},
@@ -855,6 +791,45 @@ static const struct of_device_id lahaina_asoc_machine_of_match[] = {
{}, {},
}; };
static int msm_snd_card_late_probe(struct snd_soc_card *card)
{
struct snd_soc_component *component = NULL;
const char *be_dl_name = LPASS_BE_RX_CDC_DMA_RX_0;
struct snd_soc_pcm_runtime *rtd;
int ret = 0;
void *mbhc_calibration;
rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
if (!rtd) {
dev_err(card->dev,
"%s: snd_soc_get_pcm_runtime for %s failed!\n",
__func__, be_dl_name);
return -EINVAL;
}
component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME);
if (!component) {
pr_err("%s component is NULL\n", __func__);
return -EINVAL;
}
mbhc_calibration = def_wcd_mbhc_cal();
if (!mbhc_calibration)
return -ENOMEM;
wcd_mbhc_cfg.calibration = mbhc_calibration;
ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
if (ret) {
dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
__func__, ret);
goto err_hs_detect;
}
return 0;
err_hs_detect:
kfree(mbhc_calibration);
return ret;
}
static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
{ {
struct snd_soc_card *card = NULL; struct snd_soc_card *card = NULL;
@@ -934,6 +909,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
if (card) { if (card) {
card->dai_link = dailink; card->dai_link = dailink;
card->num_links = total_links; card->num_links = total_links;
card->late_probe = msm_snd_card_late_probe;
} }
return card; return card;
@@ -958,6 +934,10 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_card_get_drvdata(rtd->card); snd_soc_card_get_drvdata(rtd->card);
int ret = 0; int ret = 0;
if (codec_reg_done) {
return 0;
}
if (pdata->wsa_max_devs > 0) { if (pdata->wsa_max_devs > 0) {
component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1"); component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1");
if (!component) { if (!component) {
@@ -1064,8 +1044,6 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_component *component = NULL; struct snd_soc_component *component = NULL;
struct snd_soc_dapm_context *dapm = NULL; struct snd_soc_dapm_context *dapm = NULL;
int ret = 0;
void *mbhc_calibration;
struct snd_info_entry *entry; struct snd_info_entry *entry;
struct snd_card *card = NULL; struct snd_card *card = NULL;
struct msm_asoc_mach_data *pdata; struct msm_asoc_mach_data *pdata;
@@ -1095,8 +1073,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
if (!entry) { if (!entry) {
dev_dbg(component->dev, "%s: Cannot create codecs module entry\n", dev_dbg(component->dev, "%s: Cannot create codecs module entry\n",
__func__); __func__);
ret = 0; return 0;
goto mbhc_cfg_cal;
} }
pdata->codec_root = entry; pdata->codec_root = entry;
} }
@@ -1121,23 +1098,8 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
} }
#endif #endif
mbhc_cfg_cal:
mbhc_calibration = def_wcd_mbhc_cal();
if (!mbhc_calibration)
return -ENOMEM;
wcd_mbhc_cfg.calibration = mbhc_calibration;
ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
if (ret) {
dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
__func__, ret);
goto err_hs_detect;
}
msm_common_dai_link_init(rtd); msm_common_dai_link_init(rtd);
return 0; return 0;
err_hs_detect:
kfree(mbhc_calibration);
return ret;
} }
static int lahaina_ssr_enable(struct device *dev, void *data) static int lahaina_ssr_enable(struct device *dev, void *data)

View File

@@ -0,0 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
int msm_compr_new(struct snd_soc_pcm_runtime *rtd, int num);

View File

@@ -5,7 +5,6 @@
#include <sound/soc.h> #include <sound/soc.h>
SND_SOC_DAILINK_DEFS(usb_audio_rx, SND_SOC_DAILINK_DEFS(usb_audio_rx,
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_DUMMY()),
@@ -16,7 +15,6 @@ SND_SOC_DAILINK_DEFS(usb_audio_tx,
DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy"))); DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
SND_SOC_DAILINK_DEFS(slimbus_7_rx, SND_SOC_DAILINK_DEFS(slimbus_7_rx,
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave", DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave",
@@ -96,6 +94,12 @@ SND_SOC_DAILINK_DEFS(rx_dma_rx3,
COMP_CODEC("wcd938x_codec", "wcd938x_cdc")), COMP_CODEC("wcd938x_codec", "wcd938x_cdc")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy"))); DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
SND_SOC_DAILINK_DEFS(rx_dma_rx5,
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx5"),
COMP_CODEC("wcd938x_codec", "wcd938x_cdc")),
DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
SND_SOC_DAILINK_DEFS(rx_dma_rx6, SND_SOC_DAILINK_DEFS(rx_dma_rx6,
DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx6"), DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx6"),

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
@@ -148,6 +148,11 @@ enum {
SPDIF_TX_MAX, SPDIF_TX_MAX,
}; };
enum {
HDMI_RX_IDX = 0,
EXT_HDMI_RX_IDX_MAX,
};
struct mi2s_conf { struct mi2s_conf {
struct mutex lock; struct mutex lock;
u32 ref_cnt; u32 ref_cnt;
@@ -344,7 +349,9 @@ static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
} }
}; };
static struct dev_config ext_hdmi_rx_cfg[] = {
[HDMI_RX_IDX] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
};
/* Default configuration of slimbus channels */ /* Default configuration of slimbus channels */
static struct dev_config slim_rx_cfg[] = { static struct dev_config slim_rx_cfg[] = {
@@ -488,6 +495,12 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
"KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_32", "KHZ_44P1", "KHZ_48",
"KHZ_88P2", "KHZ_96", "KHZ_176P4", "KHZ_88P2", "KHZ_96", "KHZ_176P4",
"KHZ_192", "KHZ_352P8", "KHZ_384"}; "KHZ_192", "KHZ_352P8", "KHZ_384"};
static char const *ext_hdmi_sample_rate_text[] = {"KHZ_48", "KHZ_96",
"KHZ_192", "KHZ_32", "KHZ_44P1",
"KHZ_88P2", "KHZ_176P4"};
static char const *ext_hdmi_bit_format_text[] = {"S16_LE", "S24_LE",
"S24_3LE"};
static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four", static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight"}; "Five", "Six", "Seven", "Eight"};
static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"}; static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
@@ -539,6 +552,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_chs, ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text);
@@ -546,6 +560,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_format, ext_hdmi_bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
@@ -553,6 +568,8 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_sink, bt_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_sink, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_sample_rate,
ext_hdmi_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text);
@@ -2110,6 +2127,191 @@ static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol,
return rc; return rc;
} }
static int ext_hdmi_get_port_idx(struct snd_kcontrol *kcontrol)
{
int idx;
if (strnstr(kcontrol->id.name, "HDMI_RX",
sizeof("HDMI_RX"))) {
idx = HDMI_RX_IDX;
} else {
pr_err("%s: unsupported BE: %s",
__func__, kcontrol->id.name);
idx = -EINVAL;
}
return idx;
}
static int ext_hdmi_rx_format_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
switch (ext_hdmi_rx_cfg[idx].bit_format) {
case SNDRV_PCM_FORMAT_S24_LE:
ucontrol->value.integer.value[0] = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
default:
ucontrol->value.integer.value[0] = 0;
break;
}
pr_debug("%s: ext_hdmi_rx[%d].format = %d, ucontrol value = %ld\n",
__func__, idx, ext_hdmi_rx_cfg[idx].bit_format,
ucontrol->value.integer.value[0]);
return 0;
}
static int ext_hdmi_rx_format_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
switch (ucontrol->value.integer.value[0]) {
case 1:
ext_hdmi_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE;
break;
case 0:
default:
ext_hdmi_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S16_LE;
break;
}
pr_debug("%s: ext_hdmi_rx[%d].format = %d, ucontrol value = %ld\n",
__func__, idx, ext_hdmi_rx_cfg[idx].bit_format,
ucontrol->value.integer.value[0]);
return 0;
}
static int ext_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
ucontrol->value.integer.value[0] =
ext_hdmi_rx_cfg[idx].channels - 2;
pr_debug("%s: ext_hdmi_rx[%d].ch = %d\n", __func__,
idx, ext_hdmi_rx_cfg[idx].channels);
return 0;
}
static int ext_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
ext_hdmi_rx_cfg[idx].channels =
ucontrol->value.integer.value[0] + 2;
pr_debug("%s: ext_hdmi_rx[%d].ch = %d\n", __func__,
idx, ext_hdmi_rx_cfg[idx].channels);
return 0;
}
static int ext_hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int sample_rate_val;
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
switch (ext_hdmi_rx_cfg[idx].sample_rate) {
case SAMPLING_RATE_176P4KHZ:
sample_rate_val = 6;
break;
case SAMPLING_RATE_88P2KHZ:
sample_rate_val = 5;
break;
case SAMPLING_RATE_44P1KHZ:
sample_rate_val = 4;
break;
case SAMPLING_RATE_32KHZ:
sample_rate_val = 3;
break;
case SAMPLING_RATE_192KHZ:
sample_rate_val = 2;
break;
case SAMPLING_RATE_96KHZ:
sample_rate_val = 1;
break;
case SAMPLING_RATE_48KHZ:
default:
sample_rate_val = 0;
break;
}
ucontrol->value.integer.value[0] = sample_rate_val;
pr_debug("%s: ext_hdmi_rx[%d].sample_rate = %d\n", __func__,
idx, ext_hdmi_rx_cfg[idx].sample_rate);
return 0;
}
static int ext_hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int idx = ext_hdmi_get_port_idx(kcontrol);
if (idx < 0)
return idx;
switch (ucontrol->value.integer.value[0]) {
case 6:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_176P4KHZ;
break;
case 5:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_88P2KHZ;
break;
case 4:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_44P1KHZ;
break;
case 3:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_32KHZ;
break;
case 2:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ;
break;
case 1:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_96KHZ;
break;
case 0:
default:
ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_48KHZ;
break;
}
pr_debug("%s: control value = %ld, ext_hdmi_rx[%d].sample_rate = %d\n",
__func__, ucontrol->value.integer.value[0], idx,
ext_hdmi_rx_cfg[idx].sample_rate);
return 0;
}
static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol, static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
@@ -3842,6 +4044,14 @@ static const struct snd_kcontrol_new msm_snd_sb_controls[] = {
slim_rx_bit_format_get, slim_rx_bit_format_put), slim_rx_bit_format_get, slim_rx_bit_format_put),
SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format, SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format,
slim_tx_bit_format_get, slim_tx_bit_format_put), slim_tx_bit_format_get, slim_tx_bit_format_put),
SOC_ENUM_EXT("HDMI_RX Bit Format", ext_hdmi_rx_format,
ext_hdmi_rx_format_get, ext_hdmi_rx_format_put),
SOC_ENUM_EXT("HDMI_RX SampleRate", ext_hdmi_rx_sample_rate,
ext_hdmi_rx_sample_rate_get,
ext_hdmi_rx_sample_rate_put),
SOC_ENUM_EXT("HDMI_RX Channels", ext_hdmi_rx_chs,
ext_hdmi_rx_ch_get,
ext_hdmi_rx_ch_put),
SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate, SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate,
slim_rx_sample_rate_get, slim_rx_sample_rate_put), slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate, SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate,
@@ -4506,6 +4716,23 @@ static int msm_slim_get_ch_from_beid(int32_t be_id)
return ch_id; return ch_id;
} }
static int msm_ext_hdmi_get_idx_from_beid(int32_t be_id)
{
int idx;
switch (be_id) {
case MSM_BACKEND_DAI_HDMI_RX_MS:
idx = HDMI_RX_IDX;
break;
default:
pr_err("%s: Incorrect ext_hdmi BE id %d\n", __func__, be_id);
idx = -EINVAL;
break;
}
return idx;
}
static int msm_cdc_dma_get_idx_from_beid(int32_t be_id) static int msm_cdc_dma_get_idx_from_beid(int32_t be_id)
{ {
int idx = 0; int idx = 0;
@@ -5040,11 +5267,27 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
channels->min = channels->max = afe_lb_tx_cfg.channels; channels->min = channels->max = afe_lb_tx_cfg.channels;
break; break;
case MSM_BACKEND_DAI_HDMI_RX_MS:
idx = msm_ext_hdmi_get_idx_from_beid(dai_link->id);
if (idx < 0) {
pr_err("%s: Incorrect ext hdmi idx %d\n",
__func__, idx);
rc = idx;
goto done;
}
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
ext_hdmi_rx_cfg[idx].bit_format);
rate->min = rate->max = ext_hdmi_rx_cfg[idx].sample_rate;
channels->min = channels->max = ext_hdmi_rx_cfg[idx].channels;
break;
default: default:
rate->min = rate->max = SAMPLING_RATE_48KHZ; rate->min = rate->max = SAMPLING_RATE_48KHZ;
break; break;
} }
done:
return rc; return rc;
} }
@@ -6104,7 +6347,6 @@ static struct snd_soc_ops msm_fe_qos_ops = {
.prepare = msm_fe_qos_prepare, .prepare = msm_fe_qos_prepare,
}; };
static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
{ {
int ret = 0; int ret = 0;
@@ -6177,6 +6419,36 @@ err:
return ret; return ret;
} }
static int msm_mi2s_snd_hw_free(struct snd_pcm_substream *substream)
{
int i, data_format = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int index = rtd->cpu_dai->id;
struct snd_soc_card *card = rtd->card;
struct snd_soc_component *component;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
data_format = mi2s_rx_cfg[index].data_format;
else
data_format = mi2s_tx_cfg[index].data_format;
pr_debug("%s(): substream = %s stream = %d\n", __func__,
substream->name, substream->stream);
/* Call csra mute function if data format is DSD, else return */
if (data_format != AFE_DSD_DATA)
return 0;
for (i = 0; i < card->num_aux_devs; i++) {
component =
soc_find_component(card->aux_dev[i].codec_of_node,
NULL);
csra66x0_hw_free_mute(component);
}
return 0;
}
static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
{ {
int ret; int ret;
@@ -6279,6 +6551,7 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream)
unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
u16 port_id = 0;
dev_dbg(rtd->card->dev, dev_dbg(rtd->card->dev,
"%s: substream = %s stream = %d, dai name %s, dai ID %d\n", "%s: substream = %s stream = %d, dai name %s, dai ID %d\n",
@@ -6312,6 +6585,13 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream)
meta_mi2s_intf_conf[index].clk_enable[i] = true; meta_mi2s_intf_conf[index].clk_enable[i] = true;
if (i == 0) { if (i == 0) {
port_id = msm_get_port_id(rtd->dai_link->id);
ret = afe_set_clk_id(port_id,
mi2s_clk[member_port].clk_id);
if (ret < 0)
pr_err("%s: afe_set_clk_id fail %d\n",
__func__, ret);
ret = snd_soc_dai_set_fmt(cpu_dai, fmt); ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret < 0) { if (ret < 0) {
pr_err("%s: set fmt cpu dai failed for META_MI2S (%d), err:%d\n", pr_err("%s: set fmt cpu dai failed for META_MI2S (%d), err:%d\n",
@@ -6504,6 +6784,7 @@ static void msm_spdif_snd_shutdown(struct snd_pcm_substream *substream)
static struct snd_soc_ops msm_mi2s_be_ops = { static struct snd_soc_ops msm_mi2s_be_ops = {
.startup = msm_mi2s_snd_startup, .startup = msm_mi2s_snd_startup,
.hw_free = msm_mi2s_snd_hw_free,
.shutdown = msm_mi2s_snd_shutdown, .shutdown = msm_mi2s_snd_shutdown,
}; };
@@ -7298,6 +7579,24 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
}, },
}; };
static struct snd_soc_dai_link ext_hdmi_be_dai_link[] = {
/* HDMI RX BACK END DAI Link */
{
.name = LPASS_BE_HDMI_MS,
.stream_name = "HDMI MS Playback",
.cpu_dai_name = "msm-dai-q6-hdmi.24578",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-ext-disp-audio-codec-rx",
.codec_dai_name = "msm_hdmi_ms_audio_codec_rx_dai",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_HDMI_RX_MS,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_common_be_dai_links[] = { static struct snd_soc_dai_link msm_common_be_dai_links[] = {
/* Backend AFE DAI Links */ /* Backend AFE DAI Links */
{ {
@@ -8305,7 +8604,8 @@ static struct snd_soc_dai_link msm_qcs405_dai_links[
ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links) + ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links) +
ARRAY_SIZE(msm_bolero_fe_dai_links) + ARRAY_SIZE(msm_bolero_fe_dai_links) +
ARRAY_SIZE(msm_spdif_be_dai_links) + ARRAY_SIZE(msm_spdif_be_dai_links) +
ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link)]; ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
ARRAY_SIZE(ext_hdmi_be_dai_link)];
static int msm_snd_card_tasha_late_probe(struct snd_soc_card *card) static int msm_snd_card_tasha_late_probe(struct snd_soc_card *card)
{ {
@@ -8556,6 +8856,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
uint32_t va_bolero_codec = 0, wsa_bolero_codec = 0, mi2s_audio_intf = 0; uint32_t va_bolero_codec = 0, wsa_bolero_codec = 0, mi2s_audio_intf = 0;
uint32_t spdif_audio_intf = 0, wcn_audio_intf = 0; uint32_t spdif_audio_intf = 0, wcn_audio_intf = 0;
uint32_t afe_loopback_intf = 0, meta_mi2s_intf = 0; uint32_t afe_loopback_intf = 0, meta_mi2s_intf = 0;
uint32_t ext_disp_hdmi_rx = 0;
const struct of_device_id *match; const struct of_device_id *match;
char __iomem *spdif_cfg, *spdif_pin_ctl; char __iomem *spdif_cfg, *spdif_pin_ctl;
int rc = 0; int rc = 0;
@@ -8743,6 +9044,20 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link); ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
} }
} }
rc = of_property_read_u32(dev->of_node,
"qcom,ext-disp-audio-rx", &ext_disp_hdmi_rx);
if (rc) {
dev_dbg(dev, "%s: No DT match ext disp hdmi rx\n",
__func__);
} else {
if (ext_disp_hdmi_rx) {
memcpy(msm_qcs405_dai_links + total_links,
ext_hdmi_be_dai_link,
sizeof(ext_hdmi_be_dai_link));
total_links += ARRAY_SIZE(ext_hdmi_be_dai_link);
}
}
dailink = msm_qcs405_dai_links; dailink = msm_qcs405_dai_links;
} else if (!strcmp(match->data, "stub_codec")) { } else if (!strcmp(match->data, "stub_codec")) {
card = &snd_soc_card_stub_msm; card = &snd_soc_card_stub_msm;
@@ -8756,7 +9071,6 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
msm_stub_be_dai_links, msm_stub_be_dai_links,
sizeof(msm_stub_be_dai_links)); sizeof(msm_stub_be_dai_links));
total_links += ARRAY_SIZE(msm_stub_be_dai_links); total_links += ARRAY_SIZE(msm_stub_be_dai_links);
dailink = msm_stub_dai_links; dailink = msm_stub_dai_links;
} }

View File

@@ -157,6 +157,10 @@ ifdef CONFIG_DIGITAL_CDC_RSC_MGR
SPF_CORE_OBJS += digital-cdc-rsc-mgr.o SPF_CORE_OBJS += digital-cdc-rsc-mgr.o
endif endif
ifdef CONFIG_DIGITAL_CDC_RSC_MGR
Q6_OBJS += digital-cdc-rsc-mgr.o
endif
LINUX_INC += -Iinclude/linux LINUX_INC += -Iinclude/linux
INCS += $(COMMON_INC) \ INCS += $(COMMON_INC) \

View File

@@ -28,6 +28,7 @@ enum apr_subsys_state {
APR_SUBSYS_DOWN, APR_SUBSYS_DOWN,
APR_SUBSYS_UP, APR_SUBSYS_UP,
APR_SUBSYS_LOADED, APR_SUBSYS_LOADED,
APR_SUBSYS_UNKNOWN,
}; };
static ssize_t adsp_boot_store(struct kobject *kobj, static ssize_t adsp_boot_store(struct kobject *kobj,
@@ -61,6 +62,53 @@ static struct work_struct adsp_ldr_work;
static struct platform_device *adsp_private; static struct platform_device *adsp_private;
static void adsp_loader_unload(struct platform_device *pdev); static void adsp_loader_unload(struct platform_device *pdev);
static int adsp_restart_subsys(void)
{
struct subsys_device *adsp_dev = NULL;
struct platform_device *pdev = adsp_private;
struct adsp_loader_private *priv = NULL;
int rc = -EINVAL;
priv = platform_get_drvdata(pdev);
if (!priv)
return rc;
adsp_dev = (struct subsys_device *)priv->pil_h;
if (!adsp_dev)
return rc;
/* subsystem_restart_dev has worker queue to handle */
rc = subsystem_restart_dev(adsp_dev);
if (rc) {
dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
return rc;
}
pr_debug("%s :: Restart Success %d\n", __func__, rc);
return rc;
}
#if 0
static void adsp_load_state_notify_cb(enum apr_subsys_state state,
void *phandle)
{
struct platform_device *pdev = adsp_private;
struct adsp_loader_private *priv = NULL;
priv = platform_get_drvdata(pdev);
if (!priv)
return;
if (phandle != adsp_private) {
pr_err("%s:callback is not for adsp-loader client\n", __func__);
return;
}
pr_debug("%s:: Received cb for ADSP restart\n", __func__);
if (state == APR_SUBSYS_UNKNOWN)
adsp_restart_subsys();
else
pr_debug("%s:Ignore restart request for ADSP", __func__);
}
#endif
static void adsp_load_fw(struct work_struct *adsp_ldr_work) static void adsp_load_fw(struct work_struct *adsp_ldr_work)
{ {
struct platform_device *pdev = adsp_private; struct platform_device *pdev = adsp_private;
@@ -69,6 +117,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work)
int rc = 0; int rc = 0;
u32 adsp_state; u32 adsp_state;
const char *img_name; const char *img_name;
// void *padsp_restart_cb = &adsp_load_state_notify_cb;
if (!pdev) { if (!pdev) {
dev_err(&pdev->dev, "%s: Platform device null\n", __func__); dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
@@ -125,7 +174,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work)
} }
dev_dbg(&pdev->dev, "%s: Q6/MDSP image is loaded\n", __func__); dev_dbg(&pdev->dev, "%s: Q6/MDSP image is loaded\n", __func__);
return; goto success;
} }
load_adsp: load_adsp:
@@ -159,10 +208,13 @@ load_adsp:
} }
dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__); dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
return; // apr_register_adsp_state_cb(padsp_restart_cb, adsp_private);
goto success;
} }
fail: fail:
dev_err(&pdev->dev, "%s: Q6 image loading failed\n", __func__); dev_err(&pdev->dev, "%s: Q6 image loading failed\n", __func__);
success:
return;
} }
static void adsp_loader_do(struct platform_device *pdev) static void adsp_loader_do(struct platform_device *pdev)
@@ -176,37 +228,24 @@ static ssize_t adsp_ssr_store(struct kobject *kobj,
size_t count) size_t count)
{ {
int ssr_command = 0; int ssr_command = 0;
struct subsys_device *adsp_dev = NULL;
struct platform_device *pdev = adsp_private; struct platform_device *pdev = adsp_private;
struct adsp_loader_private *priv = NULL; struct adsp_loader_private *priv = NULL;
int rc; int rc = -EINVAL;
dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__); dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__);
priv = platform_get_drvdata(pdev);
if (!priv)
return rc;
if (kstrtoint(buf, 10, &ssr_command) < 0) if (kstrtoint(buf, 10, &ssr_command) < 0)
return -EINVAL; return -EINVAL;
if (ssr_command != SSR_RESET_CMD) if (ssr_command != SSR_RESET_CMD)
return -EINVAL; return -EINVAL;
priv = platform_get_drvdata(pdev); adsp_restart_subsys();
if (!priv) dev_dbg(&pdev->dev, "%s :: ADSP restarted\n", __func__);
return -EINVAL;
adsp_dev = (struct subsys_device *)priv->pil_h;
if (!adsp_dev)
return -EINVAL;
dev_err(&pdev->dev, "requesting for ADSP restart\n");
/* subsystem_restart_dev has worker queue to handle */
rc = subsystem_restart_dev(adsp_dev);
if (rc) {
dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
return rc;
}
dev_dbg(&pdev->dev, "ADSP restarted\n");
return count; return count;
} }
@@ -339,6 +378,8 @@ static int adsp_loader_probe(struct platform_device *pdev)
int fw_name_size; int fw_name_size;
u32 adsp_var_idx = 0; u32 adsp_var_idx = 0;
int ret = 0; int ret = 0;
u32 adsp_fuse_not_supported = 0;
const char *adsp_fw_name;
ret = adsp_loader_init_sysfs(pdev); ret = adsp_loader_init_sysfs(pdev);
if (ret != 0) { if (ret != 0) {
@@ -350,15 +391,58 @@ static int adsp_loader_probe(struct platform_device *pdev)
/* get adsp variant idx */ /* get adsp variant idx */
cell = nvmem_cell_get(&pdev->dev, "adsp_variant"); cell = nvmem_cell_get(&pdev->dev, "adsp_variant");
if (IS_ERR_OR_NULL(cell)) { if (IS_ERR_OR_NULL(cell)) {
dev_dbg(&pdev->dev, "%s: FAILED to get nvmem cell \n", __func__); dev_dbg(&pdev->dev, "%s: FAILED to get nvmem cell \n",
__func__);
/*
* When ADSP variant read from fuse register is not
* supported, check if image with different fw image
* name needs to be loaded
*/
ret = of_property_read_u32(pdev->dev.of_node,
"adsp-fuse-not-supported",
&adsp_fuse_not_supported);
if (ret) {
dev_dbg(&pdev->dev,
"%s: adsp_fuse_not_supported prop not found",
__func__, ret);
goto wqueue;
}
if (adsp_fuse_not_supported) {
/* Read ADSP firmware image name */
ret = of_property_read_string(pdev->dev.of_node,
"adsp-fw-name",
&adsp_fw_name);
if (ret < 0) {
dev_dbg(&pdev->dev, "%s: unable to read fw-name\n",
__func__);
goto wqueue;
}
fw_name_size = strlen(adsp_fw_name) + 1;
priv->adsp_fw_name = devm_kzalloc(&pdev->dev,
fw_name_size,
GFP_KERNEL);
if (!priv->adsp_fw_name)
goto wqueue;
strlcpy(priv->adsp_fw_name, adsp_fw_name,
fw_name_size);
}
goto wqueue; goto wqueue;
} }
buf = nvmem_cell_read(cell, &len); buf = nvmem_cell_read(cell, &len);
nvmem_cell_put(cell); nvmem_cell_put(cell);
if (IS_ERR_OR_NULL(buf) || len <= 0 || len > sizeof(u32)) { if (IS_ERR_OR_NULL(buf)) {
dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__); dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__);
goto wqueue; goto wqueue;
} }
if (len <= 0 || len > sizeof(u32)) {
dev_dbg(&pdev->dev, "%s: nvmem cell length out of range: %d\n",
__func__, len);
kfree(buf);
goto wqueue;
}
memcpy(&adsp_var_idx, buf, len); memcpy(&adsp_var_idx, buf, len);
kfree(buf); kfree(buf);

View File

@@ -606,6 +606,7 @@ static int __init audio_notifier_late_init(void)
return 0; return 0;
} }
#ifdef CONFIG_MSM_QDSP6_PDR
static int __init audio_notifier_init(void) static int __init audio_notifier_init(void)
{ {
int ret; int ret;
@@ -624,6 +625,17 @@ static int __init audio_notifier_init(void)
return 0; return 0;
} }
#else
static int __init audio_notifier_init(void)
{
audio_notifier_subsys_init();
audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
audio_notifier_late_init();
return 0;
}
#endif
module_init(audio_notifier_init); module_init(audio_notifier_init);
static void __exit audio_notifier_exit(void) static void __exit audio_notifier_exit(void)

View File

@@ -87,13 +87,13 @@ void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
} }
EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset); EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
void digital_cdc_rsc_mgr_init() void digital_cdc_rsc_mgr_init(void)
{ {
mutex_init(&hw_vote_lock); mutex_init(&hw_vote_lock);
is_init_done = true; is_init_done = true;
} }
void digital_cdc_rsc_mgr_exit() void digital_cdc_rsc_mgr_exit(void)
{ {
mutex_destroy(&hw_vote_lock); mutex_destroy(&hw_vote_lock);
is_init_done = false; is_init_done = false;

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef __MFD_CDC_PINCTRL_H_ #ifndef __MFD_CDC_PINCTRL_H_
@@ -11,6 +11,7 @@
#if IS_ENABLED(CONFIG_MSM_CDC_PINCTRL) #if IS_ENABLED(CONFIG_MSM_CDC_PINCTRL)
extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *np); extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *np);
extern int msm_cdc_pinctrl_select_active_state(struct device_node *np); extern int msm_cdc_pinctrl_select_active_state(struct device_node *np);
extern int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np);
extern int msm_cdc_pinctrl_get_state(struct device_node *np); extern int msm_cdc_pinctrl_get_state(struct device_node *np);
extern int msm_cdc_get_gpio_state(struct device_node *np); extern int msm_cdc_get_gpio_state(struct device_node *np);
extern int msm_cdc_pinctrl_set_wakeup_capable(struct device_node *np, extern int msm_cdc_pinctrl_set_wakeup_capable(struct device_node *np,
@@ -27,6 +28,10 @@ int msm_cdc_pinctrl_select_active_state(struct device_node *np)
{ {
return 0; return 0;
} }
int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np)
{
return 0;
}
int msm_cdc_get_gpio_state(struct device_node *np) int msm_cdc_get_gpio_state(struct device_node *np)
{ {
return 0; return 0;

View File

@@ -15,6 +15,7 @@ struct cdc_regulator {
int max_uV; int max_uV;
int optimum_uA; int optimum_uA;
bool ondemand; bool ondemand;
bool lpm_supported;
struct regulator *regulator; struct regulator *regulator;
}; };
@@ -51,6 +52,11 @@ extern int msm_cdc_enable_static_supplies(struct device *dev,
struct regulator_bulk_data *supplies, struct regulator_bulk_data *supplies,
struct cdc_regulator *cdc_vreg, struct cdc_regulator *cdc_vreg,
int num_supplies); int num_supplies);
extern int msm_cdc_set_supplies_lpm_mode(struct device *dev,
struct regulator_bulk_data *supplies,
struct cdc_regulator *cdc_vreg,
int num_supplies,
bool flag);
extern int msm_cdc_init_supplies(struct device *dev, extern int msm_cdc_init_supplies(struct device *dev,
struct regulator_bulk_data **supplies, struct regulator_bulk_data **supplies,
struct cdc_regulator *cdc_vreg, struct cdc_regulator *cdc_vreg,

View File

@@ -145,6 +145,8 @@ do { \
#define FW_READ_ATTEMPTS 15 #define FW_READ_ATTEMPTS 15
#define FW_READ_TIMEOUT 4000000 #define FW_READ_TIMEOUT 4000000
#define FAKE_REM_RETRY_ATTEMPTS 3 #define FAKE_REM_RETRY_ATTEMPTS 3
#define HPHL_CROSS_CONN_THRESHOLD 100
#define HPHR_CROSS_CONN_THRESHOLD 100
#define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50 #define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50
#define ANC_DETECT_RETRY_CNT 7 #define ANC_DETECT_RETRY_CNT 7
@@ -456,6 +458,14 @@ struct wcd_mbhc_register {
}; };
struct wcd_mbhc_cb { struct wcd_mbhc_cb {
void (*update_cross_conn_thr)
(struct wcd_mbhc *mbhc);
void (*mbhc_surge_ctl)
(struct wcd_mbhc *mbhc, bool surge_en);
void (*mbhc_comp_autozero_control)
(struct wcd_mbhc *mbhc, bool az_enable);
void (*get_micbias_val)
(struct wcd_mbhc *mbhc, int *mb);
void (*bcs_enable) void (*bcs_enable)
(struct wcd_mbhc *mbhc, bool bcs_enable); (struct wcd_mbhc *mbhc, bool bcs_enable);
int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on); int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);
@@ -541,6 +551,7 @@ struct wcd_mbhc {
wait_queue_head_t wait_btn_press; wait_queue_head_t wait_btn_press;
bool is_btn_press; bool is_btn_press;
u8 current_plug; u8 current_plug;
u8 plug_before_ssr;
bool in_swch_irq_handler; bool in_swch_irq_handler;
bool hphl_swh; /*track HPHL switch NC / NO */ bool hphl_swh; /*track HPHL switch NC / NO */
bool gnd_swh; /*track GND switch NC / NO */ bool gnd_swh; /*track GND switch NC / NO */
@@ -551,6 +562,8 @@ struct wcd_mbhc {
u32 moist_vref; u32 moist_vref;
u32 moist_iref; u32 moist_iref;
u32 moist_rref; u32 moist_rref;
u32 hphl_cross_conn_thr;
u32 hphr_cross_conn_thr;
u8 micbias1_cap_mode; /* track ext cap setting */ u8 micbias1_cap_mode; /* track ext cap setting */
u8 micbias2_cap_mode; /* track ext cap setting */ u8 micbias2_cap_mode; /* track ext cap setting */
bool hs_detect_work_stop; bool hs_detect_work_stop;

View File

@@ -598,7 +598,7 @@ struct adm_cmd_device_open_v8 {
* In all other use cases this should be set to 0xffff * In all other use cases this should be set to 0xffff
*/ */
u16 reserved; u16 compressed_data_type;
} __packed; } __packed;
/* /*
@@ -1356,6 +1356,7 @@ struct adm_cmd_connect_afe_port_v5 {
#define RT_PROXY_PORT_001_RX 0x2000 #define RT_PROXY_PORT_001_RX 0x2000
#define RT_PROXY_PORT_001_TX 0x2001 #define RT_PROXY_PORT_001_TX 0x2001
#define AFE_LOOPBACK_TX 0x6001 #define AFE_LOOPBACK_TX 0x6001
#define HDMI_RX_MS 0x6002
#define DISPLAY_PORT_RX 0x6020 #define DISPLAY_PORT_RX 0x6020
#define AFE_LANE_MASK_INVALID 0 #define AFE_LANE_MASK_INVALID 0
@@ -1562,6 +1563,8 @@ struct adm_cmd_connect_afe_port_v5 {
#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_RX 0x4012 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_RX 0x4012
/* SLIMbus Tx port on channel 9. */ /* SLIMbus Tx port on channel 9. */
#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_TX 0x4013 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_TX 0x4013
/*AFE Rx port for audio over hdmi*/
#define AFE_PORT_ID_HDMI_MS 0x6002
/* AFE Rx port for audio over Display port */ /* AFE Rx port for audio over Display port */
#define AFE_PORT_ID_HDMI_OVER_DP_RX 0x6020 #define AFE_PORT_ID_HDMI_OVER_DP_RX 0x6020
/*USB AFE port */ /*USB AFE port */
@@ -2554,6 +2557,7 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 {
#define AFE_GENERIC_COMPRESSED 0x8 #define AFE_GENERIC_COMPRESSED 0x8
#define AFE_LINEAR_PCM_DATA_PACKED_16BIT 0X6 #define AFE_LINEAR_PCM_DATA_PACKED_16BIT 0X6
#define AFE_DSD_DOP_W_MARKER_DATA 0x9 #define AFE_DSD_DOP_W_MARKER_DATA 0x9
#define AFE_DSD_DATA 0xA
/* This param id is used to configure I2S interface */ /* This param id is used to configure I2S interface */
#define AFE_PARAM_ID_I2S_CONFIG 0x0001020D #define AFE_PARAM_ID_I2S_CONFIG 0x0001020D
@@ -4139,6 +4143,16 @@ struct afe_id_aptx_adaptive_enc_init
#define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233
#define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9
/* Macros for dynamic loading of modules by AVCS */
#define AVS_MODULE_ID_PACKETIZER_COP 0x0001322A
#define AVS_MODULE_ID_PACKETIZER_COP_V1 0x000132E8
#define AVS_MODULE_ID_DEPACKETIZER_COP 0x00013233
#define AVS_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9
/* /*
* Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module. * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module.
* This parameter cannot be set runtime. * This parameter cannot be set runtime.
@@ -4734,6 +4748,56 @@ struct afe_enc_config {
union afe_enc_config_data data; union afe_enc_config_data data;
}; };
/*
* Enable TTP generator in AFE.
*/
#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE 0x000132EF
/*
* Configure TTP generator params in AFE.
*/
#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG 0x000132F0
#define MAX_TTP_OFFSET_PAIRS 4
struct afe_ttp_gen_enable_t {
uint16_t enable;
uint16_t reserved;
} __packed;
struct afe_ttp_ssrc_offset_pair_t {
uint32_t ssrc;
uint32_t offset;
} __packed;
struct afe_ttp_gen_cfg_t {
uint32_t ttp_offset_default;
/*
* TTP offset uses for all other cases
* where no valid SSRC is received.
*/
uint32_t settling_time;
/*
* If settling_mode==0x00: time in [us]
* after first received packet until
* packets are no longer dropped.
*/
uint16_t settling_mode;
/*
* 0x00(Drop), 0x01(Settle)
*/
uint16_t num_ssrc_offsets;
/*
* Number of SSRC/TTPOFFSET pairs to follow
*/
struct afe_ttp_ssrc_offset_pair_t ssrc_ttp_offset[MAX_TTP_OFFSET_PAIRS];
/*
* Array of ssrc/offset pairs
*/
} __packed;
struct afe_ttp_config {
struct afe_ttp_gen_enable_t ttp_gen_enable;
struct afe_ttp_gen_cfg_t ttp_gen_cfg;
};
union afe_dec_config_data { union afe_dec_config_data {
struct asm_sbc_dec_cfg_t sbc_config; struct asm_sbc_dec_cfg_t sbc_config;
struct asm_aac_dec_cfg_v2_t aac_config; struct asm_aac_dec_cfg_v2_t aac_config;
@@ -4876,6 +4940,9 @@ struct avs_dec_congestion_buffer_param_t {
/* Payload of the AFE_PARAM_ID_ISLAND_CONFIG parameter used by /* Payload of the AFE_PARAM_ID_ISLAND_CONFIG parameter used by
* AFE_MODULE_AUDIO_DEV_INTERFACE. * AFE_MODULE_AUDIO_DEV_INTERFACE.
*/ */
#define AFE_PARAM_ID_POWER_MODE_CONFIG 0x0002002c
#define AFE_API_VERSION_POWER_MODE_CONFIG 0x1
struct afe_param_id_island_cfg_t { struct afe_param_id_island_cfg_t {
uint32_t island_cfg_minor_version; uint32_t island_cfg_minor_version;
/* Tracks the configuration of this parameter. /* Tracks the configuration of this parameter.
@@ -4889,6 +4956,19 @@ struct afe_param_id_island_cfg_t {
*/ */
} __packed; } __packed;
struct afe_param_id_power_mode_cfg_t {
uint32_t power_mode_cfg_minor_version;
/* Tracks the configuration of this parameter
* Supported values: #AFE_API_VERSION_POWER_MODE_CONFIG
*/
uint32_t power_mode_enable;
/* Specifies whether island mode should be enabled or disabled for the
* use-case being setup.
* Supported values: 0 - Disable, 1 - Enable
*/
} __packed;
/* ID of the parameter used by #AFE_MODULE_AUDIO_DEV_INTERFACE to configure /* ID of the parameter used by #AFE_MODULE_AUDIO_DEV_INTERFACE to configure
* the Codec DMA interface. * the Codec DMA interface.
*/ */
@@ -5380,6 +5460,7 @@ struct afe_param_id_lpass_core_shared_clk_cfg {
#define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774 #define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774
#define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY 0x00010F89 #define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY 0x00010F89
#define VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY 0x10000003 #define VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY 0x10000003
#define VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY 0x10000004
#define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72 #define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72
#define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75 #define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75
#define VPM_TX_DM_RFECNS_COPP_TOPOLOGY 0x00010F86 #define VPM_TX_DM_RFECNS_COPP_TOPOLOGY 0x00010F86
@@ -8887,6 +8968,13 @@ struct asm_data_cmd_remove_silence {
/* Shift value for the IEC 61937 to 61937 pass-through capture. */ /* Shift value for the IEC 61937 to 61937 pass-through capture. */
#define ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG 0 #define ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG 0
/* Bitmask for the DSD pass-through capture. */
#define ASM_BIT_MASK_COMPRESSED_FORMAT_FLAG (0x00000003UL)
/* Shift value for the DSD pass-through capture. */
#define ASM_SHIFT_DSD_COMPRESSED_FORMAT_FLAG 0
#define ASM_DSD_FORMAT_FLAG 2
struct asm_stream_cmd_open_read_compressed { struct asm_stream_cmd_open_read_compressed {
struct apr_hdr hdr; struct apr_hdr hdr;
u32 mode_flags; u32 mode_flags;
@@ -8898,6 +8986,12 @@ struct asm_stream_cmd_open_read_compressed {
* - Use #ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG to set the bitmask * - Use #ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG to set the bitmask
* and #ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG to set the shift value * and #ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG to set the shift value
* for this bit. * for this bit.
* Supported values for bit 1: (DSD native pass-through mode)
* 0 -- non DSD operation
* 1 -- Pass-through transfer of the DSD format stream
* To set this bit, use #ASM_BIT_MASK_DSD_PASS_THROUGH_FLAG and
* use #ASM_SHIFT_DSD_PASS_THROUGH_FLAG to set the shift value for
* this bit
* Supported values for bit 4: * Supported values for bit 4:
* - 0 -- Return data buffer contains all encoded frames only; it does * - 0 -- Return data buffer contains all encoded frames only; it does
* not contain frame metadata. * not contain frame metadata.
@@ -8914,6 +9008,9 @@ struct asm_stream_cmd_open_read_compressed {
* Supported values: should be greater than 0 for IEC to RAW compressed * Supported values: should be greater than 0 for IEC to RAW compressed
* unpack mode. * unpack mode.
* Value is don't care for IEC 61937 pass-through mode. * Value is don't care for IEC 61937 pass-through mode.
* @values
* - >0 -- For IEC 61937-to-RAW Compressed Unpack mode
* - 1 -- For IEC 61937 or DSD Pass-through mode
*/ */
} __packed; } __packed;
@@ -12102,6 +12199,35 @@ struct afe_clk_cfg {
#define AFE_MODULE_CLOCK_SET 0x0001028F #define AFE_MODULE_CLOCK_SET 0x0001028F
#define AFE_PARAM_ID_CLOCK_SET 0x00010290 #define AFE_PARAM_ID_CLOCK_SET 0x00010290
struct afe_set_clk_drift {
/*
* Clock ID
* @values
* - 0x100 to 0x10E
* - 0x200 to 0x20C
* - 0x500 to 0x505
*/
uint32_t clk_id;
/*
* Clock drift (in PPB) to be set.
* @values
* - need to get values from DSP team
*/
int32_t clk_drift;
/*
* Clock rest.
* @values
* - 1 -- Reset PLL with the original frequency
* - 0 -- Adjust the clock with the clk drift value
*/
uint32_t clk_reset;
} __packed;
/* This param id is used to adjust audio interface PLL*/
#define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6
enum afe_lpass_digital_clk_src { enum afe_lpass_digital_clk_src {
Q6AFE_LPASS_DIGITAL_ROOT_INVALID, Q6AFE_LPASS_DIGITAL_ROOT_INVALID,
Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR, Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR,

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2010-2017, 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2010-2017, 2019, 2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef __APR_H_ #ifndef __APR_H_
#define __APR_H_ #define __APR_H_
@@ -12,6 +12,7 @@ enum apr_subsys_state {
APR_SUBSYS_DOWN, APR_SUBSYS_DOWN,
APR_SUBSYS_UP, APR_SUBSYS_UP,
APR_SUBSYS_LOADED, APR_SUBSYS_LOADED,
APR_SUBSYS_UNKNOWN,
}; };
struct apr_q6 { struct apr_q6 {
@@ -19,6 +20,13 @@ struct apr_q6 {
atomic_t q6_state; atomic_t q6_state;
atomic_t modem_state; atomic_t modem_state;
struct mutex lock; struct mutex lock;
/*
* ToDo - Multiple client support to be added.
* And checking for state UNKNOWN currently.
*/
void (*state_notify_cb)(enum apr_subsys_state state,
void *client_handle);
void *client_handle;
}; };
struct apr_hdr { struct apr_hdr {
@@ -186,4 +194,5 @@ const char *apr_get_lpass_subsys_name(void);
uint16_t apr_get_reset_domain(uint16_t proc); uint16_t apr_get_reset_domain(uint16_t proc);
int apr_start_rx_rt(void *handle); int apr_start_rx_rt(void *handle);
int apr_end_rx_rt(void *handle); int apr_end_rx_rt(void *handle);
void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle);
#endif #endif

View File

@@ -7,9 +7,9 @@
/* CONFIG GET/SET */ /* CONFIG GET/SET */
#define CONFIG_CACHE 0 #define AUDIO_EFFECTS_CONFIG_CACHE 0
#define CONFIG_SET 1 #define AUDIO_EFFECTS_CONFIG_SET 1
#define CONFIG_GET 2 #define AUDIO_EFFECTS_CONFIG_GET 2
/* CONFIG HEADER */ /* CONFIG HEADER */
/* /*
@@ -17,14 +17,14 @@
* DEVICE, * DEVICE,
* NUM_COMMANDS, * NUM_COMMANDS,
* COMMAND_ID_1, * COMMAND_ID_1,
* CONFIG_CACHE/SET/GET, * AUDIO_EFFECTS_CONFIG_CACHE/SET/GET,
* OFFSET_1, * OFFSET_1,
* LENGTH_1, * LENGTH_1,
* VALUES_1, * VALUES_1,
* ..., * ...,
* ..., * ...,
* COMMAND_ID_2, * COMMAND_ID_2,
* CONFIG_CACHE/SET/GET, * AUDIO_EFFECTS_CONFIG_CACHE/SET/GET,
* OFFSET_2, * OFFSET_2,
* LENGTH_2, * LENGTH_2,
* VALUES_2, * VALUES_2,

View File

@@ -5,9 +5,8 @@
#define LSM_EVENT_TIMESTAMP_MODE_SUPPORT #define LSM_EVENT_TIMESTAMP_MODE_SUPPORT
#include <linux/types.h> #include <linux/types.h>
#include <sound/asound.h>
#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 1) #define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 2)
#define LSM_MAX_STAGES_PER_SESSION 2 #define LSM_MAX_STAGES_PER_SESSION 2
#define LSM_STAGE_INDEX_FIRST 0 #define LSM_STAGE_INDEX_FIRST 0
@@ -34,7 +33,10 @@
#define LSM_POLLING_ENABLE (7) #define LSM_POLLING_ENABLE (7)
#define LSM_DET_EVENT_TYPE (8) #define LSM_DET_EVENT_TYPE (8)
#define LSM_LAB_CONTROL (9) #define LSM_LAB_CONTROL (9)
#define LSM_PARAMS_MAX (LSM_LAB_CONTROL + 1) #define LSM_REG_MULTI_SND_MODEL (10)
#define LSM_DEREG_MULTI_SND_MODEL (11)
#define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12)
#define LSM_PARAMS_MAX (LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS + 1)
#define LSM_EVENT_NON_TIME_STAMP_MODE (0) #define LSM_EVENT_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1) #define LSM_EVENT_TIME_STAMP_MODE (1)
@@ -227,6 +229,7 @@ struct lsm_params_info {
* Member variables applicable only to V2: * Member variables applicable only to V2:
* @instance_id: instance id of the param to which parameter is to be set * @instance_id: instance id of the param to which parameter is to be set
* @stage_idx: detection stage for which the param is applicable * @stage_idx: detection stage for which the param is applicable
* @model_id: an unique number to identify sound models in DSP
*/ */
struct lsm_params_info_v2 { struct lsm_params_info_v2 {
__u32 module_id; __u32 module_id;
@@ -236,6 +239,7 @@ struct lsm_params_info_v2 {
__u32 param_type; __u32 param_type;
__u16 instance_id; __u16 instance_id;
__u16 stage_idx; __u16 stage_idx;
__u32 model_id;
}; };
/* /*

View File

@@ -1,6 +1,8 @@
#ifndef _CALIB_HWDEP_H #ifndef _CALIB_HWDEP_H
#define _CALIB_HWDEP_H #define _CALIB_HWDEP_H
#include <linux/types.h>
#define WCD9XXX_CODEC_HWDEP_NODE 1000 #define WCD9XXX_CODEC_HWDEP_NODE 1000
#define AQT1000_CODEC_HWDEP_NODE 1001 #define AQT1000_CODEC_HWDEP_NODE 1001
#define Q6AFE_HWDEP_NODE 1002 #define Q6AFE_HWDEP_NODE 1002

View File

@@ -2,7 +2,6 @@
#define __VOICE_PARAMS_H__ #define __VOICE_PARAMS_H__
#include <linux/types.h> #include <linux/types.h>
#include <sound/asound.h>
enum voice_lch_mode { enum voice_lch_mode {
VOICE_LCH_START = 1, VOICE_LCH_START = 1,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/gpio.h> #include <linux/gpio.h>
@@ -15,6 +15,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h>
#include <soc/snd_event.h> #include <soc/snd_event.h>
#include <dsp/digital-cdc-rsc-mgr.h> #include <dsp/digital-cdc-rsc-mgr.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
@@ -489,6 +490,8 @@ static int lpi_notifier_service_cb(struct notifier_block *this,
/* Reset HW votes after SSR */ /* Reset HW votes after SSR */
if (!lpi_dev_up) { if (!lpi_dev_up) {
/* Add 100ms sleep to ensure AVS is up after SSR */
msleep(100);
if (state->lpass_core_hw_vote) if (state->lpass_core_hw_vote)
digital_cdc_rsc_mgr_hw_vote_reset( digital_cdc_rsc_mgr_hw_vote_reset(
state->lpass_core_hw_vote); state->lpass_core_hw_vote);

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@@ -473,10 +473,6 @@ int swr_get_logical_dev_num(struct swr_device *dev, u64 dev_id,
} }
mutex_lock(&master->mlock); mutex_lock(&master->mlock);
ret = master->get_logical_dev_num(master, dev_id, dev_num); ret = master->get_logical_dev_num(master, dev_id, dev_num);
if (ret) {
pr_err("%s: Error %d to get logical addr for device %llx\n",
__func__, ret, dev_id);
}
mutex_unlock(&master->mlock); mutex_unlock(&master->mlock);
return ret; return ret;
} }

View File

@@ -41,7 +41,6 @@
#define SWRM_DSD_PARAMS_PORT 4 #define SWRM_DSD_PARAMS_PORT 4
#define SWR_BROADCAST_CMD_ID 0x0F #define SWR_BROADCAST_CMD_ID 0x0F
#define SWR_AUTO_SUSPEND_DELAY 1 /* delay in sec */
#define SWR_DEV_ID_MASK 0xFFFFFFFFFFFF #define SWR_DEV_ID_MASK 0xFFFFFFFFFFFF
#define SWR_REG_VAL_PACK(data, dev, id, reg) \ #define SWR_REG_VAL_PACK(data, dev, id, reg) \
((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24)) ((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
@@ -82,7 +81,7 @@
#define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08
/* pm runtime auto suspend timer in msecs */ /* pm runtime auto suspend timer in msecs */
static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000; static int auto_suspend_timer = 500;
module_param(auto_suspend_timer, int, 0664); module_param(auto_suspend_timer, int, 0664);
MODULE_PARM_DESC(auto_suspend_timer, "timer for auto suspend"); MODULE_PARM_DESC(auto_suspend_timer, "timer for auto suspend");
@@ -121,7 +120,7 @@ static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm);
static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm); static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm);
static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr); static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr);
static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val); static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val);
static int swrm_runtime_resume(struct device *dev);
static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq) static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
{ {
@@ -647,6 +646,7 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
usleep_range(50, 55); usleep_range(50, 55);
swr_master_write(swrm, reg_addr[i], val[i]); swr_master_write(swrm, reg_addr[i], val[i]);
} }
usleep_range(100, 110);
mutex_unlock(&swrm->iolock); mutex_unlock(&swrm->iolock);
} }
return 0; return 0;
@@ -901,6 +901,8 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
mutex_unlock(&swrm->devlock); mutex_unlock(&swrm->devlock);
pm_runtime_get_sync(swrm->dev); pm_runtime_get_sync(swrm->dev);
if (swrm->req_clk_switch)
swrm_runtime_resume(swrm->dev);
ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr, len); ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr, len);
if (!ret) if (!ret)
@@ -934,6 +936,8 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
mutex_unlock(&swrm->devlock); mutex_unlock(&swrm->devlock);
pm_runtime_get_sync(swrm->dev); pm_runtime_get_sync(swrm->dev);
if (swrm->req_clk_switch)
swrm_runtime_resume(swrm->dev);
ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr); ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
pm_runtime_put_autosuspend(swrm->dev); pm_runtime_put_autosuspend(swrm->dev);
@@ -1105,6 +1109,8 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq)
bus_clk_freq = SWR_CLK_RATE_4P8MHZ; bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ) else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ)
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_11P2896MHZ) } else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ)
bus_clk_freq = SWR_CLK_RATE_11P2896MHZ; bus_clk_freq = SWR_CLK_RATE_11P2896MHZ;
@@ -1871,7 +1877,7 @@ handle_irq:
swrm_enable_slave_irq(swrm); swrm_enable_slave_irq(swrm);
if (status == swrm->slave_status) { if (status == swrm->slave_status) {
dev_dbg(swrm->dev, dev_dbg(swrm->dev,
"%s: No change in slave status: %d\n", "%s: No change in slave status: 0x%x\n",
__func__, status); __func__, status);
break; break;
} }
@@ -1923,16 +1929,22 @@ handle_irq:
swrm->intr_mask); swrm->intr_mask);
break; break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW: case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n", value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
__func__); dev_err(swrm->dev,
"%s: SWR read FIFO overflow fifo status\n",
__func__, value);
break; break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW: case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
dev_dbg(swrm->dev, "%s: SWR read FIFO underflow\n", value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
__func__); dev_err(swrm->dev,
"%s: SWR read FIFO underflow fifo status\n",
__func__, value);
break; break;
case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW: case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n", value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
__func__); dev_err(swrm->dev,
"%s: SWR write FIFO overflow fifo status\n",
__func__, value);
swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
break; break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR: case SWRM_INTERRUPT_STATUS_CMD_ERROR:
@@ -2175,16 +2187,18 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
if ((id & SWR_DEV_ID_MASK) == dev_id) { if ((id & SWR_DEV_ID_MASK) == dev_id) {
*dev_num = i; *dev_num = i;
ret = 0; ret = 0;
dev_info(swrm->dev,
"%s: devnum %d assigned for dev %llx\n",
__func__, i,
swr_dev->addr);
} }
dev_dbg(swrm->dev,
"%s: devnum %d is assigned for dev addr %lx\n",
__func__, i, swr_dev->addr);
} }
} }
} }
} }
if (ret) if (ret)
dev_err(swrm->dev, "%s: device 0x%llx is not ready\n", dev_err_ratelimited(swrm->dev,
"%s: device 0x%llx is not ready\n",
__func__, dev_id); __func__, dev_id);
pm_runtime_mark_last_busy(swrm->dev); pm_runtime_mark_last_busy(swrm->dev);
@@ -2659,6 +2673,8 @@ static int swrm_probe(struct platform_device *pdev)
* controller will be up now * controller will be up now
*/ */
swr_master_add_boarddevices(&swrm->master); swr_master_add_boarddevices(&swrm->master);
if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true))
dev_dbg(&pdev->dev, "%s: Audio HW Vote is failed\n", __func__);
mutex_lock(&swrm->mlock); mutex_lock(&swrm->mlock);
swrm_clk_request(swrm, true); swrm_clk_request(swrm, true);
swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION); swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION);
@@ -2721,13 +2737,13 @@ err_mstr_fail:
swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
swrm, SWR_IRQ_FREE); swrm, SWR_IRQ_FREE);
} else if (swrm->irq) { } else if (swrm->irq) {
free_irq(swrm->irq, swrm);
irqd_set_trigger_type( irqd_set_trigger_type(
irq_get_irq_data(swrm->irq), irq_get_irq_data(swrm->irq),
IRQ_TYPE_NONE); IRQ_TYPE_NONE);
}
if (swrm->swr_irq_wakeup_capable) if (swrm->swr_irq_wakeup_capable)
irq_set_irq_wake(swrm->irq, 0); irq_set_irq_wake(swrm->irq, 0);
free_irq(swrm->irq, swrm);
}
err_irq_fail: err_irq_fail:
mutex_destroy(&swrm->irq_lock); mutex_destroy(&swrm->irq_lock);
mutex_destroy(&swrm->mlock); mutex_destroy(&swrm->mlock);
@@ -2751,15 +2767,15 @@ static int swrm_remove(struct platform_device *pdev)
swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
swrm, SWR_IRQ_FREE); swrm, SWR_IRQ_FREE);
} else if (swrm->irq) { } else if (swrm->irq) {
free_irq(swrm->irq, swrm);
irqd_set_trigger_type( irqd_set_trigger_type(
irq_get_irq_data(swrm->irq), irq_get_irq_data(swrm->irq),
IRQ_TYPE_NONE); IRQ_TYPE_NONE);
if (swrm->swr_irq_wakeup_capable)
irq_set_irq_wake(swrm->irq, 0);
free_irq(swrm->irq, swrm);
} else if (swrm->wake_irq > 0) { } else if (swrm->wake_irq > 0) {
free_irq(swrm->wake_irq, swrm); free_irq(swrm->wake_irq, swrm);
} }
if (swrm->swr_irq_wakeup_capable)
irq_set_irq_wake(swrm->irq, 0);
cancel_work_sync(&swrm->wakeup_work); cancel_work_sync(&swrm->wakeup_work);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
@@ -2799,7 +2815,6 @@ static int swrm_runtime_resume(struct device *dev)
int ret = 0; int ret = 0;
bool swrm_clk_req_err = false; bool swrm_clk_req_err = false;
bool hw_core_err = false; bool hw_core_err = false;
bool aud_core_err = false;
struct swr_master *mstr = &swrm->master; struct swr_master *mstr = &swrm->master;
struct swr_device *swr_dev; struct swr_device *swr_dev;
u32 temp = 0; u32 temp = 0;
@@ -2815,11 +2830,9 @@ static int swrm_runtime_resume(struct device *dev)
__func__); __func__);
hw_core_err = true; hw_core_err = true;
} }
if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true))
dev_err(dev, "%s:lpass audio hw enable failed\n", dev_err(dev, "%s:lpass audio hw enable failed\n",
__func__); __func__);
aud_core_err = true;
}
if ((swrm->state == SWR_MSTR_DOWN) || if ((swrm->state == SWR_MSTR_DOWN) ||
(swrm->state == SWR_MSTR_SSR && swrm->dev_up)) { (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) {
@@ -2911,8 +2924,6 @@ static int swrm_runtime_resume(struct device *dev)
swrm->state = SWR_MSTR_UP; swrm->state = SWR_MSTR_UP;
} }
exit: exit:
if (!aud_core_err)
swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
if (!hw_core_err) if (!hw_core_err)
swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
if (swrm_clk_req_err) if (swrm_clk_req_err)
@@ -2921,6 +2932,8 @@ exit:
else else
pm_runtime_set_autosuspend_delay(&pdev->dev, pm_runtime_set_autosuspend_delay(&pdev->dev,
auto_suspend_timer); auto_suspend_timer);
if (swrm->req_clk_switch)
swrm->req_clk_switch = false;
mutex_unlock(&swrm->reslock); mutex_unlock(&swrm->reslock);
trace_printk("%s: pm_runtime: resume done, state:%d\n", trace_printk("%s: pm_runtime: resume done, state:%d\n",
@@ -2934,7 +2947,6 @@ static int swrm_runtime_suspend(struct device *dev)
struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
int ret = 0; int ret = 0;
bool hw_core_err = false; bool hw_core_err = false;
bool aud_core_err = false;
struct swr_master *mstr = &swrm->master; struct swr_master *mstr = &swrm->master;
struct swr_device *swr_dev; struct swr_device *swr_dev;
int current_state = 0; int current_state = 0;
@@ -2953,11 +2965,6 @@ static int swrm_runtime_suspend(struct device *dev)
__func__); __func__);
hw_core_err = true; hw_core_err = true;
} }
if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) {
dev_err(dev, "%s:lpass audio hw enable failed\n",
__func__);
aud_core_err = true;
}
if ((current_state == SWR_MSTR_UP) || if ((current_state == SWR_MSTR_UP) ||
(current_state == SWR_MSTR_SSR)) { (current_state == SWR_MSTR_SSR)) {
@@ -3036,12 +3043,14 @@ static int swrm_runtime_suspend(struct device *dev)
} }
} }
if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false))
dev_dbg(dev, "%s:lpass audio hw enable failed\n",
__func__);
/* Retain SSR state until resume */ /* Retain SSR state until resume */
if (current_state != SWR_MSTR_SSR) if (current_state != SWR_MSTR_SSR)
swrm->state = SWR_MSTR_DOWN; swrm->state = SWR_MSTR_DOWN;
exit: exit:
if (!aud_core_err)
swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
if (!hw_core_err) if (!hw_core_err)
swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
mutex_unlock(&swrm->reslock); mutex_unlock(&swrm->reslock);
@@ -3214,8 +3223,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
} }
mutex_lock(&swrm->mlock); mutex_lock(&swrm->mlock);
if (swrm->clk_src != *(int *)data) { if (swrm->clk_src != *(int *)data) {
if (swrm->state == SWR_MSTR_UP) if (swrm->state == SWR_MSTR_UP) {
swrm->req_clk_switch = true;
swrm_device_suspend(&pdev->dev); swrm_device_suspend(&pdev->dev);
if (swrm->state == SWR_MSTR_UP)
swrm->req_clk_switch = false;
}
swrm->clk_src = *(int *)data; swrm->clk_src = *(int *)data;
} }
mutex_unlock(&swrm->mlock); mutex_unlock(&swrm->mlock);

View File

@@ -175,6 +175,7 @@ struct swr_mstr_ctrl {
u32 ipc_wakeup; u32 ipc_wakeup;
bool dev_up; bool dev_up;
bool ipc_wakeup_triggered; bool ipc_wakeup_triggered;
bool req_clk_switch;
struct pm_qos_request pm_qos_req; struct pm_qos_request pm_qos_req;
enum swrm_pm_state pm_state; enum swrm_pm_state pm_state;
wait_queue_head_t pm_wq; wait_queue_head_t pm_wq;