asoc: bolero: Add bolero clock changes

Add support for bolero clock changes for
all macros.

Change-Id: Ib7b238ffd9595b6fd2236f4a3d2bcfe545b3c5fb
Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
Laxminath Kasam 2018-05-22 15:45:42 +05:30
parent e562a364d1
commit 2df2d61851
3 changed files with 164 additions and 23 deletions

View File

@ -24,6 +24,14 @@
static struct snd_soc_codec_driver bolero;
/* MCLK_MUX table for all macros */
static u16 bolero_mclk_mux_tbl[MAX_MACRO][MCLK_MUX_MAX] = {
{TX_MACRO, VA_MACRO},
{TX_MACRO, RX_MACRO},
{TX_MACRO, WSA_MACRO},
{TX_MACRO, VA_MACRO},
};
static void bolero_ahb_write_device(char __iomem *io_base,
u16 reg, u8 value)
{
@ -45,24 +53,31 @@ static int __bolero_reg_read(struct bolero_priv *priv,
u16 macro_id, u16 reg, u8 *val)
{
int ret = -EINVAL;
u16 current_mclk_mux_macro;
if (!priv->macro_params[macro_id].mclk_fn) {
mutex_lock(&priv->clk_lock);
current_mclk_mux_macro =
priv->current_mclk_mux_macro[macro_id];
if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
dev_dbg_ratelimited(priv->dev,
"%s: mclk_fn not init for macro-id-%d\n",
__func__, macro_id);
return ret;
"%s: mclk_fn not init for macro-id:%d, current_mclk_mux_macro:%d\n",
__func__, macro_id, current_mclk_mux_macro);
goto err;
}
ret = priv->macro_params[macro_id].mclk_fn(
priv->macro_params[macro_id].dev, true);
ret = priv->macro_params[current_mclk_mux_macro].mclk_fn(
priv->macro_params[current_mclk_mux_macro].dev, true);
if (ret) {
dev_dbg_ratelimited(priv->dev,
"%s: clock enable failed\n", __func__);
return ret;
"%s: clock enable failed for macro-id:%d, current_mclk_mux_macro:%d\n",
__func__, macro_id, current_mclk_mux_macro);
goto err;
}
bolero_ahb_read_device(
priv->macro_params[macro_id].io_base, reg, val);
priv->macro_params[macro_id].mclk_fn(
priv->macro_params[macro_id].dev, false);
priv->macro_params[current_mclk_mux_macro].mclk_fn(
priv->macro_params[current_mclk_mux_macro].dev, false);
err:
mutex_unlock(&priv->clk_lock);
return ret;
}
@ -70,24 +85,31 @@ static int __bolero_reg_write(struct bolero_priv *priv,
u16 macro_id, u16 reg, u8 val)
{
int ret = -EINVAL;
u16 current_mclk_mux_macro;
if (!priv->macro_params[macro_id].mclk_fn) {
mutex_lock(&priv->clk_lock);
current_mclk_mux_macro =
priv->current_mclk_mux_macro[macro_id];
if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
dev_dbg_ratelimited(priv->dev,
"%s: mclk_fn not init for macro-id-%d\n",
__func__, macro_id);
return ret;
"%s: mclk_fn not init for macro-id:%d, current_mclk_mux_macro:%d\n",
__func__, macro_id, current_mclk_mux_macro);
goto err;
}
ret = priv->macro_params[macro_id].mclk_fn(
priv->macro_params[macro_id].dev, true);
ret = priv->macro_params[current_mclk_mux_macro].mclk_fn(
priv->macro_params[current_mclk_mux_macro].dev, true);
if (ret) {
dev_dbg_ratelimited(priv->dev,
"%s: clock enable failed\n", __func__);
return ret;
"%s: clock enable failed for macro-id:%d, current_mclk_mux_macro:%d\n",
__func__, macro_id, current_mclk_mux_macro);
goto err;
}
bolero_ahb_write_device(
priv->macro_params[macro_id].io_base, reg, val);
priv->macro_params[macro_id].mclk_fn(
priv->macro_params[macro_id].dev, false);
priv->macro_params[current_mclk_mux_macro].mclk_fn(
priv->macro_params[current_mclk_mux_macro].dev, false);
err:
mutex_unlock(&priv->clk_lock);
return ret;
}
@ -204,6 +226,8 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
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].dev = dev;
priv->current_mclk_mux_macro[macro_id] =
bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
priv->num_dais += ops->num_dais;
priv->num_macros_registered++;
priv->macros_supported[macro_id] = true;
@ -214,6 +238,12 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
dev_err(dev, "%s: copy_dais failed\n", __func__);
return ret;
}
if (priv->macros_supported[TX_MACRO] == false) {
bolero_mclk_mux_tbl[WSA_MACRO][MCLK_MUX0] = WSA_MACRO;
priv->current_mclk_mux_macro[WSA_MACRO] = WSA_MACRO;
bolero_mclk_mux_tbl[VA_MACRO][MCLK_MUX0] = VA_MACRO;
priv->current_mclk_mux_macro[VA_MACRO] = VA_MACRO;
}
ret = snd_soc_register_codec(dev->parent, &bolero,
priv->bolero_dais, priv->num_dais);
if (ret < 0) {
@ -265,6 +295,100 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id)
}
EXPORT_SYMBOL(bolero_unregister_macro);
/**
* bolero_request_clock - request for clock enable/disable
*
* @dev: macro device ptr.
* @macro_id: ID of macro calling this API.
* @mclk_mux_id: MCLK_MUX ID.
* @enable: enable or disable clock flag
*
* Returns 0 on success or -EINVAL on error.
*/
int bolero_request_clock(struct device *dev, u16 macro_id,
enum mclk_mux mclk_mux_id,
bool enable)
{
struct bolero_priv *priv;
u16 mclk_mux0_macro, mclk_mux1_macro;
int ret = 0;
if (!dev) {
pr_err("%s: dev is null\n", __func__);
return -EINVAL;
}
if (!bolero_is_valid_macro_dev(dev)) {
dev_err(dev, "%s: macro:%d not in valid registered macro-list\n",
__func__, macro_id);
return -EINVAL;
}
priv = dev_get_drvdata(dev->parent);
if (!priv || (macro_id >= MAX_MACRO)) {
dev_err(dev, "%s: priv is null or invalid macro\n", __func__);
return -EINVAL;
}
mclk_mux0_macro = bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
mutex_lock(&priv->clk_lock);
switch (mclk_mux_id) {
case MCLK_MUX0:
ret = priv->macro_params[mclk_mux0_macro].mclk_fn(
priv->macro_params[mclk_mux0_macro].dev, enable);
if (ret < 0) {
dev_err(dev,
"%s: MCLK_MUX0 %s failed for macro:%d, mclk_mux0_macro:%d\n",
__func__,
enable ? "enable" : "disable",
macro_id, mclk_mux0_macro);
goto err;
}
break;
case MCLK_MUX1:
mclk_mux1_macro = bolero_mclk_mux_tbl[macro_id][MCLK_MUX1];
ret = priv->macro_params[mclk_mux0_macro].mclk_fn(
priv->macro_params[mclk_mux0_macro].dev,
true);
if (ret < 0) {
dev_err(dev,
"%s: MCLK_MUX0 en failed for macro:%d mclk_mux0_macro:%d\n",
__func__, macro_id, mclk_mux0_macro);
goto err;
}
ret = priv->macro_params[mclk_mux1_macro].mclk_fn(
priv->macro_params[mclk_mux1_macro].dev, enable);
if (ret < 0) {
dev_err(dev,
"%s: MCLK_MUX1 %s failed for macro:%d, mclk_mux1_macro:%d\n",
__func__,
enable ? "enable" : "disable",
macro_id, mclk_mux1_macro);
priv->macro_params[mclk_mux0_macro].mclk_fn(
priv->macro_params[mclk_mux0_macro].dev,
false);
goto err;
}
priv->macro_params[mclk_mux0_macro].mclk_fn(
priv->macro_params[mclk_mux0_macro].dev,
false);
break;
case MCLK_MUX_MAX:
default:
dev_err(dev, "%s: invalid mclk_mux_id: %d\n",
__func__, mclk_mux_id);
ret = -EINVAL;
goto err;
}
if (enable)
priv->current_mclk_mux_macro[macro_id] =
bolero_mclk_mux_tbl[macro_id][mclk_mux_id];
else
priv->current_mclk_mux_macro[macro_id] =
bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
err:
mutex_unlock(&priv->clk_lock);
return ret;
}
EXPORT_SYMBOL(bolero_request_clock);
static int bolero_soc_codec_probe(struct snd_soc_codec *codec)
{
struct bolero_priv *priv = dev_get_drvdata(codec->dev);
@ -359,8 +483,6 @@ static void bolero_add_child_devices(struct work_struct *work)
fail_pdev_add:
for (i = cnt; i > 0; i--)
platform_device_put(priv->pdev_child_devices[i - 1]);
err:
return;
}
static int bolero_probe(struct platform_device *pdev)
@ -405,6 +527,7 @@ static int bolero_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, priv);
mutex_init(&priv->io_lock);
mutex_init(&priv->clk_lock);
INIT_WORK(&priv->bolero_add_child_devices_work,
bolero_add_child_devices);
schedule_work(&priv->bolero_add_child_devices_work);
@ -420,6 +543,7 @@ static int bolero_remove(struct platform_device *pdev)
for (i = priv->child_num; i > 0; i--)
platform_device_unregister(priv->pdev_child_devices[i - 1]);
mutex_destroy(&priv->io_lock);
mutex_destroy(&priv->clk_lock);
return 0;
}

