Merge "asoc: sm6150: Add SND event FWK support for talos"

This commit is contained in:
Linux Build Service Account
2018-09-26 21:37:02 -07:00
committed by Gerrit - the friendly Code Review server
14 changed files with 431 additions and 139 deletions

View File

@@ -18,7 +18,7 @@
#include <linux/printk.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <soc/snd_event.h>
#include "bolero-cdc.h"
#include "internal.h"
@@ -62,6 +62,11 @@ static int __bolero_reg_read(struct bolero_priv *priv,
u16 current_mclk_mux_macro;
mutex_lock(&priv->clk_lock);
if (!priv->dev_up) {
dev_dbg_ratelimited(priv->dev,
"%s: SSR in progress, exit\n", __func__);
goto err;
}
current_mclk_mux_macro =
priv->current_mclk_mux_macro[macro_id];
if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
@@ -94,6 +99,11 @@ static int __bolero_reg_write(struct bolero_priv *priv,
u16 current_mclk_mux_macro;
mutex_lock(&priv->clk_lock);
if (!priv->dev_up) {
dev_dbg_ratelimited(priv->dev,
"%s: SSR in progress, exit\n", __func__);
goto err;
}
current_mclk_mux_macro =
priv->current_mclk_mux_macro[macro_id];
if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
@@ -529,10 +539,64 @@ static ssize_t bolero_version_read(struct snd_info_entry *entry,
return simple_read_from_buffer(buf, count, &pos, buffer, len);
}
static int bolero_ssr_enable(struct device *dev, void *data)
{
struct bolero_priv *priv = data;
int macro_idx;
if (priv->initial_boot) {
priv->initial_boot = false;
return 0;
}
if (priv->macro_params[VA_MACRO].event_handler)
priv->macro_params[VA_MACRO].event_handler(priv->codec,
BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET, 0x0);
regcache_cache_only(priv->regmap, false);
/* call ssr event for supported macros */
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->codec,
BOLERO_MACRO_EVT_SSR_UP, 0x0);
}
mutex_lock(&priv->clk_lock);
priv->dev_up = true;
mutex_unlock(&priv->clk_lock);
bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_UP);
return 0;
}
static void bolero_ssr_disable(struct device *dev, void *data)
{
struct bolero_priv *priv = data;
int macro_idx;
regcache_cache_only(priv->regmap, true);
mutex_lock(&priv->clk_lock);
priv->dev_up = false;
mutex_unlock(&priv->clk_lock);
/* call ssr event for supported macros */
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->codec,
BOLERO_MACRO_EVT_SSR_DOWN, 0x0);
}
bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_DOWN);
}
static struct snd_info_entry_ops bolero_info_ops = {
.read = bolero_version_read,
};
static const struct snd_event_ops bolero_ssr_ops = {
.enable = bolero_ssr_enable,
.disable = bolero_ssr_disable,
};
/*
* bolero_info_create_codec_entry - creates bolero module
* @codec_root: The parent directory
@@ -623,6 +687,16 @@ static int bolero_soc_codec_probe(struct snd_soc_codec *codec)
else if (priv->num_macros_registered > 2)
priv->version = BOLERO_VERSION_1_2;
ret = snd_event_client_register(priv->dev, &bolero_ssr_ops, priv);
if (!ret) {
snd_event_notify(priv->dev, SND_EVENT_UP);
} else {
dev_err(codec->dev,
"%s: Registration with SND event FWK failed ret = %d\n",
__func__, ret);
goto err;
}
dev_dbg(codec->dev, "%s: bolero soc codec probe success\n", __func__);
err:
return ret;
@@ -633,6 +707,7 @@ static int bolero_soc_codec_remove(struct snd_soc_codec *codec)
struct bolero_priv *priv = dev_get_drvdata(codec->dev);
int macro_idx;
snd_event_client_deregister(priv->dev);
/* call exit for supported macros */
for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++)
if (priv->macro_params[macro_idx].exit)
@@ -756,6 +831,8 @@ static int bolero_probe(struct platform_device *pdev)
bolero_reg_access[VA_MACRO] = bolero_va_top_reg_access;
priv->dev = &pdev->dev;
priv->dev_up = true;
priv->initial_boot = true;
priv->regmap = bolero_regmap_init(priv->dev,
&bolero_regmap_config);
if (IS_ERR_OR_NULL((void *)(priv->regmap))) {

View File

@@ -43,6 +43,9 @@ enum {
BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */
BOLERO_MACRO_EVT_IMPED_FALSE, /* for imped false */
BOLERO_MACRO_EVT_SSR_DOWN,
BOLERO_MACRO_EVT_SSR_UP,
BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET
};
struct macro_ops {

View File

@@ -20,6 +20,8 @@
/* from bolero to WCD events */
enum {
BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
BOLERO_WCD_EVT_SSR_DOWN,
BOLERO_WCD_EVT_SSR_UP,
};
enum {
@@ -52,6 +54,8 @@ struct bolero_priv {
struct mutex clk_lock;
bool va_without_decimation;
bool macros_supported[MAX_MACRO];
bool dev_up;
bool initial_boot;
struct macro_ops macro_params[MAX_MACRO];
struct snd_soc_dai_driver *bolero_dais;
u16 num_dais;

View File

@@ -1130,6 +1130,19 @@ static int rx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
case BOLERO_MACRO_EVT_IMPED_FALSE:
rx_macro_wcd_clsh_imped_config(codec, data, false);
break;
case BOLERO_MACRO_EVT_SSR_DOWN:
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_DOWN, NULL);
break;
case BOLERO_MACRO_EVT_SSR_UP:
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_SSR_UP, NULL);
break;
}
return 0;
}

