Merge "ASoC: wcd934x-dsp-cntl: Add misc device to control codec dsp"
This commit is contained in:
commit
ddb7835f5f
2 changed files with 127 additions and 2 deletions
|
@ -665,6 +665,12 @@ static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl)
|
||||||
__func__);
|
__func__);
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
goto err_boot;
|
goto err_boot;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Re-initialize the return code to 0, as in success case,
|
||||||
|
* it will hold the remaining time for completion timeout
|
||||||
|
*/
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(codec->dev, "%s: WDSP booted in normal mode\n", __func__);
|
dev_dbg(codec->dev, "%s: WDSP booted in normal mode\n", __func__);
|
||||||
|
@ -877,6 +883,108 @@ static void wcd_cntl_debugfs_remove(struct wcd_dsp_cntl *cntl)
|
||||||
debugfs_remove(cntl->entry);
|
debugfs_remove(cntl->entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wcd_miscdev_release(struct inode *inode, struct file *filep)
|
||||||
|
{
|
||||||
|
struct wcd_dsp_cntl *cntl = container_of(filep->private_data,
|
||||||
|
struct wcd_dsp_cntl, miscdev);
|
||||||
|
if (!cntl->m_dev || !cntl->m_ops ||
|
||||||
|
!cntl->m_ops->vote_for_dsp) {
|
||||||
|
dev_err(cntl->codec->dev,
|
||||||
|
"%s: DSP not ready to boot\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the DSP users goes to zero upon closing dev node */
|
||||||
|
while (cntl->boot_reqs > 0) {
|
||||||
|
cntl->m_ops->vote_for_dsp(cntl->m_dev, false);
|
||||||
|
cntl->boot_reqs--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t wcd_miscdev_write(struct file *filep, const char __user *ubuf,
|
||||||
|
size_t count, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct wcd_dsp_cntl *cntl = container_of(filep->private_data,
|
||||||
|
struct wcd_dsp_cntl, miscdev);
|
||||||
|
char val[count];
|
||||||
|
bool vote;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (count == 0 || count > 2) {
|
||||||
|
pr_err("%s: Invalid count = %zd\n", __func__, count);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = copy_from_user(val, ubuf, count);
|
||||||
|
if (IS_ERR_VALUE(ret)) {
|
||||||
|
dev_err(cntl->codec->dev,
|
||||||
|
"%s: copy_from_user failed, err = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val[0] == '1') {
|
||||||
|
cntl->boot_reqs++;
|
||||||
|
vote = true;
|
||||||
|
} else if (val[0] == '0') {
|
||||||
|
if (cntl->boot_reqs == 0) {
|
||||||
|
dev_err(cntl->codec->dev,
|
||||||
|
"%s: WDSP already disabled\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cntl->boot_reqs--;
|
||||||
|
vote = false;
|
||||||
|
} else {
|
||||||
|
dev_err(cntl->codec->dev, "%s: Invalid value %s\n",
|
||||||
|
__func__, val);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(cntl->codec->dev,
|
||||||
|
"%s: booted = %s, ref_cnt = %d, vote = %s\n",
|
||||||
|
__func__, cntl->is_wdsp_booted ? "true" : "false",
|
||||||
|
cntl->boot_reqs, vote ? "true" : "false");
|
||||||
|
|
||||||
|
if (cntl->m_dev && cntl->m_ops &&
|
||||||
|
cntl->m_ops->vote_for_dsp)
|
||||||
|
ret = cntl->m_ops->vote_for_dsp(cntl->m_dev, vote);
|
||||||
|
else
|
||||||
|
ret = -EINVAL;
|
||||||
|
done:
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
else
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations wcd_miscdev_fops = {
|
||||||
|
.write = wcd_miscdev_write,
|
||||||
|
.release = wcd_miscdev_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int wcd_cntl_miscdev_create(struct wcd_dsp_cntl *cntl)
|
||||||
|
{
|
||||||
|
snprintf(cntl->miscdev_name, ARRAY_SIZE(cntl->miscdev_name),
|
||||||
|
"wcd_dsp%u_control", cntl->dsp_instance);
|
||||||
|
cntl->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||||
|
cntl->miscdev.name = cntl->miscdev_name;
|
||||||
|
cntl->miscdev.fops = &wcd_miscdev_fops;
|
||||||
|
cntl->miscdev.parent = cntl->codec->dev;
|
||||||
|
|
||||||
|
return misc_register(&cntl->miscdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wcd_cntl_miscdev_destroy(struct wcd_dsp_cntl *cntl)
|
||||||
|
{
|
||||||
|
misc_deregister(&cntl->miscdev);
|
||||||
|
}
|
||||||
|
|
||||||
static int wcd_control_init(struct device *dev, void *priv_data)
|
static int wcd_control_init(struct device *dev, void *priv_data)
|
||||||
{
|
{
|
||||||
struct wcd_dsp_cntl *cntl = priv_data;
|
struct wcd_dsp_cntl *cntl = priv_data;
|
||||||
|
@ -1009,13 +1117,20 @@ static int wcd_ctrl_component_bind(struct device *dev,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = wcd_cntl_miscdev_create(cntl);
|
||||||
|
if (IS_ERR_VALUE(ret)) {
|
||||||
|
dev_err(dev, "%s: misc dev register failed, err = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(wcd_cntl_dir_name, WCD_CNTL_DIR_NAME_LEN_MAX,
|
snprintf(wcd_cntl_dir_name, WCD_CNTL_DIR_NAME_LEN_MAX,
|
||||||
"%s%d", "wdsp", cntl->dsp_instance);
|
"%s%d", "wdsp", cntl->dsp_instance);
|
||||||
ret = wcd_cntl_sysfs_init(wcd_cntl_dir_name, cntl);
|
ret = wcd_cntl_sysfs_init(wcd_cntl_dir_name, cntl);
|
||||||
if (IS_ERR_VALUE(ret)) {
|
if (IS_ERR_VALUE(ret)) {
|
||||||
dev_err(dev, "%s: sysfs_init failed, err = %d\n",
|
dev_err(dev, "%s: sysfs_init failed, err = %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
goto done;
|
goto err_sysfs_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcd_cntl_debugfs_init(wcd_cntl_dir_name, cntl);
|
wcd_cntl_debugfs_init(wcd_cntl_dir_name, cntl);
|
||||||
|
@ -1029,7 +1144,7 @@ static int wcd_ctrl_component_bind(struct device *dev,
|
||||||
/* Do not treat this as Fatal error */
|
/* Do not treat this as Fatal error */
|
||||||
dev_err(dev, "%s: Failed to create procfs entry %s\n",
|
dev_err(dev, "%s: Failed to create procfs entry %s\n",
|
||||||
__func__, proc_name);
|
__func__, proc_name);
|
||||||
goto done;
|
goto err_sysfs_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
cntl->ssr_entry.entry = entry;
|
cntl->ssr_entry.entry = entry;
|
||||||
|
@ -1048,6 +1163,10 @@ static int wcd_ctrl_component_bind(struct device *dev,
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
err_sysfs_init:
|
||||||
|
wcd_cntl_miscdev_destroy(cntl);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wcd_ctrl_component_unbind(struct device *dev,
|
static void wcd_ctrl_component_unbind(struct device *dev,
|
||||||
|
@ -1077,6 +1196,8 @@ static void wcd_ctrl_component_unbind(struct device *dev,
|
||||||
/* Remove the debugfs entries */
|
/* Remove the debugfs entries */
|
||||||
wcd_cntl_debugfs_remove(cntl);
|
wcd_cntl_debugfs_remove(cntl);
|
||||||
|
|
||||||
|
/* Remove the misc device */
|
||||||
|
wcd_cntl_miscdev_destroy(cntl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct component_ops wcd_ctrl_component_ops = {
|
static const struct component_ops wcd_ctrl_component_ops = {
|
||||||
|
|
|
@ -105,6 +105,10 @@ struct wcd_dsp_cntl {
|
||||||
/* SSR related */
|
/* SSR related */
|
||||||
struct wdsp_ssr_entry ssr_entry;
|
struct wdsp_ssr_entry ssr_entry;
|
||||||
struct mutex ssr_mutex;
|
struct mutex ssr_mutex;
|
||||||
|
|
||||||
|
/* Misc device related */
|
||||||
|
char miscdev_name[256];
|
||||||
|
struct miscdevice miscdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
void wcd_dsp_cntl_init(struct snd_soc_codec *codec,
|
void wcd_dsp_cntl_init(struct snd_soc_codec *codec,
|
||||||
|
|
Loading…
Add table
Reference in a new issue