View File

@ -25,6 +25,12 @@ enum {
MAX_MACRO
};
enum mclk_mux {
MCLK_MUX0,
MCLK_MUX1,
MCLK_MUX_MAX
};
struct macro_ops {
int (*init)(struct snd_soc_codec *codec);
int (*exit)(struct snd_soc_codec *codec);
@ -40,6 +46,9 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
struct macro_ops *ops);
void bolero_unregister_macro(struct device *dev, u16 macro_id);
struct device *bolero_get_device_ptr(struct device *dev, u16 macro_id);
int bolero_request_clock(struct device *dev, u16 macro_id,
enum mclk_mux mclk_mux_id,
bool enable);
#else
static inline int bolero_register_macro(struct device *dev,
u16 macro_id,
@ -53,9 +62,15 @@ static inline void bolero_unregister_macro(struct device *dev, u16 macro_id)
}
static inline struct device *bolero_get_device_ptr(struct device *dev,
u16 macro_id)
u16 macro_id)
{
return NULL;
}
static inline int bolero_request_clock(struct device *dev, u16 macro_id,
enum mclk_mux mclk_mux_id,
bool enable)
{
return 0;
}
#endif /* CONFIG_SND_SOC_BOLERO */
#endif /* BOLERO_CDC_H */

View File

@ -27,6 +27,7 @@ struct bolero_priv {
struct snd_soc_codec *codec;
struct regmap *regmap;
struct mutex io_lock;
struct mutex clk_lock;
bool va_without_decimation;
bool macros_supported[MAX_MACRO];
struct macro_ops macro_params[MAX_MACRO];
@ -34,6 +35,7 @@ struct bolero_priv {
u16 num_dais;
u16 num_macros_registered;
u16 child_num;
u16 current_mclk_mux_macro[MAX_MACRO];
struct platform_device *pdev_child_devices[MAX_MACRO];
struct work_struct bolero_add_child_devices_work;