View File

@@ -19,6 +19,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <soc/swr-wcd.h>
#include "bolero-cdc.h"
#include "bolero-cdc-registers.h"
#include "../msm-cdc-pinctrl.h"
@@ -303,6 +304,33 @@ exit:
return ret;
}
static int tx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
u32 data)
{
struct device *tx_dev = NULL;
struct tx_macro_priv *tx_priv = NULL;
if (!tx_macro_get_data(codec, &tx_dev, &tx_priv, __func__))
return -EINVAL;
switch (event) {
case BOLERO_MACRO_EVT_SSR_DOWN:
swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_DEVICE_DOWN, NULL);
break;
case BOLERO_MACRO_EVT_SSR_UP:
swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_DEVICE_SSR_UP, NULL);
break;
}
return 0;
}
static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
{
struct delayed_work *hpf_delayed_work = NULL;
@@ -1640,6 +1668,7 @@ static void tx_macro_init_ops(struct macro_ops *ops,
ops->dai_ptr = tx_macro_dai;
ops->num_dais = ARRAY_SIZE(tx_macro_dai);
ops->mclk_fn = tx_macro_mclk_ctrl;
ops->event_handler = tx_macro_event_handler;
}
static int tx_macro_probe(struct platform_device *pdev)

View File

@@ -46,6 +46,7 @@
#define VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01
#define BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS 40
#define MAX_RETRY_ATTEMPTS 50
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static int va_tx_unmute_delay = BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS;
@@ -178,8 +179,7 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv,
0x02, 0x02);
}
} else {
va_priv->va_mclk_users--;
if (va_priv->va_mclk_users == 0) {
if (va_priv->va_mclk_users == 1) {
regmap_update_bits(regmap,
BOLERO_CDC_VA_TOP_CSR_TOP_CFG0,
0x02, 0x00);
@@ -192,12 +192,47 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv,
bolero_request_clock(va_priv->dev,
VA_MACRO, MCLK_MUX0, false);
}
va_priv->va_mclk_users--;
}
exit:
mutex_unlock(&va_priv->mclk_lock);
return ret;
}
static int va_macro_event_handler(struct snd_soc_codec *codec, u16 event,
u32 data)
{
struct device *va_dev = NULL;
struct va_macro_priv *va_priv = NULL;
int retry_cnt = MAX_RETRY_ATTEMPTS;
if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
return -EINVAL;
switch (event) {
case BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET:
while ((va_priv->va_mclk_users != 0) && (retry_cnt != 0)) {
dev_dbg(va_dev, "%s:retry_cnt: %d\n",
__func__, retry_cnt);
/*
* loop and check every 20ms for va_mclk user count
* to get reset to 0 which ensures userspace teardown
* is done and SSR powerup seq can proceed.
*/
msleep(20);
retry_cnt--;
}
if (retry_cnt == 0)
dev_err(va_dev,
"%s: va_mclk_users is non-zero still, audio SSR fail!!\n",
__func__);
break;
default:
break;
}
return 0;
}
static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -1054,13 +1089,13 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("VA_MCLK", 0, SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
va_macro_mclk_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY_S("VA_MCLK", 0, SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
va_macro_mclk_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
@@ -1465,6 +1500,7 @@ static void va_macro_init_ops(struct macro_ops *ops,
ops->exit = va_macro_deinit;
ops->io_base = va_io_base;
ops->mclk_fn = va_macro_mclk_ctrl;
ops->event_handler = va_macro_event_handler;
}
static int va_macro_probe(struct platform_device *pdev)

View File

@@ -859,6 +859,33 @@ exit:
return ret;
}
static int wsa_macro_event_handler(struct snd_soc_codec *codec, u16 event,
u32 data)
{
struct device *wsa_dev = NULL;
struct wsa_macro_priv *wsa_priv = NULL;
if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
return -EINVAL;
switch (event) {
case BOLERO_MACRO_EVT_SSR_DOWN:
swrm_wcd_notify(
wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
swrm_wcd_notify(
wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
SWR_DEVICE_DOWN, NULL);
break;
case BOLERO_MACRO_EVT_SSR_UP:
swrm_wcd_notify(
wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
SWR_DEVICE_SSR_UP, NULL);
break;
}
return 0;
}
static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -2617,6 +2644,7 @@ static void wsa_macro_init_ops(struct macro_ops *ops,
ops->dai_ptr = wsa_macro_dai;
ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
ops->mclk_fn = wsa_macro_mclk_ctrl;
ops->event_handler = wsa_macro_event_handler;
}
static int wsa_macro_probe(struct platform_device *pdev)

View File

@@ -123,6 +123,8 @@ enum {
enum {
BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
BOLERO_WCD_EVT_SSR_DOWN,
BOLERO_WCD_EVT_SSR_UP,
};
enum {

View File

@@ -974,6 +974,7 @@ int wcd937x_mbhc_post_ssr_init(struct wcd937x_mbhc *mbhc,
return -EINVAL;
}
wcd937x_mbhc_hs_detect_exit(codec);
wcd_mbhc_deinit(wcd_mbhc);
ret = wcd_mbhc_init(wcd_mbhc, codec, &mbhc_cb, &intr_ids,
wcd_mbhc_registers, WCD937X_ZDET_SUPPORTED);

View File

@@ -450,8 +450,10 @@ static bool wcd937x_volatile_register(struct device *dev, unsigned int reg)
{
if(reg <= WCD937X_BASE_ADDRESS)
return 0;
return (wcd937x_reg_access[WCD937X_REG(reg)] & RD_REG)
& ~(wcd937x_reg_access[WCD937X_REG(reg)] & WR_REG);
if ((wcd937x_reg_access[WCD937X_REG(reg)] & RD_REG)
&& !(wcd937x_reg_access[WCD937X_REG(reg)] & WR_REG))
return true;
return false;
}
struct regmap_config wcd937x_regmap_config = {

View File

@@ -48,6 +48,8 @@ static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static int wcd937x_handle_post_irq(void *data);
static int wcd937x_reset(struct device *dev);
static int wcd937x_reset_low(struct device *dev);
static const struct regmap_irq wcd937x_irqs[WCD937X_NUM_IRQS] = {
REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
@@ -1216,6 +1218,23 @@ int wcd937x_micbias_control(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL(wcd937x_micbias_control);
static int wcd937x_get_logical_addr(struct swr_device *swr_dev)
{
int ret = 0;
uint8_t devnum = 0;
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);
swr_remove_device(swr_dev);
return ret;
}
swr_dev->dev_num = devnum;
return 0;
}
static int wcd937x_event_notify(struct notifier_block *block,
unsigned long val,
void *data)
@@ -1223,8 +1242,10 @@ static int wcd937x_event_notify(struct notifier_block *block,
u16 event = (val & 0xffff);
u16 amic = (val >> 0x10);
u16 mask = 0x40, reg = 0x0;
int ret = 0;
struct wcd937x_priv *wcd937x = dev_get_drvdata((struct device *)data);
struct snd_soc_codec *codec = wcd937x->codec;
struct wcd_mbhc *mbhc;
switch (event) {
case BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR:
@@ -1238,6 +1259,25 @@ static int wcd937x_event_notify(struct notifier_block *block,
mask = 0x20;
snd_soc_update_bits(codec, reg, mask, 0x00);
break;
case BOLERO_WCD_EVT_SSR_DOWN:
wcd937x_reset_low(wcd937x->dev);
break;
case BOLERO_WCD_EVT_SSR_UP:
wcd937x_reset(wcd937x->dev);
wcd937x_get_logical_addr(wcd937x->tx_swr_dev);
wcd937x_get_logical_addr(wcd937x->rx_swr_dev);
regcache_mark_dirty(wcd937x->regmap);
regcache_sync(wcd937x->regmap);
/* Initialize MBHC module */
mbhc = &wcd937x->mbhc->wcd_mbhc;
ret = wcd937x_mbhc_post_ssr_init(wcd937x->mbhc, codec);
if (ret) {
dev_err(codec->dev, "%s: mbhc initialization failed\n",
__func__);
} else {
wcd937x_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
}
break;
default:
dev_err(codec->dev, "%s: invalid event %d\n", __func__, event);
break;
@@ -1923,7 +1963,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wcd937x = {
},
};
int wcd937x_reset(struct device *dev)
static int wcd937x_reset(struct device *dev)
{
struct wcd937x_priv *wcd937x = NULL;
int rc = 0;
@@ -2026,6 +2066,36 @@ static void wcd937x_dt_parse_micbias_info(struct device *dev,
}
}
static int wcd937x_reset_low(struct device *dev)
{
struct wcd937x_priv *wcd937x = NULL;
int rc = 0;
if (!dev)
return -ENODEV;
wcd937x = dev_get_drvdata(dev);
if (!wcd937x)
return -EINVAL;
if (!wcd937x->rst_np) {
dev_err(dev, "%s: reset gpio device node not specified\n",
__func__);
return -EINVAL;
}
rc = msm_cdc_pinctrl_select_sleep_state(wcd937x->rst_np);
if (rc) {
dev_err(dev, "%s: wcd sleep state request fail!\n",
__func__);
return rc;
}
/* 20ms sleep required after pulling the reset gpio to LOW */
usleep_range(20, 30);
return rc;
}
struct wcd937x_pdata *wcd937x_populate_dt_data(struct device *dev)
{
struct wcd937x_pdata *pdata = NULL;

View File

@@ -85,6 +85,21 @@ static const struct component_ops wcd937x_slave_comp_ops = {
.unbind = wcd937x_slave_unbind,
};
static int wcd937x_swr_up(struct swr_device *pdev)
{
return 0;
}
static int wcd937x_swr_down(struct swr_device *pdev)
{
return 0;
}
static int wcd937x_swr_reset(struct swr_device *pdev)
{
return 0;
}
static int wcd937x_swr_probe(struct swr_device *pdev)
{
return component_add(&pdev->dev, &wcd937x_slave_comp_ops);
@@ -105,6 +120,9 @@ static struct swr_driver wcd937x_slave_driver = {
.probe = wcd937x_swr_probe,
.remove = wcd937x_swr_remove,
.id_table = wcd937x_swr_id,
.device_up = wcd937x_swr_up,
.device_down = wcd937x_swr_down,
.reset_device = wcd937x_swr_reset,
};
static int __init wcd937x_slave_init(void)

View File

@@ -28,7 +28,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/info.h>
#include <dsp/audio_notifier.h>
#include <soc/snd_event.h>
#include <dsp/q6afe-v2.h>
#include <dsp/q6core.h>
#include "device_event.h"
@@ -201,6 +201,7 @@ struct msm_asoc_mach_data {
struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
bool is_afe_config_done;
};
struct msm_asoc_wcd93xx_codec {
@@ -628,10 +629,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_sample_rate,
static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_sample_rate,
cdc_dma_sample_rate_text);
static struct platform_device *spdev;
static int msm_hifi_control;
static bool is_initial_boot;
static bool codec_reg_done;
static struct snd_soc_aux_dev *msm_aux_dev;
static struct snd_soc_codec_conf *msm_codec_conf;
@@ -4643,121 +4641,6 @@ static void msm_afe_clear_config(void)
afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
}
static int msm_adsp_power_up_config(struct snd_soc_codec *codec,
struct snd_card *card)
{
int ret = 0;
unsigned long timeout;
int adsp_ready = 0;
bool snd_card_online = 0;
timeout = jiffies +
msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
do {
if (!snd_card_online) {
snd_card_online = snd_card_is_online_state(card);
pr_debug("%s: Sound card is %s\n", __func__,
snd_card_online ? "Online" : "Offline");
}
if (!adsp_ready) {
adsp_ready = q6core_is_adsp_ready();
pr_debug("%s: ADSP Audio is %s\n", __func__,
adsp_ready ? "ready" : "not ready");
}
if (snd_card_online && adsp_ready)
break;
/*
* Sound card/ADSP will be coming up after subsystem restart and
* it might not be fully up when the control reaches
* here. So, wait for 50msec before checking ADSP state
*/
msleep(50);
} while (time_after(timeout, jiffies));
if (!snd_card_online || !adsp_ready) {
pr_err("%s: Timeout. Sound card is %s, ADSP Audio is %s\n",
__func__,
snd_card_online ? "Online" : "Offline",
adsp_ready ? "ready" : "not ready");
ret = -ETIMEDOUT;
goto err;
}
ret = msm_afe_set_config(codec);
if (ret)
pr_err("%s: Failed to set AFE config. err %d\n",
__func__, ret);
return 0;
err:
return ret;
}
static int sm6150_notifier_service_cb(struct notifier_block *this,
unsigned long opcode, void *ptr)
{
int ret;
struct snd_soc_card *card = NULL;
const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_codec *codec;
pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
switch (opcode) {
case AUDIO_NOTIFIER_SERVICE_DOWN:
/*
* Use flag to ignore initial boot notifications
* On initial boot msm_adsp_power_up_config is
* called on init. There is no need to clear
* and set the config again on initial boot.
*/
if (is_initial_boot)
break;
msm_afe_clear_config();
break;
case AUDIO_NOTIFIER_SERVICE_UP:
if (is_initial_boot) {
is_initial_boot = false;
break;
}
if (!spdev)
return -EINVAL;
card = platform_get_drvdata(spdev);
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);
ret = -EINVAL;
goto err;
}
codec = rtd->codec;
ret = msm_adsp_power_up_config(codec, card->snd_card);
if (ret < 0) {
dev_err(card->dev,
"%s: msm_adsp_power_up_config failed ret = %d!\n",
__func__, ret);
goto err;
}
break;
default:
break;
}
err:
return NOTIFY_OK;
}
static struct notifier_block service_nb = {
.notifier_call = sm6150_notifier_service_cb,
.priority = -INT_MAX,
};
static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
@@ -4845,11 +4728,12 @@ static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
ret = msm_adsp_power_up_config(codec, rtd->card->snd_card);
ret = msm_afe_set_config(codec);
if (ret) {
pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
goto err;
}
pdata->is_afe_config_done = true;
config_data = msm_codec_fn.get_afe_config_fn(codec,
AFE_AANC_VERSION);
@@ -8357,6 +8241,108 @@ static void msm_i2s_auxpcm_deinit(void)
mi2s_intf_conf[count].msm_is_mi2s_master = 0;
}
}
static int sm6150_ssr_enable(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct msm_asoc_mach_data *pdata;
int ret = 0;
if (!card) {
dev_err(dev, "%s: card is NULL\n", __func__);
ret = -EINVAL;
goto err;
}
if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
pdata = snd_soc_card_get_drvdata(card);
if (!pdata->is_afe_config_done) {
const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
struct snd_soc_pcm_runtime *rtd;
rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
if (!rtd) {
dev_err(dev,
"%s: snd_soc_get_pcm_runtime for %s failed!\n",
__func__, be_dl_name);
ret = -EINVAL;
goto err;
}
ret = msm_afe_set_config(rtd->codec);
if (ret)
dev_err(dev, "%s: Failed to set AFE config. err %d\n",
__func__, ret);
else
pdata->is_afe_config_done = true;
}
}
snd_soc_card_change_online_state(card, 1);
dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
err:
return ret;
}
static void sm6150_ssr_disable(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct msm_asoc_mach_data *pdata;
if (!card) {
dev_err(dev, "%s: card is NULL\n", __func__);
return;
}
dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
snd_soc_card_change_online_state(card, 0);
if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
pdata = snd_soc_card_get_drvdata(card);
msm_afe_clear_config();
pdata->is_afe_config_done = false;
}
}
static const struct snd_event_ops sm6150_ssr_ops = {
.enable = sm6150_ssr_enable,
.disable = sm6150_ssr_disable,
};
static int msm_audio_ssr_compare(struct device *dev, void *data)
{
struct device_node *node = data;
dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
__func__, dev->of_node, node);
return (dev->of_node && dev->of_node == node);
}
static int msm_audio_ssr_register(struct device *dev)
{
struct device_node *np = dev->of_node;
struct snd_event_clients *ssr_clients = NULL;
struct device_node *node;
int ret;
int i;
for (i = 0; ; i++) {
node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
if (!node)
break;
snd_event_mstr_add_client(&ssr_clients,
msm_audio_ssr_compare, node);
}
ret = snd_event_master_register(dev, &sm6150_ssr_ops,
ssr_clients, NULL);
if (!ret)
snd_event_notify(dev, SND_EVENT_UP);
return ret;
}
static int msm_asoc_machine_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
@@ -8419,7 +8405,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
goto err;
}
dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
spdev = pdev;
pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
"qcom,hph-en1-gpio", 0);
@@ -8486,15 +8471,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
}
msm_i2s_auxpcm_init(pdev);
if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
is_initial_boot = true;
ret = audio_notifier_register("sm6150",
AUDIO_NOTIFIER_ADSP_DOMAIN,
&service_nb);
if (ret < 0)
pr_err("%s: Audio notifier register failed ret = %d\n",
__func__, ret);
} else {
if (strcmp(card->name, "sm6150-tavil-snd-card")) {
pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
"qcom,cdc-dmic01-gpios",
0);
@@ -8502,13 +8479,19 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
"qcom,cdc-dmic23-gpios",
0);
}
ret = msm_audio_ssr_register(&pdev->dev);
if (ret)
pr_err("%s: Registration with SND event FWK failed ret = %d\n",
__func__, ret);
err:
return ret;
}
static int msm_asoc_machine_remove(struct platform_device *pdev)
{
audio_notifier_deregister("sm6150");
snd_event_master_deregister(&pdev->dev);
msm_i2s_auxpcm_deinit();
return 0;

View File

@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <soc/snd_event.h>
#include <dsp/audio_notifier.h>
#include "core.h"
@@ -59,6 +60,7 @@
#define LPI_GPIO_FUNC_FUNC5 "func5"
static bool lpi_dev_up;
static struct device *lpi_dev;
/* The index of each function in lpi_gpio_functions[] array */
enum lpi_gpio_func_index {
@@ -384,12 +386,14 @@ static int lpi_notifier_service_cb(struct notifier_block *this,
initial_boot = false;
break;
}
snd_event_notify(lpi_dev, SND_EVENT_DOWN);
lpi_dev_up = false;
break;
case AUDIO_NOTIFIER_SERVICE_UP:
if (initial_boot)
initial_boot = false;
lpi_dev_up = true;
snd_event_notify(lpi_dev, SND_EVENT_UP);
break;
default:
break;
@@ -402,6 +406,15 @@ static struct notifier_block service_nb = {
.priority = -INT_MAX,
};
static void lpi_pinctrl_ssr_disable(struct device *dev, void *data)
{
lpi_dev_up = false;
}
static const struct snd_event_ops lpi_pinctrl_ssr_ops = {
.disable = lpi_pinctrl_ssr_disable,
};
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
@@ -576,6 +589,7 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
goto err_range;
}
lpi_dev = &pdev->dev;
lpi_dev_up = true;
ret = audio_notifier_register("lpi_tlmm", AUDIO_NOTIFIER_ADSP_DOMAIN,
&service_nb);
@@ -585,8 +599,19 @@ static int lpi_pinctrl_probe(struct platform_device *pdev)
goto err_range;
}
ret = snd_event_client_register(dev, &lpi_pinctrl_ssr_ops, NULL);
if (!ret) {
snd_event_notify(dev, SND_EVENT_UP);
} else {
dev_err(dev, "%s: snd_event registration failed, ret [%d]\n",
__func__, ret);
goto err_snd_evt;
}
return 0;
err_snd_evt:
audio_notifier_deregister("lpi_tlmm");
err_range:
gpiochip_remove(&state->chip);
err_chip:
@@ -597,6 +622,7 @@ static int lpi_pinctrl_remove(struct platform_device *pdev)
{
struct lpi_gpio_state *state = platform_get_drvdata(pdev);
snd_event_client_deregister(&pdev->dev);
audio_notifier_deregister("lpi_tlmm");
gpiochip_remove(&state->chip);
return 0;