asoc: codecs: Add parent child relation for bolero and tanggu
In bolero and tanggu combination, make bolero parent of tanggu. Bolero and tanggu can communicate mutually using notifier and plat_data callback APIs. Change-Id: Iecd119df7f0ad1ba225c0427f3f42f217146b092 Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#define BOLERO_VERSION_1_1 0x0002
|
#define BOLERO_VERSION_1_1 0x0002
|
||||||
#define BOLERO_VERSION_1_2 0x0003
|
#define BOLERO_VERSION_1_2 0x0003
|
||||||
#define BOLERO_VERSION_ENTRY_SIZE 32
|
#define BOLERO_VERSION_ENTRY_SIZE 32
|
||||||
|
#define BOLERO_CDC_STRING_LEN 80
|
||||||
|
|
||||||
static struct snd_soc_codec_driver bolero;
|
static struct snd_soc_codec_driver bolero;
|
||||||
|
|
||||||
@@ -118,6 +119,65 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data)
|
||||||
|
{
|
||||||
|
struct bolero_priv *priv = (struct bolero_priv *)handle;
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
pr_err("%s:Invalid bolero priv handle\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case WCD_BOLERO_EVT_RX_MUTE:
|
||||||
|
if (priv->macro_params[RX_MACRO].event_handler)
|
||||||
|
priv->macro_params[RX_MACRO].event_handler(priv->codec,
|
||||||
|
BOLERO_MACRO_EVT_RX_MUTE, data);
|
||||||
|
break;
|
||||||
|
case WCD_BOLERO_EVT_IMPED_TRUE:
|
||||||
|
if (priv->macro_params[RX_MACRO].event_handler)
|
||||||
|
priv->macro_params[RX_MACRO].event_handler(priv->codec,
|
||||||
|
BOLERO_MACRO_EVT_IMPED_TRUE, data);
|
||||||
|
break;
|
||||||
|
case WCD_BOLERO_EVT_IMPED_FALSE:
|
||||||
|
if (priv->macro_params[RX_MACRO].event_handler)
|
||||||
|
priv->macro_params[RX_MACRO].event_handler(priv->codec,
|
||||||
|
BOLERO_MACRO_EVT_IMPED_FALSE, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
|
||||||
|
__func__, event);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bolero_cdc_register_notifier(void *handle,
|
||||||
|
struct notifier_block *nblock,
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
struct bolero_priv *priv = (struct bolero_priv *)handle;
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
pr_err("%s: bolero priv is null\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (enable)
|
||||||
|
return blocking_notifier_chain_register(&priv->notifier,
|
||||||
|
nblock);
|
||||||
|
|
||||||
|
return blocking_notifier_chain_unregister(&priv->notifier,
|
||||||
|
nblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bolero_cdc_notifier_call(struct bolero_priv *priv,
|
||||||
|
u32 data)
|
||||||
|
{
|
||||||
|
dev_dbg(priv->dev, "%s: notifier call, data:%d\n", __func__, data);
|
||||||
|
blocking_notifier_call_chain(&priv->notifier,
|
||||||
|
data, (void *)priv->wcd_dev);
|
||||||
|
}
|
||||||
|
|
||||||
static bool bolero_is_valid_macro_dev(struct device *dev)
|
static bool bolero_is_valid_macro_dev(struct device *dev)
|
||||||
{
|
{
|
||||||
if (of_device_is_compatible(dev->parent->of_node, "qcom,bolero-codec"))
|
if (of_device_is_compatible(dev->parent->of_node, "qcom,bolero-codec"))
|
||||||
@@ -134,6 +194,46 @@ static bool bolero_is_valid_codec_dev(struct device *dev)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bolero_clear_amic_tx_hold - clears AMIC register on analog codec
|
||||||
|
*
|
||||||
|
* @dev: bolero device ptr.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
|
||||||
|
{
|
||||||
|
struct bolero_priv *priv;
|
||||||
|
u16 event;
|
||||||
|
u16 amic = 0;
|
||||||
|
|
||||||
|
if (!dev) {
|
||||||
|
pr_err("%s: dev is null\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bolero_is_valid_codec_dev(dev)) {
|
||||||
|
pr_err("%s: invalid codec\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
priv = dev_get_drvdata(dev);
|
||||||
|
if (!priv) {
|
||||||
|
dev_err(dev, "%s: priv is null\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event = BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR;
|
||||||
|
if (adc_n == BOLERO_ADC0)
|
||||||
|
amic = 0x1;
|
||||||
|
else if (adc_n == BOLERO_ADC2)
|
||||||
|
amic = 0x2;
|
||||||
|
else if (adc_n == BOLERO_ADC3)
|
||||||
|
amic = 0x3;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
bolero_cdc_notifier_call(priv, (amic << 0x10 | event));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(bolero_clear_amic_tx_hold);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bolero_get_device_ptr - Get child or macro device ptr
|
* bolero_get_device_ptr - Get child or macro device ptr
|
||||||
*
|
*
|
||||||
@@ -230,6 +330,7 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
|
|||||||
priv->macro_params[macro_id].num_dais = ops->num_dais;
|
priv->macro_params[macro_id].num_dais = ops->num_dais;
|
||||||
priv->macro_params[macro_id].dai_ptr = ops->dai_ptr;
|
priv->macro_params[macro_id].dai_ptr = ops->dai_ptr;
|
||||||
priv->macro_params[macro_id].mclk_fn = ops->mclk_fn;
|
priv->macro_params[macro_id].mclk_fn = ops->mclk_fn;
|
||||||
|
priv->macro_params[macro_id].event_handler = ops->event_handler;
|
||||||
priv->macro_params[macro_id].dev = dev;
|
priv->macro_params[macro_id].dev = dev;
|
||||||
priv->current_mclk_mux_macro[macro_id] =
|
priv->current_mclk_mux_macro[macro_id] =
|
||||||
bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
|
bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
|
||||||
@@ -237,7 +338,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;
|
||||||
|
|
||||||
if (priv->num_macros_registered == priv->child_num) {
|
if (priv->num_macros_registered == priv->num_macros) {
|
||||||
ret = bolero_copy_dais_from_macro(priv);
|
ret = bolero_copy_dais_from_macro(priv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: copy_dais failed\n", __func__);
|
dev_err(dev, "%s: copy_dais failed\n", __func__);
|
||||||
@@ -290,12 +391,13 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id)
|
|||||||
priv->macro_params[macro_id].num_dais = 0;
|
priv->macro_params[macro_id].num_dais = 0;
|
||||||
priv->macro_params[macro_id].dai_ptr = NULL;
|
priv->macro_params[macro_id].dai_ptr = NULL;
|
||||||
priv->macro_params[macro_id].mclk_fn = NULL;
|
priv->macro_params[macro_id].mclk_fn = NULL;
|
||||||
|
priv->macro_params[macro_id].event_handler = NULL;
|
||||||
priv->macro_params[macro_id].dev = NULL;
|
priv->macro_params[macro_id].dev = NULL;
|
||||||
priv->num_dais -= priv->macro_params[macro_id].num_dais;
|
priv->num_dais -= priv->macro_params[macro_id].num_dais;
|
||||||
priv->num_macros_registered--;
|
priv->num_macros_registered--;
|
||||||
|
|
||||||
/* UNREGISTER CODEC HERE */
|
/* UNREGISTER CODEC HERE */
|
||||||
if (priv->child_num - 1 == priv->num_macros_registered)
|
if (priv->num_macros - 1 == priv->num_macros_registered)
|
||||||
snd_soc_unregister_codec(dev->parent);
|
snd_soc_unregister_codec(dev->parent);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(bolero_unregister_macro);
|
EXPORT_SYMBOL(bolero_unregister_macro);
|
||||||
@@ -555,7 +657,12 @@ static struct snd_soc_codec_driver bolero = {
|
|||||||
static void bolero_add_child_devices(struct work_struct *work)
|
static void bolero_add_child_devices(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct bolero_priv *priv;
|
struct bolero_priv *priv;
|
||||||
int rc;
|
bool wcd937x_node = false;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct device_node *node;
|
||||||
|
int ret = 0, count = 0;
|
||||||
|
struct wcd_ctrl_platform_data *platdata = NULL;
|
||||||
|
char plat_dev_name[BOLERO_CDC_STRING_LEN] = "";
|
||||||
|
|
||||||
priv = container_of(work, struct bolero_priv,
|
priv = container_of(work, struct bolero_priv,
|
||||||
bolero_add_child_devices_work);
|
bolero_add_child_devices_work);
|
||||||
@@ -569,12 +676,53 @@ static void bolero_add_child_devices(struct work_struct *work)
|
|||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rc = of_platform_populate(priv->dev->of_node, NULL, NULL, priv->dev);
|
|
||||||
if (rc)
|
platdata = &priv->plat_data;
|
||||||
dev_err(priv->dev, "%s: failed to add child nodes, rc=%d\n",
|
priv->child_count = 0;
|
||||||
__func__, rc);
|
|
||||||
else
|
for_each_available_child_of_node(priv->dev->of_node, node) {
|
||||||
dev_dbg(priv->dev, "%s: added child node\n", __func__);
|
wcd937x_node = false;
|
||||||
|
if (strnstr(node->name, "wcd937x", strlen("wcd937x")) != NULL)
|
||||||
|
wcd937x_node = true;
|
||||||
|
|
||||||
|
strlcpy(plat_dev_name, node->name,
|
||||||
|
(BOLERO_CDC_STRING_LEN - 1));
|
||||||
|
|
||||||
|
pdev = platform_device_alloc(plat_dev_name, -1);
|
||||||
|
if (!pdev) {
|
||||||
|
dev_err(priv->dev, "%s: pdev memory alloc failed\n",
|
||||||
|
__func__);
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
pdev->dev.parent = priv->dev;
|
||||||
|
pdev->dev.of_node = node;
|
||||||
|
|
||||||
|
if (wcd937x_node) {
|
||||||
|
priv->dev->platform_data = platdata;
|
||||||
|
priv->wcd_dev = &pdev->dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = platform_device_add(pdev);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"%s: Cannot add platform device\n",
|
||||||
|
__func__);
|
||||||
|
platform_device_put(pdev);
|
||||||
|
goto fail_pdev_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->child_count < BOLERO_CDC_CHILD_DEVICES_MAX)
|
||||||
|
priv->pdev_child_devices[priv->child_count++] = pdev;
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
fail_pdev_add:
|
||||||
|
for (count = 0; count < priv->child_count; count++)
|
||||||
|
platform_device_put(priv->pdev_child_devices[count]);
|
||||||
|
err:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bolero_probe(struct platform_device *pdev)
|
static int bolero_probe(struct platform_device *pdev)
|
||||||
@@ -595,11 +743,11 @@ static int bolero_probe(struct platform_device *pdev)
|
|||||||
__func__);
|
__func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
priv->child_num = num_macros;
|
priv->num_macros = num_macros;
|
||||||
if (priv->child_num > MAX_MACRO) {
|
if (priv->num_macros > MAX_MACRO) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s:child_num(%d) > MAX_MACRO(%d) than supported\n",
|
"%s:num_macros(%d) > MAX_MACRO(%d) than supported\n",
|
||||||
__func__, priv->child_num, MAX_MACRO);
|
__func__, priv->num_macros, MAX_MACRO);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
priv->va_without_decimation = of_property_read_bool(pdev->dev.of_node,
|
priv->va_without_decimation = of_property_read_bool(pdev->dev.of_node,
|
||||||
@@ -617,6 +765,10 @@ static int bolero_probe(struct platform_device *pdev)
|
|||||||
priv->read_dev = __bolero_reg_read;
|
priv->read_dev = __bolero_reg_read;
|
||||||
priv->write_dev = __bolero_reg_write;
|
priv->write_dev = __bolero_reg_write;
|
||||||
|
|
||||||
|
priv->plat_data.handle = (void *) priv;
|
||||||
|
priv->plat_data.update_wcd_event = bolero_cdc_update_wcd_event;
|
||||||
|
priv->plat_data.register_notifier = bolero_cdc_register_notifier;
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, priv);
|
dev_set_drvdata(&pdev->dev, priv);
|
||||||
mutex_init(&priv->io_lock);
|
mutex_init(&priv->io_lock);
|
||||||
mutex_init(&priv->clk_lock);
|
mutex_init(&priv->clk_lock);
|
||||||
|
@@ -31,6 +31,20 @@ enum mclk_mux {
|
|||||||
MCLK_MUX_MAX
|
MCLK_MUX_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BOLERO_ADC0 = 1,
|
||||||
|
BOLERO_ADC1,
|
||||||
|
BOLERO_ADC2,
|
||||||
|
BOLERO_ADC3,
|
||||||
|
BOLERO_ADC_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
struct macro_ops {
|
struct macro_ops {
|
||||||
int (*init)(struct snd_soc_codec *codec);
|
int (*init)(struct snd_soc_codec *codec);
|
||||||
int (*exit)(struct snd_soc_codec *codec);
|
int (*exit)(struct snd_soc_codec *codec);
|
||||||
@@ -38,6 +52,8 @@ struct macro_ops {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct snd_soc_dai_driver *dai_ptr;
|
struct snd_soc_dai_driver *dai_ptr;
|
||||||
int (*mclk_fn)(struct device *dev, bool enable);
|
int (*mclk_fn)(struct device *dev, bool enable);
|
||||||
|
int (*event_handler)(struct snd_soc_codec *codec, u16 event,
|
||||||
|
u32 data);
|
||||||
char __iomem *io_base;
|
char __iomem *io_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,6 +68,7 @@ int bolero_request_clock(struct device *dev, u16 macro_id,
|
|||||||
int bolero_info_create_codec_entry(
|
int bolero_info_create_codec_entry(
|
||||||
struct snd_info_entry *codec_root,
|
struct snd_info_entry *codec_root,
|
||||||
struct snd_soc_codec *codec);
|
struct snd_soc_codec *codec);
|
||||||
|
void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n);
|
||||||
#else
|
#else
|
||||||
static inline int bolero_register_macro(struct device *dev,
|
static inline int bolero_register_macro(struct device *dev,
|
||||||
u16 macro_id,
|
u16 macro_id,
|
||||||
@@ -83,5 +100,9 @@ static int bolero_info_create_codec_entry(
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_SND_SOC_BOLERO */
|
#endif /* CONFIG_SND_SOC_BOLERO */
|
||||||
#endif /* BOLERO_CDC_H */
|
#endif /* BOLERO_CDC_H */
|
||||||
|
@@ -15,6 +15,13 @@
|
|||||||
|
|
||||||
#include "bolero-cdc-registers.h"
|
#include "bolero-cdc-registers.h"
|
||||||
|
|
||||||
|
#define BOLERO_CDC_CHILD_DEVICES_MAX 5
|
||||||
|
|
||||||
|
/* from bolero to WCD events */
|
||||||
|
enum {
|
||||||
|
BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
REG_NO_ACCESS,
|
REG_NO_ACCESS,
|
||||||
RD_REG,
|
RD_REG,
|
||||||
@@ -22,6 +29,21 @@ enum {
|
|||||||
RD_WR_REG
|
RD_WR_REG
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* from WCD to bolero events */
|
||||||
|
enum {
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
|
||||||
|
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
|
||||||
|
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wcd_ctrl_platform_data {
|
||||||
|
void *handle;
|
||||||
|
int (*update_wcd_event)(void *handle, u16 event, u32 data);
|
||||||
|
int (*register_notifier)(void *handle,
|
||||||
|
struct notifier_block *nblock,
|
||||||
|
bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
struct bolero_priv {
|
struct bolero_priv {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct snd_soc_codec *codec;
|
struct snd_soc_codec *codec;
|
||||||
@@ -34,7 +56,7 @@ struct bolero_priv {
|
|||||||
struct snd_soc_dai_driver *bolero_dais;
|
struct snd_soc_dai_driver *bolero_dais;
|
||||||
u16 num_dais;
|
u16 num_dais;
|
||||||
u16 num_macros_registered;
|
u16 num_macros_registered;
|
||||||
u16 child_num;
|
u16 num_macros;
|
||||||
u16 current_mclk_mux_macro[MAX_MACRO];
|
u16 current_mclk_mux_macro[MAX_MACRO];
|
||||||
struct work_struct bolero_add_child_devices_work;
|
struct work_struct bolero_add_child_devices_work;
|
||||||
u32 version;
|
u32 version;
|
||||||
@@ -47,6 +69,12 @@ struct bolero_priv {
|
|||||||
u16 macro_id, u16 reg, u8 *val);
|
u16 macro_id, u16 reg, u8 *val);
|
||||||
int (*write_dev)(struct bolero_priv *priv,
|
int (*write_dev)(struct bolero_priv *priv,
|
||||||
u16 macro_id, u16 reg, u8 val);
|
u16 macro_id, u16 reg, u8 val);
|
||||||
|
struct platform_device *pdev_child_devices
|
||||||
|
[BOLERO_CDC_CHILD_DEVICES_MAX];
|
||||||
|
u16 child_count;
|
||||||
|
struct wcd_ctrl_platform_data plat_data;
|
||||||
|
struct device *wcd_dev;
|
||||||
|
struct blocking_notifier_head notifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regmap *bolero_regmap_init(struct device *dev,
|
struct regmap *bolero_regmap_init(struct device *dev,
|
||||||
|
@@ -75,6 +75,107 @@ static const struct snd_kcontrol_new name##_mux = \
|
|||||||
#define RX_MACRO_RX_PATH_OFFSET 0x80
|
#define RX_MACRO_RX_PATH_OFFSET 0x80
|
||||||
#define RX_MACRO_COMP_OFFSET 0x40
|
#define RX_MACRO_COMP_OFFSET 0x40
|
||||||
|
|
||||||
|
#define MAX_IMPED_PARAMS 6
|
||||||
|
|
||||||
|
struct wcd_imped_val {
|
||||||
|
u32 imped_val;
|
||||||
|
u8 index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wcd_imped_val imped_index[] = {
|
||||||
|
{4, 0},
|
||||||
|
{5, 1},
|
||||||
|
{6, 2},
|
||||||
|
{7, 3},
|
||||||
|
{8, 4},
|
||||||
|
{9, 5},
|
||||||
|
{10, 6},
|
||||||
|
{11, 7},
|
||||||
|
{12, 8},
|
||||||
|
{13, 9},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rx_macro_reg_mask_val {
|
||||||
|
u16 reg;
|
||||||
|
u8 mask;
|
||||||
|
u8 val;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rx_macro_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf2},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf2},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf2},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf4},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf4},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf4},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf7},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf7},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf7},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf9},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf9},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf9},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfa},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfa},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfa},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfb},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfb},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfb},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfc},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfc},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfc},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
|
||||||
|
{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
INTERP_HPHL,
|
INTERP_HPHL,
|
||||||
INTERP_HPHR,
|
INTERP_HPHR,
|
||||||
@@ -494,6 +595,80 @@ static struct snd_soc_dai_driver rx_macro_dai[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int get_impedance_index(int imped)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (imped < imped_index[i].imped_val) {
|
||||||
|
pr_debug("%s, detected impedance is less than %d Ohm\n",
|
||||||
|
__func__, imped_index[i].imped_val);
|
||||||
|
i = 0;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
|
||||||
|
pr_debug("%s, detected impedance is greater than %d Ohm\n",
|
||||||
|
__func__,
|
||||||
|
imped_index[ARRAY_SIZE(imped_index) - 1].imped_val);
|
||||||
|
i = ARRAY_SIZE(imped_index) - 1;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
|
||||||
|
if (imped >= imped_index[i].imped_val &&
|
||||||
|
imped < imped_index[i + 1].imped_val)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret:
|
||||||
|
pr_debug("%s: selected impedance index = %d\n",
|
||||||
|
__func__, imped_index[i].index);
|
||||||
|
return imped_index[i].index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rx_macro_wcd_clsh_imped_config -
|
||||||
|
* This function updates HPHL and HPHR gain settings
|
||||||
|
* according to the impedance value.
|
||||||
|
*
|
||||||
|
* @codec: codec pointer handle
|
||||||
|
* @imped: impedance value of HPHL/R
|
||||||
|
* @reset: bool variable to reset registers when teardown
|
||||||
|
*/
|
||||||
|
static void rx_macro_wcd_clsh_imped_config(struct snd_soc_codec *codec,
|
||||||
|
int imped, bool reset)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int index = 0;
|
||||||
|
int table_size;
|
||||||
|
|
||||||
|
static const struct rx_macro_reg_mask_val
|
||||||
|
(*imped_table_ptr)[MAX_IMPED_PARAMS];
|
||||||
|
|
||||||
|
table_size = ARRAY_SIZE(imped_table);
|
||||||
|
imped_table_ptr = imped_table;
|
||||||
|
/* reset = 1, which means request is to reset the register values */
|
||||||
|
if (reset) {
|
||||||
|
for (i = 0; i < MAX_IMPED_PARAMS; i++)
|
||||||
|
snd_soc_update_bits(codec,
|
||||||
|
imped_table_ptr[index][i].reg,
|
||||||
|
imped_table_ptr[index][i].mask, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index = get_impedance_index(imped);
|
||||||
|
if (index >= (ARRAY_SIZE(imped_index) - 1)) {
|
||||||
|
pr_debug("%s, impedance not in range = %d\n", __func__, imped);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (index >= table_size) {
|
||||||
|
pr_debug("%s, impedance index not in range = %d\n", __func__,
|
||||||
|
index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_IMPED_PARAMS; i++)
|
||||||
|
snd_soc_update_bits(codec,
|
||||||
|
imped_table_ptr[index][i].reg,
|
||||||
|
imped_table_ptr[index][i].mask,
|
||||||
|
imped_table_ptr[index][i].val);
|
||||||
|
}
|
||||||
|
|
||||||
static bool rx_macro_get_data(struct snd_soc_codec *codec,
|
static bool rx_macro_get_data(struct snd_soc_codec *codec,
|
||||||
struct device **rx_dev,
|
struct device **rx_dev,
|
||||||
struct rx_macro_priv **rx_priv,
|
struct rx_macro_priv **rx_priv,
|
||||||
@@ -928,6 +1103,37 @@ static int rx_macro_mclk_ctrl(struct device *dev, bool enable)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
|
||||||
|
u32 data)
|
||||||
|
{
|
||||||
|
u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0;
|
||||||
|
struct device *rx_dev = NULL;
|
||||||
|
struct rx_macro_priv *rx_priv = NULL;
|
||||||
|
|
||||||
|
if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case BOLERO_MACRO_EVT_RX_MUTE:
|
||||||
|
rx_idx = data >> 0x10;
|
||||||
|
mute = data & 0xffff;
|
||||||
|
reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + (rx_idx *
|
||||||
|
RX_MACRO_RX_PATH_OFFSET);
|
||||||
|
reg_mix = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL + (rx_idx *
|
||||||
|
RX_MACRO_RX_PATH_OFFSET);
|
||||||
|
snd_soc_update_bits(codec, reg, 0x10, mute << 0x10);
|
||||||
|
snd_soc_update_bits(codec, reg_mix, 0x10, mute << 0x10);
|
||||||
|
break;
|
||||||
|
case BOLERO_MACRO_EVT_IMPED_TRUE:
|
||||||
|
rx_macro_wcd_clsh_imped_config(codec, data, true);
|
||||||
|
break;
|
||||||
|
case BOLERO_MACRO_EVT_IMPED_FALSE:
|
||||||
|
rx_macro_wcd_clsh_imped_config(codec, data, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rx_macro_find_playback_dai_id_for_port(int port_id,
|
static int rx_macro_find_playback_dai_id_for_port(int port_id,
|
||||||
struct rx_macro_priv *rx_priv)
|
struct rx_macro_priv *rx_priv)
|
||||||
{
|
{
|
||||||
@@ -1078,7 +1284,6 @@ static int rx_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
|
|||||||
case SND_SOC_DAPM_POST_PMU:
|
case SND_SOC_DAPM_POST_PMU:
|
||||||
snd_soc_write(codec, gain_reg,
|
snd_soc_write(codec, gain_reg,
|
||||||
snd_soc_read(codec, gain_reg));
|
snd_soc_read(codec, gain_reg));
|
||||||
snd_soc_update_bits(codec, mix_reg, 0x10, 0x00);
|
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_POST_PMD:
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
/* Clk Disable */
|
/* Clk Disable */
|
||||||
@@ -1128,7 +1333,6 @@ static int rx_macro_enable_main_path(struct snd_soc_dapm_widget *w,
|
|||||||
case SND_SOC_DAPM_POST_PMU:
|
case SND_SOC_DAPM_POST_PMU:
|
||||||
snd_soc_write(codec, gain_reg,
|
snd_soc_write(codec, gain_reg,
|
||||||
snd_soc_read(codec, gain_reg));
|
snd_soc_read(codec, gain_reg));
|
||||||
snd_soc_update_bits(codec, reg, 0x10, 0x00);
|
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_POST_PMD:
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
rx_macro_enable_interp_clk(codec, event, w->shift);
|
rx_macro_enable_interp_clk(codec, event, w->shift);
|
||||||
@@ -2955,6 +3159,7 @@ static void rx_macro_init_ops(struct macro_ops *ops, char __iomem *rx_io_base)
|
|||||||
ops->dai_ptr = rx_macro_dai;
|
ops->dai_ptr = rx_macro_dai;
|
||||||
ops->num_dais = ARRAY_SIZE(rx_macro_dai);
|
ops->num_dais = ARRAY_SIZE(rx_macro_dai);
|
||||||
ops->mclk_fn = rx_macro_mclk_ctrl;
|
ops->mclk_fn = rx_macro_mclk_ctrl;
|
||||||
|
ops->event_handler = rx_macro_event_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rx_macro_probe(struct platform_device *pdev)
|
static int rx_macro_probe(struct platform_device *pdev)
|
||||||
|
@@ -42,6 +42,8 @@
|
|||||||
#define TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
|
#define TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
|
||||||
#define TX_MACRO_MCLK_FREQ 9600000
|
#define TX_MACRO_MCLK_FREQ 9600000
|
||||||
#define TX_MACRO_TX_PATH_OFFSET 0x80
|
#define TX_MACRO_TX_PATH_OFFSET 0x80
|
||||||
|
#define TX_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
|
||||||
|
#define TX_MACRO_ADC_MUX_CFG_OFFSET 0x2
|
||||||
|
|
||||||
#define TX_MACRO_TX_UNMUTE_DELAY_MS 40
|
#define TX_MACRO_TX_UNMUTE_DELAY_MS 40
|
||||||
|
|
||||||
@@ -107,6 +109,12 @@ enum {
|
|||||||
TX_MACRO_CLK_DIV_16,
|
TX_MACRO_CLK_DIV_16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSM_DMIC,
|
||||||
|
SWR_MIC,
|
||||||
|
ANC_FB_TUNE1
|
||||||
|
};
|
||||||
|
|
||||||
struct tx_mute_work {
|
struct tx_mute_work {
|
||||||
struct tx_macro_priv *tx_priv;
|
struct tx_macro_priv *tx_priv;
|
||||||
u32 decimator;
|
u32 decimator;
|
||||||
@@ -303,6 +311,7 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
|
|||||||
struct snd_soc_codec *codec = NULL;
|
struct snd_soc_codec *codec = NULL;
|
||||||
u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
|
u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
|
||||||
u8 hpf_cut_off_freq = 0;
|
u8 hpf_cut_off_freq = 0;
|
||||||
|
u16 adc_mux_reg = 0, adc_n = 0, adc_reg = 0;
|
||||||
|
|
||||||
hpf_delayed_work = to_delayed_work(work);
|
hpf_delayed_work = to_delayed_work(work);
|
||||||
hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
|
hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
|
||||||
@@ -318,6 +327,19 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
|
|||||||
dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
|
dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
|
||||||
__func__, hpf_work->decimator, hpf_cut_off_freq);
|
__func__, hpf_work->decimator, hpf_cut_off_freq);
|
||||||
|
|
||||||
|
adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
|
||||||
|
TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
|
||||||
|
if (snd_soc_read(codec, adc_mux_reg) & SWR_MIC) {
|
||||||
|
adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
|
||||||
|
TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
|
||||||
|
adc_n = snd_soc_read(codec, adc_reg) &
|
||||||
|
TX_MACRO_SWR_MIC_MUX_SEL_MASK;
|
||||||
|
if (adc_n >= BOLERO_ADC_MAX)
|
||||||
|
goto tx_hpf_set;
|
||||||
|
/* analog mic clear TX hold */
|
||||||
|
bolero_clear_amic_tx_hold(codec->dev, adc_n);
|
||||||
|
}
|
||||||
|
tx_hpf_set:
|
||||||
snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
|
snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
|
||||||
hpf_cut_off_freq << 5);
|
hpf_cut_off_freq << 5);
|
||||||
snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
|
snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
|
||||||
@@ -399,7 +421,7 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
|
|||||||
__func__, e->reg);
|
__func__, e->reg);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (strnstr(widget->name, "smic", strlen(widget->name))) {
|
if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
if (val < 5)
|
if (val < 5)
|
||||||
snd_soc_update_bits(codec, mic_sel_reg,
|
snd_soc_update_bits(codec, mic_sel_reg,
|
||||||
|
@@ -74,6 +74,14 @@ struct wcd937x_priv {
|
|||||||
rx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
|
rx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
|
||||||
struct regulator_bulk_data *supplies;
|
struct regulator_bulk_data *supplies;
|
||||||
|
|
||||||
|
struct notifier_block nblock;
|
||||||
|
/* wcd callback to bolero */
|
||||||
|
void *handle;
|
||||||
|
int (*update_wcd_event)(void *handle, u16 event, u32 data);
|
||||||
|
int (*register_notifier)(void *handle,
|
||||||
|
struct notifier_block *nblock,
|
||||||
|
bool enable);
|
||||||
|
|
||||||
u32 version;
|
u32 version;
|
||||||
/* Entry for version info */
|
/* Entry for version info */
|
||||||
struct snd_info_entry *entry;
|
struct snd_info_entry *entry;
|
||||||
@@ -99,6 +107,30 @@ struct wcd937x_pdata {
|
|||||||
int num_supplies;
|
int num_supplies;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wcd_ctrl_platform_data {
|
||||||
|
void *handle;
|
||||||
|
int (*update_wcd_event)(void *handle, u16 event, u32 data);
|
||||||
|
int (*register_notifier)(void *handle,
|
||||||
|
struct notifier_block *nblock,
|
||||||
|
bool enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WCD_RX1,
|
||||||
|
WCD_RX2,
|
||||||
|
WCD_RX3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
|
||||||
|
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
|
||||||
|
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* INTR_CTRL_INT_MASK_0 */
|
/* INTR_CTRL_INT_MASK_0 */
|
||||||
WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
|
WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
|
||||||
|
@@ -568,8 +568,16 @@ static int wcd937x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
|
|||||||
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
||||||
wcd937x->rx_swr_dev->dev_num,
|
wcd937x->rx_swr_dev->dev_num,
|
||||||
true);
|
true);
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX2 << 0x10));
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_PRE_PMD:
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX2 << 0x10 | 0x1));
|
||||||
blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
|
blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
|
||||||
WCD_EVENT_PRE_HPHR_PA_OFF,
|
WCD_EVENT_PRE_HPHR_PA_OFF,
|
||||||
&wcd937x->mbhc->wcd_mbhc);
|
&wcd937x->mbhc->wcd_mbhc);
|
||||||
@@ -607,8 +615,16 @@ static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|||||||
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
||||||
wcd937x->rx_swr_dev->dev_num,
|
wcd937x->rx_swr_dev->dev_num,
|
||||||
true);
|
true);
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX1 << 0x10));
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_PRE_PMD:
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX1 << 0x10 | 0x1));
|
||||||
blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
|
blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
|
||||||
WCD_EVENT_PRE_HPHL_PA_OFF,
|
WCD_EVENT_PRE_HPHL_PA_OFF,
|
||||||
&wcd937x->mbhc->wcd_mbhc);
|
&wcd937x->mbhc->wcd_mbhc);
|
||||||
@@ -650,6 +666,16 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
|
|||||||
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
||||||
wcd937x->rx_swr_dev->dev_num,
|
wcd937x->rx_swr_dev->dev_num,
|
||||||
true);
|
true);
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX3 << 0x10));
|
||||||
|
break;
|
||||||
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX3 << 0x10 | 0x1));
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_POST_PMD:
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
usleep_range(1000, 1010);
|
usleep_range(1000, 1010);
|
||||||
@@ -685,6 +711,16 @@ static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|||||||
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
|
||||||
wcd937x->rx_swr_dev->dev_num,
|
wcd937x->rx_swr_dev->dev_num,
|
||||||
true);
|
true);
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX1 << 0x10));
|
||||||
|
break;
|
||||||
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
if (wcd937x->update_wcd_event)
|
||||||
|
wcd937x->update_wcd_event(wcd937x->handle,
|
||||||
|
WCD_BOLERO_EVT_RX_MUTE,
|
||||||
|
(WCD_RX1 << 0x10 | 0x1));
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAPM_POST_PMD:
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
usleep_range(7000, 7010);
|
usleep_range(7000, 7010);
|
||||||
@@ -1180,6 +1216,35 @@ int wcd937x_micbias_control(struct snd_soc_codec *codec,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(wcd937x_micbias_control);
|
EXPORT_SYMBOL(wcd937x_micbias_control);
|
||||||
|
|
||||||
|
static int wcd937x_event_notify(struct notifier_block *block,
|
||||||
|
unsigned long val,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
u16 event = (val & 0xffff);
|
||||||
|
u16 amic = (val >> 0x10);
|
||||||
|
u16 mask = 0x40, reg = 0x0;
|
||||||
|
struct wcd937x_priv *wcd937x = dev_get_drvdata((struct device *)data);
|
||||||
|
struct snd_soc_codec *codec = wcd937x->codec;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR:
|
||||||
|
if (amic == 0x1 || amic == 0x2)
|
||||||
|
reg = WCD937X_ANA_TX_CH2;
|
||||||
|
else if (amic == 0x3)
|
||||||
|
reg = WCD937X_ANA_TX_CH3_HPF;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
if (amic == 0x2)
|
||||||
|
mask = 0x20;
|
||||||
|
snd_soc_update_bits(codec, reg, mask, 0x00);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(codec->dev, "%s: invalid event %d\n", __func__, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
|
static int __wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
|
||||||
int event)
|
int event)
|
||||||
{
|
{
|
||||||
@@ -1443,11 +1508,11 @@ static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
|
|||||||
SND_SOC_DAPM_PGA_E("EAR PGA", WCD937X_ANA_EAR, 7, 0, NULL, 0,
|
SND_SOC_DAPM_PGA_E("EAR PGA", WCD937X_ANA_EAR, 7, 0, NULL, 0,
|
||||||
wcd937x_codec_enable_ear_pa,
|
wcd937x_codec_enable_ear_pa,
|
||||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
||||||
SND_SOC_DAPM_POST_PMD),
|
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
|
||||||
SND_SOC_DAPM_PGA_E("AUX PGA", WCD937X_AUX_AUXPA, 7, 0, NULL, 0,
|
SND_SOC_DAPM_PGA_E("AUX PGA", WCD937X_AUX_AUXPA, 7, 0, NULL, 0,
|
||||||
wcd937x_codec_enable_aux_pa,
|
wcd937x_codec_enable_aux_pa,
|
||||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
||||||
SND_SOC_DAPM_POST_PMD),
|
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
|
||||||
SND_SOC_DAPM_PGA_E("HPHL PGA", WCD937X_ANA_HPH, 7, 0, NULL, 0,
|
SND_SOC_DAPM_PGA_E("HPHL PGA", WCD937X_ANA_HPH, 7, 0, NULL, 0,
|
||||||
wcd937x_codec_enable_hphl_pa,
|
wcd937x_codec_enable_hphl_pa,
|
||||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
||||||
@@ -1754,7 +1819,6 @@ static int wcd937x_soc_codec_probe(struct snd_soc_codec *codec)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
wcd937x->codec = codec;
|
wcd937x->codec = codec;
|
||||||
|
|
||||||
variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x0E) >> 1;
|
variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x0E) >> 1;
|
||||||
wcd937x->variant = variant;
|
wcd937x->variant = variant;
|
||||||
|
|
||||||
@@ -1802,6 +1866,19 @@ static int wcd937x_soc_codec_probe(struct snd_soc_codec *codec)
|
|||||||
snd_soc_dapm_sync(dapm);
|
snd_soc_dapm_sync(dapm);
|
||||||
}
|
}
|
||||||
wcd937x->version = WCD937X_VERSION_1_0;
|
wcd937x->version = WCD937X_VERSION_1_0;
|
||||||
|
/* Register event notifier */
|
||||||
|
wcd937x->nblock.notifier_call = wcd937x_event_notify;
|
||||||
|
if (wcd937x->register_notifier) {
|
||||||
|
ret = wcd937x->register_notifier(wcd937x->handle,
|
||||||
|
&wcd937x->nblock,
|
||||||
|
true);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev,
|
||||||
|
"%s: Failed to register notifier %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_hwdep:
|
err_hwdep:
|
||||||
@@ -1818,6 +1895,10 @@ static int wcd937x_soc_codec_remove(struct snd_soc_codec *codec)
|
|||||||
if (!wcd937x)
|
if (!wcd937x)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (wcd937x->register_notifier)
|
||||||
|
return wcd937x->register_notifier(wcd937x->handle,
|
||||||
|
&wcd937x->nblock,
|
||||||
|
false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1985,6 +2066,7 @@ static int wcd937x_bind(struct device *dev)
|
|||||||
int ret = 0, i = 0;
|
int ret = 0, i = 0;
|
||||||
struct wcd937x_priv *wcd937x = NULL;
|
struct wcd937x_priv *wcd937x = NULL;
|
||||||
struct wcd937x_pdata *pdata = NULL;
|
struct wcd937x_pdata *pdata = NULL;
|
||||||
|
struct wcd_ctrl_platform_data *plat_data = NULL;
|
||||||
|
|
||||||
wcd937x = devm_kzalloc(dev, sizeof(struct wcd937x_priv), GFP_KERNEL);
|
wcd937x = devm_kzalloc(dev, sizeof(struct wcd937x_priv), GFP_KERNEL);
|
||||||
if (!wcd937x)
|
if (!wcd937x)
|
||||||
@@ -2008,6 +2090,30 @@ static int wcd937x_bind(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plat_data = dev_get_platdata(dev->parent);
|
||||||
|
if (!plat_data) {
|
||||||
|
dev_err(dev, "%s: platform data from parent is NULL\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
wcd937x->handle = (void *)plat_data->handle;
|
||||||
|
if (!wcd937x->handle) {
|
||||||
|
dev_err(dev, "%s: handle is NULL\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
wcd937x->update_wcd_event = plat_data->update_wcd_event;
|
||||||
|
if (!wcd937x->update_wcd_event) {
|
||||||
|
dev_err(dev, "%s: update_wcd_event api is null!\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
wcd937x->register_notifier = plat_data->register_notifier;
|
||||||
|
if (!wcd937x->register_notifier) {
|
||||||
|
dev_err(dev, "%s: register_notifier api is null!\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = msm_cdc_enable_static_supplies(dev, wcd937x->supplies,
|
ret = msm_cdc_enable_static_supplies(dev, wcd937x->supplies,
|
||||||
pdata->regulator,
|
pdata->regulator,
|
||||||
pdata->num_supplies);
|
pdata->num_supplies);
|
||||||
|
Reference in New Issue
Block a user