asoc: Expose a sysfs node to notify device open/close.
Add support in kona machine driver to expose a sysfs node. Userspace uses this sysfs node to notify machine driver on which dai-link ( pcm id) is opened/closed. This information regarding device open/close is then compared against shutdown/ startup dai_link ops. If there is a mismatch we conclude that there has been a userspace service crash and we issue a close all session command to dsp and also clear all the dma buffers which were allocated by the service. Change-Id: I4fc13adf8cc527c87b822a3b189d4ff081539a3c Signed-off-by: Ashish Jain <ashishj@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
4adf995c01
commit
de3e09d08d
57
asoc/kona.c
57
asoc/kona.c
@@ -34,6 +34,7 @@
|
|||||||
#include "codecs/bolero/wsa-macro.h"
|
#include "codecs/bolero/wsa-macro.h"
|
||||||
#include "kona-port-config.h"
|
#include "kona-port-config.h"
|
||||||
#include "msm-audio-defs.h"
|
#include "msm-audio-defs.h"
|
||||||
|
#include "msm_common.h"
|
||||||
|
|
||||||
#define DRV_NAME "kona-asoc-snd"
|
#define DRV_NAME "kona-asoc-snd"
|
||||||
#define __CHIPSET__ "KONA "
|
#define __CHIPSET__ "KONA "
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
|
|
||||||
struct msm_asoc_mach_data {
|
struct msm_asoc_mach_data {
|
||||||
struct snd_info_entry *codec_root;
|
struct snd_info_entry *codec_root;
|
||||||
|
struct msm_common_pdata *common_pdata;
|
||||||
int lito_v2_enabled;
|
int lito_v2_enabled;
|
||||||
struct device_node *dmic01_gpio_p; /* used by pinctrl API */
|
struct device_node *dmic01_gpio_p; /* used by pinctrl API */
|
||||||
struct device_node *dmic23_gpio_p; /* used by pinctrl API */
|
struct device_node *dmic23_gpio_p; /* used by pinctrl API */
|
||||||
@@ -413,6 +415,11 @@ static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
|
|||||||
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
|
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct snd_soc_ops msm_common_be_ops = {
|
||||||
|
.startup = msm_common_snd_startup,
|
||||||
|
.shutdown = msm_common_snd_shutdown,
|
||||||
|
};
|
||||||
|
|
||||||
/* 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[] = {
|
||||||
{
|
{
|
||||||
@@ -426,6 +433,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
.codec_dai_name = "wsa_macro_rx1",
|
.codec_dai_name = "wsa_macro_rx1",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
.init = &msm_int_audrx_init,
|
.init = &msm_int_audrx_init,
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -441,6 +449,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "wsa_macro_rx_mix",
|
.codec_dai_name = "wsa_macro_rx_mix",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -456,6 +465,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "wsa_macro_echo",
|
.codec_dai_name = "wsa_macro_echo",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -471,6 +481,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "rx_macro_rx1",
|
.codec_dai_name = "rx_macro_rx1",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -486,6 +497,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "rx_macro_rx2",
|
.codec_dai_name = "rx_macro_rx2",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -501,6 +513,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "rx_macro_rx3",
|
.codec_dai_name = "rx_macro_rx3",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -516,6 +529,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "rx_macro_rx4",
|
.codec_dai_name = "rx_macro_rx4",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -531,6 +545,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "tx_macro_tx1",
|
.codec_dai_name = "tx_macro_tx1",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -546,6 +561,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "tx_macro_tx2",
|
.codec_dai_name = "tx_macro_tx2",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -561,6 +577,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "va_macro_tx1",
|
.codec_dai_name = "va_macro_tx1",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -576,6 +593,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "va_macro_tx2",
|
.codec_dai_name = "va_macro_tx2",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -591,6 +609,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_dai_name = "va_macro_tx3",
|
.codec_dai_name = "va_macro_tx3",
|
||||||
.codec_name = "bolero_codec",
|
.codec_name = "bolero_codec",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
.be_hw_params_fixup = msm_be_hw_params_fixup,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -605,6 +624,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_name = "btfmslim_slave",
|
.codec_name = "btfmslim_slave",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
|
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
/* this dainlink has playback support */
|
/* this dainlink has playback support */
|
||||||
@@ -619,6 +639,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.codec_name = "btfmslim_slave",
|
.codec_name = "btfmslim_slave",
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
.codec_dai_name = "btfm_bt_sco_slim_tx",
|
.codec_dai_name = "btfm_bt_sco_slim_tx",
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
.ignore_pmdown_time = 1,
|
.ignore_pmdown_time = 1,
|
||||||
@@ -636,6 +657,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.ignore_pmdown_time = 1,
|
.ignore_pmdown_time = 1,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = LPASS_BE_USB_AUDIO_RX,
|
.name = LPASS_BE_USB_AUDIO_RX,
|
||||||
@@ -649,6 +671,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.ignore_pmdown_time = 1,
|
.ignore_pmdown_time = 1,
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = LPASS_BE_USB_AUDIO_TX,
|
.name = LPASS_BE_USB_AUDIO_TX,
|
||||||
@@ -661,6 +684,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
|
|||||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
||||||
SND_SOC_DPCM_TRIGGER_POST},
|
SND_SOC_DPCM_TRIGGER_POST},
|
||||||
.ignore_suspend = 1,
|
.ignore_suspend = 1,
|
||||||
|
.ops = &msm_common_be_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1346,6 +1370,27 @@ static int msm_audio_ssr_register(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card)
|
||||||
|
{
|
||||||
|
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
||||||
|
|
||||||
|
if (!pdata)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pdata->common_pdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_common_set_pdata(struct snd_soc_card *card,
|
||||||
|
struct msm_common_pdata *common_pdata)
|
||||||
|
{
|
||||||
|
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
||||||
|
|
||||||
|
if (!pdata)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pdata->common_pdata = common_pdata;
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_asoc_machine_probe(struct platform_device *pdev)
|
static int msm_asoc_machine_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct snd_soc_card *card = NULL;
|
struct snd_soc_card *card = NULL;
|
||||||
@@ -1415,6 +1460,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|||||||
dev_info(&pdev->dev, "%s: Sound card %s registered\n",
|
dev_info(&pdev->dev, "%s: Sound card %s registered\n",
|
||||||
__func__, card->name);
|
__func__, card->name);
|
||||||
|
|
||||||
|
msm_common_snd_init(pdev, card);
|
||||||
|
|
||||||
pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
|
pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
|
||||||
"qcom,hph-en1-gpio", 0);
|
"qcom,hph-en1-gpio", 0);
|
||||||
if (!pdata->hph_en1_gpio_p) {
|
if (!pdata->hph_en1_gpio_p) {
|
||||||
@@ -1510,6 +1557,16 @@ err:
|
|||||||
static int msm_asoc_machine_remove(struct platform_device *pdev)
|
static int msm_asoc_machine_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||||
|
struct msm_asoc_mach_data *pdata = NULL;
|
||||||
|
struct msm_common_pdata *common_pdata = NULL;
|
||||||
|
|
||||||
|
if (card)
|
||||||
|
pdata = snd_soc_card_get_drvdata(card);
|
||||||
|
|
||||||
|
if (pdata)
|
||||||
|
common_pdata = pdata->common_pdata;
|
||||||
|
|
||||||
|
msm_common_snd_deinit(common_pdata);
|
||||||
|
|
||||||
snd_event_master_deregister(&pdev->dev);
|
snd_event_master_deregister(&pdev->dev);
|
||||||
snd_soc_unregister_card(card);
|
snd_soc_unregister_card(card);
|
||||||
|
@@ -15,9 +15,116 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include "asoc/msm-cdc-pinctrl.h"
|
#include <asoc/msm-cdc-pinctrl.h>
|
||||||
|
#include <dsp/gecko-core.h>
|
||||||
|
#include <dsp/msm_audio_ion.h>
|
||||||
#include "msm_common.h"
|
#include "msm_common.h"
|
||||||
|
|
||||||
|
#define to_asoc_mach_common_pdata(kobj) \
|
||||||
|
container_of((kobj), struct msm_common_pdata, aud_dev_kobj)
|
||||||
|
|
||||||
|
#define DEVICE_ENABLE 1
|
||||||
|
#define DEVICE_DISABLE 0
|
||||||
|
|
||||||
|
static struct attribute device_state_attr = {
|
||||||
|
.name = "state",
|
||||||
|
.mode = 0660,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_USR_INPUT 10
|
||||||
|
|
||||||
|
static ssize_t aud_dev_sysfs_store(struct kobject *kobj,
|
||||||
|
struct attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
ssize_t ret = -EINVAL;
|
||||||
|
struct msm_common_pdata *pdata = to_asoc_mach_common_pdata(kobj);
|
||||||
|
uint32_t pcm_id, state = 0;
|
||||||
|
|
||||||
|
if (count > MAX_USR_INPUT) {
|
||||||
|
pr_err("%s: invalid string written", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscanf(buf, "%d %d", &pcm_id, &state);
|
||||||
|
|
||||||
|
if ((pcm_id > pdata->num_aud_devs) || (pcm_id < 0)) {
|
||||||
|
pr_err("%s: invalid pcm id %d \n", __func__, pcm_id);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((state > DEVICE_ENABLE) || (state < DEVICE_DISABLE)) {
|
||||||
|
pr_err("%s: invalid state %d \n", __func__, state);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
pr_info("%s: pcm_id %d state %d \n", __func__, pcm_id, state);
|
||||||
|
|
||||||
|
pdata->aud_dev_state[pcm_id] = state;
|
||||||
|
if ( state == DEVICE_ENABLE && (pdata->dsp_sessions_closed != 0))
|
||||||
|
pdata->dsp_sessions_closed = 0;
|
||||||
|
|
||||||
|
ret = count;
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sysfs_ops aud_dev_sysfs_ops = {
|
||||||
|
.store = aud_dev_sysfs_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct kobj_type aud_dev_ktype = {
|
||||||
|
.sysfs_ops = &aud_dev_sysfs_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int aud_dev_sysfs_init(struct msm_common_pdata *pdata)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
char dir[10] = "aud_dev";
|
||||||
|
|
||||||
|
ret = kobject_init_and_add(&pdata->aud_dev_kobj, &aud_dev_ktype,
|
||||||
|
kernel_kobj, dir);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s: Failed to add kobject %s, err = %d\n",
|
||||||
|
__func__, dir, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sysfs_create_file(&pdata->aud_dev_kobj, &device_state_attr);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s: Failed to add wdsp_boot sysfs entry to %s\n",
|
||||||
|
__func__, dir);
|
||||||
|
goto fail_create_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail_create_file:
|
||||||
|
kobject_put(&pdata->aud_dev_kobj);
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_userspace_service_state(struct snd_soc_pcm_runtime *rtd,
|
||||||
|
struct msm_common_pdata *pdata)
|
||||||
|
{
|
||||||
|
dev_info(rtd->card->dev,"%s: pcm_id %d state %d\n", __func__,
|
||||||
|
rtd->num, pdata->aud_dev_state[rtd->num]);
|
||||||
|
|
||||||
|
if (pdata->aud_dev_state[rtd->num] == DEVICE_ENABLE) {
|
||||||
|
dev_info(rtd->card->dev, "%s userspace service crashed\n",
|
||||||
|
__func__);
|
||||||
|
if (pdata->dsp_sessions_closed == 0) {
|
||||||
|
/*Issue close all graph cmd to DSP*/
|
||||||
|
gecko_core_apm_close_all();
|
||||||
|
/*unmap all dma mapped buffers*/
|
||||||
|
msm_audio_ion_crash_handler();
|
||||||
|
pdata->dsp_sessions_closed = 1;
|
||||||
|
}
|
||||||
|
/*Reset the state as sysfs node wont be triggred*/
|
||||||
|
pdata->aud_dev_state[rtd->num] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int get_intf_index(const char *stream_name)
|
static int get_intf_index(const char *stream_name)
|
||||||
{
|
{
|
||||||
if (strnstr(stream_name, "PRIMARY", strlen("PRIMARY")))
|
if (strnstr(stream_name, "PRIMARY", strlen("PRIMARY")))
|
||||||
@@ -54,27 +161,23 @@ int msm_common_snd_startup(struct snd_pcm_substream *substream)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < 0) {
|
if (index >= 0) {
|
||||||
dev_err(rtd->card->dev,
|
mutex_lock(&pdata->lock[index]);
|
||||||
"%s: Invalid Backend interface %d\n", __func__, index);
|
if (pdata->mi2s_gpio_p[index]) {
|
||||||
return -EINVAL;
|
if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) {
|
||||||
}
|
ret = msm_cdc_pinctrl_select_active_state(
|
||||||
|
pdata->mi2s_gpio_p[index]);
|
||||||
mutex_lock(&pdata->lock[index]);
|
if (ret) {
|
||||||
if (pdata->mi2s_gpio_p[index]) {
|
pr_err("%s:pinctrl set actve fail with %d\n",
|
||||||
if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) {
|
__func__, ret);
|
||||||
ret = msm_cdc_pinctrl_select_active_state(
|
goto done;
|
||||||
pdata->mi2s_gpio_p[index]);
|
}
|
||||||
if (ret) {
|
|
||||||
pr_err("%s: GPIO pinctrl set active failed with %d\n",
|
|
||||||
__func__, ret);
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index]));
|
||||||
}
|
}
|
||||||
atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index]));
|
|
||||||
}
|
|
||||||
done:
|
done:
|
||||||
mutex_unlock(&pdata->lock[index]);
|
mutex_unlock(&pdata->lock[index]);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,24 +198,23 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < 0) {
|
check_userspace_service_state(rtd, pdata);
|
||||||
dev_err(card->dev,
|
|
||||||
"%s: Invalid Backend interface %d\n", __func__, index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&pdata->lock[index]);
|
if (index >= 0) {
|
||||||
if (pdata->mi2s_gpio_p[index]) {
|
mutex_lock(&pdata->lock[index]);
|
||||||
atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]);
|
if (pdata->mi2s_gpio_p[index]) {
|
||||||
if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) {
|
atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]);
|
||||||
ret = msm_cdc_pinctrl_select_active_state(
|
if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) {
|
||||||
pdata->mi2s_gpio_p[index]);
|
ret = msm_cdc_pinctrl_select_active_state(
|
||||||
if (ret)
|
pdata->mi2s_gpio_p[index]);
|
||||||
dev_err(card->dev, "%s: GPIO pinctrl set active failed with %d\n",
|
if (ret)
|
||||||
__func__, ret);
|
dev_err(card->dev,
|
||||||
|
"%s: pinctrl set actv fail %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&pdata->lock[index]);
|
||||||
}
|
}
|
||||||
mutex_unlock(&pdata->lock[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
||||||
@@ -141,6 +243,12 @@ int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
|||||||
"qcom,quin-mi2s-gpios", 0);
|
"qcom,quin-mi2s-gpios", 0);
|
||||||
common_pdata->mi2s_gpio_p[SEN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
common_pdata->mi2s_gpio_p[SEN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
"qcom,sen-mi2s-gpios", 0);
|
"qcom,sen-mi2s-gpios", 0);
|
||||||
|
common_pdata->aud_dev_state = devm_kcalloc(&pdev->dev, card->num_links,
|
||||||
|
sizeof(uint8_t), GFP_KERNEL);
|
||||||
|
dev_info(&pdev->dev, "num_links %d \n", card->num_links);
|
||||||
|
common_pdata->num_aud_devs = card->num_links;
|
||||||
|
|
||||||
|
aud_dev_sysfs_init(common_pdata);
|
||||||
|
|
||||||
msm_common_set_pdata(card, common_pdata);
|
msm_common_set_pdata(card, common_pdata);
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -32,6 +32,10 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msm_common_pdata {
|
struct msm_common_pdata {
|
||||||
|
uint8_t *aud_dev_state;
|
||||||
|
struct kobject aud_dev_kobj;
|
||||||
|
uint8_t dsp_sessions_closed;
|
||||||
|
uint32_t num_aud_devs;
|
||||||
struct device_node *mi2s_gpio_p[MI2S_TDM_AUXPCM_MAX];
|
struct device_node *mi2s_gpio_p[MI2S_TDM_AUXPCM_MAX];
|
||||||
struct mutex lock[MI2S_TDM_AUXPCM_MAX];
|
struct mutex lock[MI2S_TDM_AUXPCM_MAX];
|
||||||
atomic_t mi2s_gpio_ref_cnt[MI2S_TDM_AUXPCM_MAX];
|
atomic_t mi2s_gpio_ref_cnt[MI2S_TDM_AUXPCM_MAX];
|
||||||
|
142
dsp/gecko-core.c
142
dsp/gecko-core.c
@@ -25,6 +25,7 @@
|
|||||||
#define APM_STATE_READY_TIMEOUT_MS 10000
|
#define APM_STATE_READY_TIMEOUT_MS 10000
|
||||||
#define Q6_READY_TIMEOUT_MS 1000
|
#define Q6_READY_TIMEOUT_MS 1000
|
||||||
#define APM_CMD_GET_GECKO_STATE 0x01001021
|
#define APM_CMD_GET_GECKO_STATE 0x01001021
|
||||||
|
#define APM_CMD_CLOSE_ALL 0x01001013
|
||||||
#define APM_CMD_RSP_GET_GECKO_STATE 0x02001007
|
#define APM_CMD_RSP_GET_GECKO_STATE 0x02001007
|
||||||
#define APM_MODULE_INSTANCE_ID 0x00000001
|
#define APM_MODULE_INSTANCE_ID 0x00000001
|
||||||
#define GPR_SVC_ADSP_CORE 0x3
|
#define GPR_SVC_ADSP_CORE 0x3
|
||||||
@@ -34,7 +35,7 @@ struct gecko_core {
|
|||||||
wait_queue_head_t wait;
|
wait_queue_head_t wait;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
bool resp_received;
|
bool resp_received;
|
||||||
bool is_ready;
|
int32_t status;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gecko_core_private {
|
struct gecko_core_private {
|
||||||
@@ -46,6 +47,13 @@ struct gecko_core_private {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct gecko_core_private *gecko_core_priv;
|
static struct gecko_core_private *gecko_core_priv;
|
||||||
|
|
||||||
|
/* used to decode basic responses from Gecko */
|
||||||
|
struct gecko_cmd_basic_rsp {
|
||||||
|
uint32_t opcode;
|
||||||
|
int32_t status;
|
||||||
|
};
|
||||||
|
|
||||||
struct apm_cmd_rsp_get_gecko_status_t
|
struct apm_cmd_rsp_get_gecko_status_t
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -61,20 +69,34 @@ struct apm_cmd_rsp_get_gecko_status_t
|
|||||||
static int gecko_core_callback(struct gpr_device *adev, void *data)
|
static int gecko_core_callback(struct gpr_device *adev, void *data)
|
||||||
{
|
{
|
||||||
struct gecko_core *core = dev_get_drvdata(&adev->dev);
|
struct gecko_core *core = dev_get_drvdata(&adev->dev);
|
||||||
struct apm_cmd_rsp_get_gecko_status_t *result;
|
struct apm_cmd_rsp_get_gecko_status_t *gecko_status_rsp;
|
||||||
|
struct gecko_cmd_basic_rsp *basic_rsp;
|
||||||
struct gpr_hdr *hdr = data;
|
struct gpr_hdr *hdr = data;
|
||||||
|
|
||||||
result = GPR_PKT_GET_PAYLOAD(struct apm_cmd_rsp_get_gecko_status_t, data);
|
|
||||||
|
|
||||||
dev_err(&adev->dev ,"%s: Payload %x",__func__, hdr->opcode);
|
dev_info(&adev->dev ,"%s: Payload %x",__func__, hdr->opcode);
|
||||||
switch (hdr->opcode) {
|
switch (hdr->opcode) {
|
||||||
case GPR_IBASIC_RSP_RESULT:
|
case GPR_IBASIC_RSP_RESULT:
|
||||||
dev_err(&adev->dev ,"%s: Failed response received",__func__);
|
basic_rsp = GPR_PKT_GET_PAYLOAD(
|
||||||
|
struct gecko_cmd_basic_rsp,
|
||||||
|
data);
|
||||||
|
dev_info(&adev->dev ,"%s: op %x status %d", __func__,
|
||||||
|
basic_rsp->opcode, basic_rsp->status);
|
||||||
|
if (basic_rsp->opcode == APM_CMD_CLOSE_ALL) {
|
||||||
|
core->status = basic_rsp->status;
|
||||||
|
} else {
|
||||||
|
dev_err(&adev->dev ,"%s: Failed response received",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
core->resp_received = true;
|
core->resp_received = true;
|
||||||
break;
|
break;
|
||||||
case APM_CMD_RSP_GET_GECKO_STATE:
|
case APM_CMD_RSP_GET_GECKO_STATE:
|
||||||
dev_err(&adev->dev ,"%s: sucess response received",__func__);
|
gecko_status_rsp =
|
||||||
core->is_ready = result->status;
|
GPR_PKT_GET_PAYLOAD(
|
||||||
|
struct apm_cmd_rsp_get_gecko_status_t,
|
||||||
|
data);
|
||||||
|
dev_info(&adev->dev ,"%s: sucess response received",__func__);
|
||||||
|
core->status = gecko_status_rsp->status;
|
||||||
core->resp_received = true;
|
core->resp_received = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -93,12 +115,12 @@ static bool __gecko_core_is_apm_ready(struct gecko_core *core)
|
|||||||
struct gpr_device *adev = core->adev;
|
struct gpr_device *adev = core->adev;
|
||||||
struct gpr_pkt pkt;
|
struct gpr_pkt pkt;
|
||||||
int rc;
|
int rc;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
||||||
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
|
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
|
||||||
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, GPR_PKT_HEADER_BYTE_SIZE_V);
|
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, GPR_PKT_HEADER_BYTE_SIZE_V);
|
||||||
|
|
||||||
pkt.hdr.opcode = APM_CMD_GET_GECKO_STATE;
|
|
||||||
pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
|
pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
|
||||||
pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
|
pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
|
||||||
pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
||||||
@@ -108,31 +130,30 @@ static bool __gecko_core_is_apm_ready(struct gecko_core *core)
|
|||||||
dev_err(gecko_core_priv->dev, "%s: send_command ret\n", __func__);
|
dev_err(gecko_core_priv->dev, "%s: send_command ret\n", __func__);
|
||||||
|
|
||||||
rc = gpr_send_pkt(adev, &pkt);
|
rc = gpr_send_pkt(adev, &pkt);
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
return false;
|
ret = false;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
rc = wait_event_timeout(core->wait, (core->resp_received),
|
rc = wait_event_timeout(core->wait, (core->resp_received),
|
||||||
msecs_to_jiffies(Q6_READY_TIMEOUT_MS));
|
msecs_to_jiffies(Q6_READY_TIMEOUT_MS));
|
||||||
dev_err(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__);
|
dev_dbg(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__);
|
||||||
// core->resp_received = true;
|
|
||||||
// core->is_ready = true;
|
|
||||||
if (rc > 0 && core->resp_received) {
|
|
||||||
core->resp_received = false;
|
|
||||||
|
|
||||||
if (core->is_ready)
|
if (rc > 0 && core->resp_received) {
|
||||||
return true;
|
ret = core->status;
|
||||||
} else {
|
} else {
|
||||||
dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n",
|
dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n",
|
||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
return false;
|
core->resp_received = false;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gecko_core_is_apm_ready() - Get status of adsp
|
* gecko_core_is_apm_ready() - Get status of adsp
|
||||||
*
|
*
|
||||||
* Return: Will be an true if apm is ready and false if not.
|
* Return: Will return true if apm is ready and false if not.
|
||||||
*/
|
*/
|
||||||
bool gecko_core_is_apm_ready(void)
|
bool gecko_core_is_apm_ready(void)
|
||||||
{
|
{
|
||||||
@@ -141,14 +162,15 @@ bool gecko_core_is_apm_ready(void)
|
|||||||
struct gecko_core *core;
|
struct gecko_core *core;
|
||||||
|
|
||||||
if (!gecko_core_priv)
|
if (!gecko_core_priv)
|
||||||
return 0;
|
return ret;
|
||||||
|
|
||||||
|
mutex_lock(&gecko_core_priv->lock);
|
||||||
core = gecko_core_priv->gecko_core_drv;
|
core = gecko_core_priv->gecko_core_drv;
|
||||||
if (!core)
|
if (!core)
|
||||||
return 0;
|
goto done;
|
||||||
|
|
||||||
mutex_lock(&core->lock);
|
|
||||||
timeout = jiffies + msecs_to_jiffies(APM_STATE_READY_TIMEOUT_MS);
|
timeout = jiffies + msecs_to_jiffies(APM_STATE_READY_TIMEOUT_MS);
|
||||||
|
mutex_lock(&core->lock);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (__gecko_core_is_apm_ready(core)) {
|
if (__gecko_core_is_apm_ready(core)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
@@ -162,10 +184,80 @@ bool gecko_core_is_apm_ready(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&core->lock);
|
mutex_unlock(&core->lock);
|
||||||
|
done:
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gecko_core_is_apm_ready);
|
EXPORT_SYMBOL_GPL(gecko_core_is_apm_ready);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gecko_core_apm_close_all() - Get status of adsp
|
||||||
|
*
|
||||||
|
* Return: Will be return true if apm is ready and false if not.
|
||||||
|
*/
|
||||||
|
void gecko_core_apm_close_all(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct gecko_core *core;
|
||||||
|
struct gpr_pkt pkt;
|
||||||
|
struct gpr_device *adev = NULL;
|
||||||
|
|
||||||
|
if (!gecko_core_priv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&gecko_core_priv->lock);
|
||||||
|
core = gecko_core_priv->gecko_core_drv;
|
||||||
|
if (!core) {
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&core->lock);
|
||||||
|
|
||||||
|
adev = core->adev;
|
||||||
|
|
||||||
|
pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE,
|
||||||
|
GPR_PKT_HEADER_WORD_SIZE_V) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE,
|
||||||
|
GPR_PKT_HEADER_BYTE_SIZE_V);
|
||||||
|
|
||||||
|
pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
|
||||||
|
pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
|
||||||
|
pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
||||||
|
pkt.hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
|
||||||
|
pkt.hdr.opcode = APM_CMD_CLOSE_ALL;
|
||||||
|
|
||||||
|
dev_info(gecko_core_priv->dev, "%s: send_command \n", __func__);
|
||||||
|
|
||||||
|
rc = gpr_send_pkt(adev, &pkt);
|
||||||
|
if (rc < 0) {
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: send_pkt_failed %d\n",
|
||||||
|
__func__, rc);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = wait_event_timeout(core->wait, (core->resp_received),
|
||||||
|
msecs_to_jiffies(Q6_READY_TIMEOUT_MS));
|
||||||
|
dev_info(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__);
|
||||||
|
if (rc > 0 && core->resp_received) {
|
||||||
|
if (core->status != 0)
|
||||||
|
dev_err(gecko_core_priv->dev, "%s, cmd failed status %d",
|
||||||
|
__func__, core->status);
|
||||||
|
} else {
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
core->resp_received = false;
|
||||||
|
mutex_unlock(&core->lock);
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(gecko_core_apm_close_all);
|
||||||
|
|
||||||
|
|
||||||
static int gecko_core_probe(struct gpr_device *adev)
|
static int gecko_core_probe(struct gpr_device *adev)
|
||||||
{
|
{
|
||||||
struct gecko_core *core;
|
struct gecko_core *core;
|
||||||
@@ -176,8 +268,10 @@ static int gecko_core_probe(struct gpr_device *adev)
|
|||||||
}
|
}
|
||||||
mutex_lock(&gecko_core_priv->lock);
|
mutex_lock(&gecko_core_priv->lock);
|
||||||
core = kzalloc(sizeof(*core), GFP_KERNEL);
|
core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||||
if (!core)
|
if (!core) {
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
dev_set_drvdata(&adev->dev, core);
|
dev_set_drvdata(&adev->dev, core);
|
||||||
|
|
||||||
|
@@ -15,5 +15,6 @@
|
|||||||
#include <ipc/gpr-lite.h>
|
#include <ipc/gpr-lite.h>
|
||||||
|
|
||||||
bool gecko_core_is_apm_ready(void);
|
bool gecko_core_is_apm_ready(void);
|
||||||
|
void gecko_core_apm_close_all(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/termios.h>
|
#include <linux/termios.h>
|
||||||
#include <ipc/gpr-lite.h>
|
#include <ipc/gpr-lite.h>
|
||||||
|
#include <dsp/gecko-core.h>
|
||||||
#include <dsp/msm_audio_ion.h>
|
#include <dsp/msm_audio_ion.h>
|
||||||
|
|
||||||
/* Define IPC Logging Macros */
|
/* Define IPC Logging Macros */
|
||||||
@@ -192,6 +193,8 @@ int audio_pkt_release(struct inode *inode, struct file *file)
|
|||||||
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
||||||
|
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
gecko_core_apm_close_all();
|
||||||
|
msm_audio_ion_crash_handler();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user