audio-kernel: Add changes to support SSR/PDR
Add changes in audio-pkt,voice_mhi and gpr-lite drivers. Fixing bug in audio_pdr driver w.r.t memory allocation. Change-Id: I6ab7ff13b532921f85e9548341969abd32ee3b6d Signed-off-by: Bharath Tirunagaru <bharatht@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
2f145b55cf
commit
ebf0162590
@@ -33,11 +33,34 @@ static int audio_pdr_locator_callback(struct notifier_block *this,
|
|||||||
memcpy(&audio_pdr_services, data,
|
memcpy(&audio_pdr_services, data,
|
||||||
sizeof(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP]));
|
sizeof(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP]));
|
||||||
if (audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains == 1) {
|
if (audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains == 1) {
|
||||||
|
int domain_list_size = (sizeof(struct servreg_loc_entry_v01)) *
|
||||||
|
(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains);
|
||||||
|
struct servreg_loc_entry_v01 *domain_list_temp = NULL;
|
||||||
|
|
||||||
pr_debug("%s: Service %s, returned total domains %d, ",
|
pr_debug("%s: Service %s, returned total domains %d, ",
|
||||||
__func__,
|
__func__,
|
||||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||||
total_domains);
|
total_domains);
|
||||||
|
|
||||||
|
domain_list_temp = (struct servreg_loc_entry_v01 *)kzalloc(
|
||||||
|
sizeof(domain_list_size), GFP_KERNEL);
|
||||||
|
|
||||||
|
if(!domain_list_size)
|
||||||
|
{
|
||||||
|
pr_err("%s: Service %s total domains %d could not allocate memory",
|
||||||
|
__func__,
|
||||||
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||||
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||||
|
total_domains);
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
memcpy(domain_list_temp,
|
||||||
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].domain_list,
|
||||||
|
domain_list_size);
|
||||||
|
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].domain_list = domain_list_temp;
|
||||||
|
}
|
||||||
|
|
||||||
pdr_state = AUDIO_PDR_FRAMEWORK_UP;
|
pdr_state = AUDIO_PDR_FRAMEWORK_UP;
|
||||||
goto done;
|
goto done;
|
||||||
} else
|
} else
|
||||||
@@ -108,7 +131,7 @@ void *audio_pdr_service_register(int domain_id,
|
|||||||
audio_pdr_services[domain_id].domain_list[0].instance_id,
|
audio_pdr_services[domain_id].domain_list[0].instance_id,
|
||||||
nb, curr_state);
|
nb, curr_state);
|
||||||
if (IS_ERR_OR_NULL(handle)) {
|
if (IS_ERR_OR_NULL(handle)) {
|
||||||
pr_err("%s: Failed to register for service %s, instance %d\n",
|
pr_err("%s: Failed to register for domain %s, instance %d\n",
|
||||||
__func__,
|
__func__,
|
||||||
audio_pdr_services[domain_id].domain_list[0].name,
|
audio_pdr_services[domain_id].domain_list[0].name,
|
||||||
audio_pdr_services[domain_id].domain_list[0].
|
audio_pdr_services[domain_id].domain_list[0].
|
||||||
@@ -168,6 +191,14 @@ module_init(audio_pdr_late_init);
|
|||||||
|
|
||||||
static void __exit audio_pdr_late_exit(void)
|
static void __exit audio_pdr_late_exit(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AUDIO_PDR_DOMAIN_MAX; i++)
|
||||||
|
{
|
||||||
|
if (audio_pdr_services[i].domain_list != NULL)
|
||||||
|
kfree(audio_pdr_services[i].domain_list);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
module_exit(audio_pdr_late_exit);
|
module_exit(audio_pdr_late_exit);
|
||||||
|
|
||||||
|
@@ -357,9 +357,8 @@ static int audio_prm_remove(struct gpr_device *adev)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
g_prm.adev = NULL;
|
g_prm.adev = NULL;
|
||||||
|
g_prm.is_adsp_up = false;
|
||||||
mutex_unlock(&g_prm.lock);
|
mutex_unlock(&g_prm.lock);
|
||||||
|
|
||||||
kfree(&g_prm);
|
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -488,8 +488,8 @@ static int voice_mhi_gpr_probe(struct gpr_device *gdev)
|
|||||||
|
|
||||||
static int voice_mhi_gpr_exit(struct gpr_device *gdev)
|
static int voice_mhi_gpr_exit(struct gpr_device *gdev)
|
||||||
{
|
{
|
||||||
mutex_lock(&voice_mhi_lcl.mutex);
|
|
||||||
voice_mhi_end();
|
voice_mhi_end();
|
||||||
|
mutex_lock(&voice_mhi_lcl.mutex);
|
||||||
voice_mhi_lcl.gdev = NULL;
|
voice_mhi_lcl.gdev = NULL;
|
||||||
VOICE_MHI_STATE_RESET(voice_mhi_lcl.voice_mhi_state,
|
VOICE_MHI_STATE_RESET(voice_mhi_lcl.voice_mhi_state,
|
||||||
VOICE_MHI_ADSP_UP);
|
VOICE_MHI_ADSP_UP);
|
||||||
|
@@ -29,6 +29,14 @@ enum gpr_subsys_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct gpr_q6 {
|
||||||
|
//void *pil;
|
||||||
|
atomic_t q6_state;
|
||||||
|
atomic_t modem_state;
|
||||||
|
struct mutex lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Version */
|
/* Version */
|
||||||
#define GPR_PKT_VER 0x0
|
#define GPR_PKT_VER 0x0
|
||||||
|
|
||||||
|
314
ipc/audio-pkt.c
314
ipc/audio-pkt.c
@@ -62,12 +62,19 @@ do { \
|
|||||||
#define AUDPKT_DRIVER_NAME "aud_pasthru_adsp"
|
#define AUDPKT_DRIVER_NAME "aud_pasthru_adsp"
|
||||||
#define CHANNEL_NAME "to_apps"
|
#define CHANNEL_NAME "to_apps"
|
||||||
|
|
||||||
|
|
||||||
|
enum audio_pkt_state {
|
||||||
|
AUDIO_PKT_INIT,
|
||||||
|
AUDIO_PKT_PROBED,
|
||||||
|
AUDIO_PKT_REMOVED,
|
||||||
|
AUDIO_PKT_DEINIT,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct audio_pkt - driver context, relates rpdev to cdev
|
* struct audio_pkt_device - driver context, relates to platform dev
|
||||||
* @adev: gpr device node
|
|
||||||
* @dev: audio pkt device
|
* @dev: audio pkt device
|
||||||
* @cdev: cdev for the audio pkt device
|
* @cdev: cdev for the audio pkt device
|
||||||
* @lock: synchronization of @rpdev
|
* @lock: synchronization of @dev
|
||||||
* @queue_lock: synchronization of @queue operations
|
* @queue_lock: synchronization of @queue operations
|
||||||
* @queue: incoming message queue
|
* @queue: incoming message queue
|
||||||
* @readq: wait object for incoming queue
|
* @readq: wait object for incoming queue
|
||||||
@@ -77,12 +84,10 @@ do { \
|
|||||||
* @audio_pkt_class: audio pkt class pointer
|
* @audio_pkt_class: audio pkt class pointer
|
||||||
*/
|
*/
|
||||||
struct audio_pkt_device {
|
struct audio_pkt_device {
|
||||||
struct gpr_device *adev;
|
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
|
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
|
||||||
spinlock_t queue_lock;
|
spinlock_t queue_lock;
|
||||||
struct sk_buff_head queue;
|
struct sk_buff_head queue;
|
||||||
wait_queue_head_t readq;
|
wait_queue_head_t readq;
|
||||||
@@ -94,6 +99,18 @@ struct audio_pkt_device {
|
|||||||
struct class *audio_pkt_class;
|
struct class *audio_pkt_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct audio_pkt_priv {
|
||||||
|
struct gpr_device *adev;
|
||||||
|
struct device *dev;
|
||||||
|
struct audio_pkt_device *ap_dev;
|
||||||
|
|
||||||
|
struct mutex lock;
|
||||||
|
enum audio_pkt_state status;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct audio_pkt_priv *ap_priv;
|
||||||
|
|
||||||
|
|
||||||
struct audio_pkt_apm_cmd_shared_mem_map_regions_t {
|
struct audio_pkt_apm_cmd_shared_mem_map_regions_t {
|
||||||
uint16_t mem_pool_id;
|
uint16_t mem_pool_id;
|
||||||
uint16_t num_regions;
|
uint16_t num_regions;
|
||||||
@@ -124,9 +141,6 @@ struct audio_pkt_clnt_ch {
|
|||||||
audio_pkt_clnt_cb_fn func;
|
audio_pkt_clnt_cb_fn func;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define dev_to_audpkt_dev(_dev) container_of(_dev, struct audio_pkt_device, dev)
|
|
||||||
#define cdev_to_audpkt_dev(_cdev) container_of(_cdev, struct audio_pkt_device, cdev)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* audio_pkt_open() - open() syscall for the audio_pkt device
|
* audio_pkt_open() - open() syscall for the audio_pkt device
|
||||||
* inode: Pointer to the inode structure.
|
* inode: Pointer to the inode structure.
|
||||||
@@ -138,14 +152,9 @@ struct audio_pkt_clnt_ch {
|
|||||||
*/
|
*/
|
||||||
int audio_pkt_open(struct inode *inode, struct file *file)
|
int audio_pkt_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = cdev_to_audpkt_dev(inode->i_cdev);
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
struct device *dev = audpkt_dev->dev;
|
AUDIO_PKT_INFO("%s: for %s \n", __func__,audpkt_dev->ch_name);
|
||||||
|
file->private_data = ap_priv;
|
||||||
AUDIO_PKT_ERR("for %s\n", audpkt_dev->ch_name);
|
|
||||||
|
|
||||||
get_device(dev);
|
|
||||||
file->private_data = audpkt_dev;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,12 +169,18 @@ int audio_pkt_open(struct inode *inode, struct file *file)
|
|||||||
*/
|
*/
|
||||||
int audio_pkt_release(struct inode *inode, struct file *file)
|
int audio_pkt_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = cdev_to_audpkt_dev(inode->i_cdev);
|
struct audio_pkt_priv *ap_priv = file->private_data;
|
||||||
struct device *dev = audpkt_dev->dev;
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
|
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
AUDIO_PKT_INFO("for %s \n", audpkt_dev->ch_name);
|
if ((!audpkt_dev)) {
|
||||||
|
AUDIO_PKT_ERR("invalid device handle\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AUDIO_PKT_INFO("%s: for %s \n", __func__,audpkt_dev->ch_name);
|
||||||
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
||||||
|
|
||||||
/* Discard all SKBs */
|
/* Discard all SKBs */
|
||||||
@@ -176,12 +191,38 @@ int audio_pkt_release(struct inode *inode, struct file *file)
|
|||||||
wake_up_interruptible(&audpkt_dev->readq);
|
wake_up_interruptible(&audpkt_dev->readq);
|
||||||
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
||||||
|
|
||||||
put_device(dev);
|
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int audio_pkt_internal_release(struct platform_device *adev)
|
||||||
|
{
|
||||||
|
struct audio_pkt_priv *ap_priv = platform_get_drvdata(adev);
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if ((!audpkt_dev)) {
|
||||||
|
AUDIO_PKT_ERR("invalid device handle\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AUDIO_PKT_INFO("%s: for %s\n", __func__,audpkt_dev->ch_name);
|
||||||
|
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
||||||
|
/* Discard all SKBs */
|
||||||
|
while (!skb_queue_empty(&audpkt_dev->queue)) {
|
||||||
|
skb = skb_dequeue(&audpkt_dev->queue);
|
||||||
|
kfree_skb(skb);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
||||||
|
|
||||||
|
wake_up_interruptible(&audpkt_dev->readq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* audio_pkt_read() - read() syscall for the audio_pkt device
|
* audio_pkt_read() - read() syscall for the audio_pkt device
|
||||||
* file: Pointer to the file structure.
|
* file: Pointer to the file structure.
|
||||||
@@ -196,7 +237,9 @@ int audio_pkt_release(struct inode *inode, struct file *file)
|
|||||||
ssize_t audio_pkt_read(struct file *file, char __user *buf,
|
ssize_t audio_pkt_read(struct file *file, char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = file->private_data;
|
struct audio_pkt_priv *ap_priv = file->private_data;
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int use;
|
int use;
|
||||||
@@ -207,6 +250,15 @@ ssize_t audio_pkt_read(struct file *file, char __user *buf,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ap_priv->lock);
|
||||||
|
if (AUDIO_PKT_PROBED != ap_priv->status)
|
||||||
|
{
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
AUDIO_PKT_ERR("dev is in reset\n");
|
||||||
|
return -ENETRESET;
|
||||||
|
}
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
|
||||||
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
||||||
/* Wait for data in the queue */
|
/* Wait for data in the queue */
|
||||||
if (skb_queue_empty(&audpkt_dev->queue)) {
|
if (skb_queue_empty(&audpkt_dev->queue)) {
|
||||||
@@ -278,7 +330,8 @@ int audpkt_chk_and_update_physical_addr(struct audio_gpr_pkt *gpr_pkt)
|
|||||||
ssize_t audio_pkt_write(struct file *file, const char __user *buf,
|
ssize_t audio_pkt_write(struct file *file, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = file->private_data;
|
struct audio_pkt_priv *ap_priv = file->private_data;
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
struct gpr_hdr *audpkt_hdr = NULL;
|
struct gpr_hdr *audpkt_hdr = NULL;
|
||||||
void *kbuf;
|
void *kbuf;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -288,6 +341,15 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ap_priv->lock);
|
||||||
|
if (AUDIO_PKT_PROBED != ap_priv->status)
|
||||||
|
{
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
AUDIO_PKT_ERR("dev is in reset\n");
|
||||||
|
return -ENETRESET;
|
||||||
|
}
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
|
||||||
kbuf = memdup_user(buf, count);
|
kbuf = memdup_user(buf, count);
|
||||||
if (IS_ERR(kbuf))
|
if (IS_ERR(kbuf))
|
||||||
return PTR_ERR(kbuf);
|
return PTR_ERR(kbuf);
|
||||||
@@ -305,9 +367,10 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf,
|
|||||||
ret = -ERESTARTSYS;
|
ret = -ERESTARTSYS;
|
||||||
goto free_kbuf;
|
goto free_kbuf;
|
||||||
}
|
}
|
||||||
ret = gpr_send_pkt(audpkt_dev->adev,(struct gpr_pkt *) kbuf);
|
ret = gpr_send_pkt(ap_priv->adev,(struct gpr_pkt *) kbuf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
AUDIO_PKT_ERR("APR Send Packet Failed ret -%d\n", ret);
|
AUDIO_PKT_ERR("APR Send Packet Failed ret -%d\n", ret);
|
||||||
|
mutex_unlock(&audpkt_dev->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
mutex_unlock(&audpkt_dev->lock);
|
mutex_unlock(&audpkt_dev->lock);
|
||||||
@@ -328,18 +391,16 @@ free_kbuf:
|
|||||||
*/
|
*/
|
||||||
static unsigned int audio_pkt_poll(struct file *file, poll_table *wait)
|
static unsigned int audio_pkt_poll(struct file *file, poll_table *wait)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = file->private_data;
|
struct audio_pkt_priv *ap_priv = file->private_data;
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
audpkt_dev = file->private_data;
|
|
||||||
if (!audpkt_dev) {
|
if (!audpkt_dev) {
|
||||||
AUDIO_PKT_ERR("invalid device handle\n");
|
AUDIO_PKT_ERR("invalid device handle\n");
|
||||||
return POLLERR;
|
return POLLERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
poll_wait(file, &audpkt_dev->readq, wait);
|
poll_wait(file, &audpkt_dev->readq, wait);
|
||||||
|
|
||||||
mutex_lock(&audpkt_dev->lock);
|
mutex_lock(&audpkt_dev->lock);
|
||||||
|
|
||||||
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
spin_lock_irqsave(&audpkt_dev->queue_lock, flags);
|
||||||
@@ -347,7 +408,6 @@ static unsigned int audio_pkt_poll(struct file *file, poll_table *wait)
|
|||||||
mask |= POLLIN | POLLRDNORM;
|
mask |= POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags);
|
||||||
|
|
||||||
mutex_unlock(&audpkt_dev->lock);
|
mutex_unlock(&audpkt_dev->lock);
|
||||||
|
|
||||||
return mask;
|
return mask;
|
||||||
@@ -372,7 +432,9 @@ static const struct file_operations audio_pkt_fops = {
|
|||||||
static int audio_pkt_srvc_callback(struct gpr_device *adev,
|
static int audio_pkt_srvc_callback(struct gpr_device *adev,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev = dev_get_drvdata(&adev->dev);
|
struct audio_pkt_priv *ap_priv = dev_get_drvdata(&adev->dev);
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct gpr_hdr *hdr = (struct gpr_hdr *)data;
|
struct gpr_hdr *hdr = (struct gpr_hdr *)data;
|
||||||
@@ -380,7 +442,8 @@ static int audio_pkt_srvc_callback(struct gpr_device *adev,
|
|||||||
hdr_size = GPR_PKT_GET_HEADER_BYTE_SIZE(hdr->header);
|
hdr_size = GPR_PKT_GET_HEADER_BYTE_SIZE(hdr->header);
|
||||||
pkt_size = GPR_PKT_GET_PACKET_BYTE_SIZE(hdr->header);
|
pkt_size = GPR_PKT_GET_PACKET_BYTE_SIZE(hdr->header);
|
||||||
|
|
||||||
AUDIO_PKT_INFO("header %d packet %d \n",hdr_size, pkt_size);
|
AUDIO_PKT_INFO("%s: header %d packet %d \n",
|
||||||
|
__func__,hdr_size, pkt_size);
|
||||||
|
|
||||||
skb = alloc_skb(pkt_size, GFP_ATOMIC);
|
skb = alloc_skb(pkt_size, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
@@ -409,11 +472,117 @@ static int audio_pkt_srvc_callback(struct gpr_device *adev,
|
|||||||
*/
|
*/
|
||||||
static int audio_pkt_probe(struct gpr_device *adev)
|
static int audio_pkt_probe(struct gpr_device *adev)
|
||||||
{
|
{
|
||||||
struct audio_pkt_device *audpkt_dev;
|
if(ap_priv)
|
||||||
struct device *dev = &adev->dev;
|
{
|
||||||
int ret;
|
mutex_lock(&ap_priv->lock);
|
||||||
|
ap_priv->adev = adev;
|
||||||
|
ap_priv->status = AUDIO_PKT_PROBED;
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
|
||||||
audpkt_dev = devm_kzalloc(dev, sizeof(*audpkt_dev), GFP_KERNEL);
|
dev_set_drvdata(&adev->dev, ap_priv);
|
||||||
|
|
||||||
|
dev_dbg(&adev->dev, "%s: Driver[%s] Probed\n",
|
||||||
|
__func__, adev->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dev_err(&adev->dev, "%s: Driver[%s] Probe Failed\n",
|
||||||
|
__func__, adev->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* audio_pkt_remove() - Remove a AUDIO packet device
|
||||||
|
*
|
||||||
|
* adev: Pointer to gpr device.
|
||||||
|
*
|
||||||
|
* return: 0 on success, standard Linux error codes on error.
|
||||||
|
*
|
||||||
|
* This function is called when the underlying device tree driver
|
||||||
|
* removeds a gpr device, mapped to a Audio packet device.
|
||||||
|
*/
|
||||||
|
static int audio_pkt_remove(struct gpr_device *adev)
|
||||||
|
{
|
||||||
|
if(ap_priv)
|
||||||
|
{
|
||||||
|
mutex_lock(&ap_priv->lock);
|
||||||
|
ap_priv->adev = NULL;
|
||||||
|
ap_priv->status = AUDIO_PKT_REMOVED;
|
||||||
|
mutex_unlock(&ap_priv->lock);
|
||||||
|
dev_dbg(&adev->dev, "%s: Driver[%s] Removing\n",
|
||||||
|
__func__, adev->name);
|
||||||
|
dev_set_drvdata(&adev->dev, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dev_err(&adev->dev, "%s: Driver[%s] Remove Failed\n",
|
||||||
|
__func__, adev->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id audio_pkt_match_table[] = {
|
||||||
|
{ .compatible = "qcom,audio-pkt" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, audio_pkt_match_table);
|
||||||
|
|
||||||
|
static struct gpr_driver audio_pkt_driver = {
|
||||||
|
.probe = audio_pkt_probe,
|
||||||
|
.remove = audio_pkt_remove,
|
||||||
|
.callback = audio_pkt_srvc_callback,
|
||||||
|
.driver = {
|
||||||
|
.name = MODULE_NAME,
|
||||||
|
.of_match_table = of_match_ptr(audio_pkt_match_table),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int audio_pkt_plaform_driver_register_gpr(struct platform_device *pdev,
|
||||||
|
struct audio_pkt_device *audpkt_dev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ap_priv = devm_kzalloc(&pdev->dev,
|
||||||
|
sizeof(*ap_priv), GFP_KERNEL);
|
||||||
|
if (!ap_priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = gpr_driver_register(&audio_pkt_driver);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "%s: registering to gpr driver failed, err = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_init(&ap_priv->lock);
|
||||||
|
ap_priv->status = AUDIO_PKT_INIT;
|
||||||
|
ap_priv->ap_dev = audpkt_dev;
|
||||||
|
ap_priv->dev = audpkt_dev->dev;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* audio_pkt_platform_driver_probe() - Probe a AUDIO packet device
|
||||||
|
*
|
||||||
|
* adev: Pointer to platform device.
|
||||||
|
*
|
||||||
|
* return: 0 on success, standard Linux error codes on error.
|
||||||
|
*
|
||||||
|
* This function is called when the underlying device tree driver registers
|
||||||
|
* a platform device, mapped to a Audio packet device.
|
||||||
|
*/
|
||||||
|
static int audio_pkt_platform_driver_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct audio_pkt_device *audpkt_dev;
|
||||||
|
|
||||||
|
audpkt_dev = devm_kzalloc(&pdev->dev, sizeof(*audpkt_dev), GFP_KERNEL);
|
||||||
if (!audpkt_dev)
|
if (!audpkt_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -452,9 +621,6 @@ static int audio_pkt_probe(struct gpr_device *adev)
|
|||||||
skb_queue_head_init(&audpkt_dev->queue);
|
skb_queue_head_init(&audpkt_dev->queue);
|
||||||
init_waitqueue_head(&audpkt_dev->readq);
|
init_waitqueue_head(&audpkt_dev->readq);
|
||||||
|
|
||||||
audpkt_dev->adev = adev;
|
|
||||||
dev_set_drvdata(dev, audpkt_dev);
|
|
||||||
|
|
||||||
cdev_init(&audpkt_dev->cdev, &audio_pkt_fops);
|
cdev_init(&audpkt_dev->cdev, &audio_pkt_fops);
|
||||||
audpkt_dev->cdev.owner = THIS_MODULE;
|
audpkt_dev->cdev.owner = THIS_MODULE;
|
||||||
|
|
||||||
@@ -466,12 +632,20 @@ static int audio_pkt_probe(struct gpr_device *adev)
|
|||||||
goto free_dev;
|
goto free_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = audio_pkt_plaform_driver_register_gpr(pdev, audpkt_dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "%s: Failed to register with gpr, err = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
goto free_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, ap_priv);
|
||||||
AUDIO_PKT_INFO("Audio Packet Port Driver Initialized\n");
|
AUDIO_PKT_INFO("Audio Packet Port Driver Initialized\n");
|
||||||
|
|
||||||
return of_platform_populate(dev->of_node, NULL, NULL, dev);
|
goto done;
|
||||||
|
//return of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||||
|
|
||||||
free_dev:
|
free_dev:
|
||||||
put_device(dev);
|
|
||||||
device_destroy(audpkt_dev->audio_pkt_class,audpkt_dev->audio_pkt_major);
|
device_destroy(audpkt_dev->audio_pkt_class,audpkt_dev->audio_pkt_major);
|
||||||
err_device:
|
err_device:
|
||||||
class_destroy(audpkt_dev->audio_pkt_class);
|
class_destroy(audpkt_dev->audio_pkt_class);
|
||||||
@@ -479,45 +653,73 @@ err_class:
|
|||||||
unregister_chrdev_region(MAJOR(audpkt_dev->audio_pkt_major),
|
unregister_chrdev_region(MAJOR(audpkt_dev->audio_pkt_major),
|
||||||
MINOR_NUMBER_COUNT);
|
MINOR_NUMBER_COUNT);
|
||||||
err_chrdev:
|
err_chrdev:
|
||||||
kfree(audpkt_dev);
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* audio_pkt_remove() - Remove a AUDIO packet device
|
* audio_pkt_platform_driver_remove() - Remove a AUDIO packet platform device
|
||||||
*
|
*
|
||||||
* adev: Pointer to gpr device.
|
* adev: Pointer to platform device.
|
||||||
*
|
*
|
||||||
* return: 0 on success, standard Linux error codes on error.
|
* return: 0 on success, standard Linux error codes on error.
|
||||||
*
|
*
|
||||||
* This function is called when the underlying device tree driver
|
* This function is called when the underlying device tree driver
|
||||||
* removeds a gpr device, mapped to a Audio packet device.
|
* removes a platform device, mapped to a Audio packet device.
|
||||||
*/
|
*/
|
||||||
static int audio_pkt_remove(struct gpr_device *adev)
|
static int audio_pkt_platform_driver_remove(struct platform_device *adev)
|
||||||
{
|
{
|
||||||
of_platform_depopulate(&adev->dev);
|
struct audio_pkt_priv *ap_priv = platform_get_drvdata(adev);
|
||||||
|
struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
|
||||||
|
|
||||||
|
gpr_driver_unregister(&audio_pkt_driver);
|
||||||
|
|
||||||
|
audio_pkt_internal_release(adev);
|
||||||
|
|
||||||
|
if (audpkt_dev) {
|
||||||
|
cdev_del(&audpkt_dev->cdev);
|
||||||
|
device_destroy(audpkt_dev->audio_pkt_class,audpkt_dev->audio_pkt_major);
|
||||||
|
class_destroy(audpkt_dev->audio_pkt_class);
|
||||||
|
unregister_chrdev_region(MAJOR(audpkt_dev->audio_pkt_major),
|
||||||
|
MINOR_NUMBER_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//of_platform_depopulate(&adev->dev);
|
||||||
AUDIO_PKT_INFO("Audio Packet Port Driver Removed\n");
|
AUDIO_PKT_INFO("Audio Packet Port Driver Removed\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
static const struct of_device_id audio_pkt_match_table[] = {
|
|
||||||
{ .compatible = "qcom,audio-pkt" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(of, audio_pkt_match_table);
|
|
||||||
|
|
||||||
static struct gpr_driver audio_pkt_driver = {
|
static const struct of_device_id audio_pkt_platform_match_table[] = {
|
||||||
.probe = audio_pkt_probe,
|
{ .compatible = "qcom,audio-pkt-core-platform"},
|
||||||
.remove = audio_pkt_remove,
|
{}
|
||||||
.callback = audio_pkt_srvc_callback,
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, audio_pkt_platform_match_table);
|
||||||
|
|
||||||
|
|
||||||
|
static struct platform_driver audio_pkt_core_platform_driver = {
|
||||||
|
.probe = audio_pkt_platform_driver_probe,
|
||||||
|
.remove = audio_pkt_platform_driver_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = MODULE_NAME,
|
.name = MODULE_NAME,
|
||||||
.of_match_table = of_match_ptr(audio_pkt_match_table),
|
.of_match_table = of_match_ptr(audio_pkt_platform_match_table),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_gpr_driver(audio_pkt_driver);
|
|
||||||
|
static int __init audio_pkt_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&audio_pkt_core_platform_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit audio_pkt_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&audio_pkt_core_platform_driver);
|
||||||
|
}
|
||||||
|
module_init(audio_pkt_init);
|
||||||
|
module_exit(audio_pkt_exit);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("MSM Audio Packet Driver");
|
MODULE_DESCRIPTION("MSM Audio Packet Driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
262
ipc/gpr-lite.c
262
ipc/gpr-lite.c
@@ -22,36 +22,107 @@
|
|||||||
#include <linux/rpmsg.h>
|
#include <linux/rpmsg.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
#include <soc/snd_event.h>
|
||||||
|
#include <dsp/audio_notifier.h>
|
||||||
|
|
||||||
struct gpr {
|
struct gpr {
|
||||||
struct rpmsg_endpoint *ch;
|
struct rpmsg_endpoint *ch;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
spinlock_t gpr_lock;
|
||||||
|
bool is_initial_boot;
|
||||||
|
|
||||||
spinlock_t svcs_lock;
|
spinlock_t svcs_lock;
|
||||||
struct idr svcs_idr;
|
struct idr svcs_idr;
|
||||||
int dest_domain_id;
|
int dest_domain_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpr_q6 q6;
|
||||||
|
static struct gpr *gpr_priv;
|
||||||
|
|
||||||
|
enum gpr_subsys_state gpr_get_q6_state(void)
|
||||||
|
{
|
||||||
|
return atomic_read(&q6.q6_state);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpr_get_q6_state);
|
||||||
|
|
||||||
|
enum gpr_subsys_state gpr_get_modem_state(void)
|
||||||
|
{
|
||||||
|
return atomic_read(&q6.modem_state);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpr_get_modem_state);
|
||||||
|
|
||||||
|
|
||||||
|
void gpr_subsys_notif_register(char *client_name, int domain,
|
||||||
|
struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = audio_notifier_register(client_name, domain, nb);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(gpr_priv->dev, "%s: Audio notifier register failed for domain %d ret = %d\n",
|
||||||
|
__func__, domain, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpr_subsys_notif_deregister(char *client_name)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = audio_notifier_deregister(client_name);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(gpr_priv->dev, "%s: Audio notifier de-register failed for client %s\n",
|
||||||
|
__func__, client_name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpr_send_pkt() - Send a gpr message from gpr device
|
* gpr_send_pkt() - Send a gpr message from gpr device
|
||||||
*
|
*
|
||||||
* @adev: Pointer to previously registered gpr device.
|
* @adev: Pointer to previously registered gpr device.
|
||||||
* @pkt: Pointer to gpr packet to send
|
* @pkt: Pointer to gpr packet to send
|
||||||
*
|
*
|
||||||
* Return: Will be an negative on packet size on success.
|
* Return: Will be an negative and/or packet size on success.
|
||||||
*/
|
*/
|
||||||
int gpr_send_pkt(struct gpr_device *adev, struct gpr_pkt *pkt)
|
int gpr_send_pkt(struct gpr_device *adev, struct gpr_pkt *pkt)
|
||||||
{
|
{
|
||||||
struct gpr *gpr = dev_get_drvdata(adev->dev.parent);
|
struct gpr *gpr;
|
||||||
struct gpr_hdr *hdr;
|
struct gpr_hdr *hdr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint32_t pkt_size;
|
uint32_t pkt_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if(!adev)
|
||||||
|
{
|
||||||
|
pr_err("%s: enter pointer adev[%p] \n", __func__, adev);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(adev->dev.parent))
|
||||||
|
{
|
||||||
|
pr_err("%s: enter pointer adev->dev.parent[%p] \n",
|
||||||
|
__func__, adev->dev.parent);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpr = dev_get_drvdata(adev->dev.parent);
|
||||||
|
|
||||||
|
if ((adev->domain_id == GPR_IDS_DOMAIN_ID_ADSP_V) &&
|
||||||
|
(gpr_get_q6_state() != GPR_SUBSYS_LOADED)) {
|
||||||
|
dev_err(gpr->dev,"%s: domain_id[%d], Still Dsp is not Up\n",
|
||||||
|
__func__, adev->domain_id);
|
||||||
|
return -ENETRESET;
|
||||||
|
} else if ((adev->domain_id == GPR_IDS_DOMAIN_ID_MODEM_V) &&
|
||||||
|
(gpr_get_modem_state() == GPR_SUBSYS_DOWN)) {
|
||||||
|
dev_err(gpr->dev, "%s: domain_id[%d], Still Modem is not Up\n",
|
||||||
|
__func__, adev->domain_id );
|
||||||
|
return -ENETRESET;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&adev->lock, flags);
|
spin_lock_irqsave(&adev->lock, flags);
|
||||||
|
|
||||||
hdr = &pkt->hdr;
|
hdr = &pkt->hdr;
|
||||||
pkt_size = GPR_PKT_GET_PACKET_BYTE_SIZE(hdr->header);
|
pkt_size = GPR_PKT_GET_PACKET_BYTE_SIZE(hdr->header);
|
||||||
|
|
||||||
dev_dbg(gpr->dev, "SVC_ID %d %s packet size %d\n", adev->svc_id, __func__, pkt_size);
|
dev_dbg(gpr->dev, "SVC_ID %d %s packet size %d\n",
|
||||||
|
adev->svc_id, __func__, pkt_size);
|
||||||
ret = rpmsg_trysend(gpr->ch, pkt, pkt_size);
|
ret = rpmsg_trysend(gpr->ch, pkt, pkt_size);
|
||||||
spin_unlock_irqrestore(&adev->lock, flags);
|
spin_unlock_irqrestore(&adev->lock, flags);
|
||||||
|
|
||||||
@@ -59,6 +130,126 @@ int gpr_send_pkt(struct gpr_device *adev, struct gpr_pkt *pkt)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gpr_send_pkt);
|
EXPORT_SYMBOL_GPL(gpr_send_pkt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apr_set_modem_state - Update modem load status.
|
||||||
|
*
|
||||||
|
* @state: State to update modem load status
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void gpr_set_modem_state(enum gpr_subsys_state state)
|
||||||
|
{
|
||||||
|
atomic_set(&q6.modem_state, state);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpr_set_modem_state);
|
||||||
|
|
||||||
|
|
||||||
|
static void gpr_modem_down(unsigned long opcode)
|
||||||
|
{
|
||||||
|
gpr_set_modem_state(GPR_SUBSYS_DOWN);
|
||||||
|
//dispatch_event(opcode, APR_DEST_MODEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpr_modem_up(void)
|
||||||
|
{
|
||||||
|
//if (apr_cmpxchg_modem_state(APR_SUBSYS_DOWN, APR_SUBSYS_UP) ==
|
||||||
|
// APR_SUBSYS_DOWN)
|
||||||
|
// wake_up(&modem_wait);
|
||||||
|
//is_modem_up = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int gpr_set_q6_state(enum gpr_subsys_state state)
|
||||||
|
{
|
||||||
|
dev_dbg(gpr_priv->dev,"%s: setting adsp state %d\n", __func__, state);
|
||||||
|
if (state < GPR_SUBSYS_DOWN || state > GPR_SUBSYS_LOADED)
|
||||||
|
return -EINVAL;
|
||||||
|
atomic_set(&q6.q6_state, state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpr_set_q6_state);
|
||||||
|
|
||||||
|
static void gpr_ssr_disable(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
gpr_set_q6_state(GPR_SUBSYS_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snd_event_ops gpr_ssr_ops = {
|
||||||
|
.disable = gpr_ssr_disable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gpr_adsp_down(unsigned long opcode)
|
||||||
|
{
|
||||||
|
dev_dbg(gpr_priv->dev,"%s: Q6 is Down\n", __func__);
|
||||||
|
snd_event_notify(gpr_priv->dev, SND_EVENT_DOWN);
|
||||||
|
gpr_set_q6_state(GPR_SUBSYS_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpr_adsp_up(void)
|
||||||
|
{
|
||||||
|
dev_dbg(gpr_priv->dev,"%s: Q6 is Up\n", __func__);
|
||||||
|
gpr_set_q6_state(GPR_SUBSYS_LOADED);
|
||||||
|
snd_event_notify(gpr_priv->dev, SND_EVENT_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gpr_notifier_service_cb(struct notifier_block *this,
|
||||||
|
unsigned long opcode, void *data)
|
||||||
|
{
|
||||||
|
struct audio_notifier_cb_data *cb_data = data;
|
||||||
|
|
||||||
|
if (cb_data == NULL) {
|
||||||
|
dev_err(gpr_priv->dev,"%s: Callback data is NULL!\n", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(gpr_priv->dev,"%s: Service opcode 0x%lx, domain %d\n",
|
||||||
|
__func__, opcode, cb_data->domain);
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case AUDIO_NOTIFIER_SERVICE_DOWN:
|
||||||
|
/*
|
||||||
|
* Use flag to ignore down notifications during
|
||||||
|
* initial boot. There is no benefit from error
|
||||||
|
* recovery notifications during initial boot
|
||||||
|
* up since everything is expected to be down.
|
||||||
|
*/
|
||||||
|
spin_lock(&gpr_priv->gpr_lock);
|
||||||
|
if (gpr_priv->is_initial_boot) {
|
||||||
|
spin_unlock(&gpr_priv->gpr_lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock(&gpr_priv->gpr_lock);
|
||||||
|
if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
|
||||||
|
gpr_modem_down(opcode);
|
||||||
|
else
|
||||||
|
gpr_adsp_down(opcode);
|
||||||
|
break;
|
||||||
|
case AUDIO_NOTIFIER_SERVICE_UP:
|
||||||
|
if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
|
||||||
|
gpr_modem_up();
|
||||||
|
else
|
||||||
|
gpr_adsp_up();
|
||||||
|
spin_lock(&gpr_priv->gpr_lock);
|
||||||
|
gpr_priv->is_initial_boot = false;
|
||||||
|
spin_unlock(&gpr_priv->gpr_lock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct notifier_block adsp_service_nb = {
|
||||||
|
.notifier_call = gpr_notifier_service_cb,
|
||||||
|
.priority = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct notifier_block modem_service_nb = {
|
||||||
|
.notifier_call = gpr_notifier_service_cb,
|
||||||
|
.priority = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void gpr_dev_release(struct device *dev)
|
static void gpr_dev_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct gpr_device *adev = to_gpr_device(dev);
|
struct gpr_device *adev = to_gpr_device(dev);
|
||||||
@@ -100,7 +291,8 @@ static int gpr_callback(struct rpmsg_device *rpdev, void *buf,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(gpr->dev, "%s: dst_port %x hdr_size %d pkt_size %d\n",__func__ , hdr->dst_port, hdr_size, pkt_size);
|
dev_dbg(gpr->dev, "%s: dst_port %x hdr_size %d pkt_size %d\n",
|
||||||
|
__func__ , hdr->dst_port, hdr_size, pkt_size);
|
||||||
|
|
||||||
svc_id = hdr->dst_port;
|
svc_id = hdr->dst_port;
|
||||||
spin_lock_irqsave(&gpr->svcs_lock, flags);
|
spin_lock_irqsave(&gpr->svcs_lock, flags);
|
||||||
@@ -267,40 +459,78 @@ static void of_register_gpr_devices(struct device *dev)
|
|||||||
static int gpr_probe(struct rpmsg_device *rpdev)
|
static int gpr_probe(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &rpdev->dev;
|
struct device *dev = &rpdev->dev;
|
||||||
struct gpr *gpr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
gpr_priv = devm_kzalloc(dev, sizeof(*gpr_priv), GFP_KERNEL);
|
||||||
gpr = devm_kzalloc(dev, sizeof(*gpr), GFP_KERNEL);
|
if (!gpr_priv)
|
||||||
if (!gpr)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = of_property_read_u32(dev->of_node, "reg", &gpr->dest_domain_id);
|
spin_lock_init(&gpr_priv->gpr_lock);
|
||||||
|
mutex_init(&q6.lock);
|
||||||
|
|
||||||
|
spin_lock(&gpr_priv->gpr_lock);
|
||||||
|
gpr_priv->is_initial_boot = true;
|
||||||
|
spin_unlock(&gpr_priv->gpr_lock);
|
||||||
|
|
||||||
|
ret = of_property_read_u32(dev->of_node, "reg", &gpr_priv->dest_domain_id);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "GPR Domain ID not specified in DT\n");
|
dev_err(dev, "GPR Domain ID not specified in DT\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (GPR_DOMAIN_ADSP == gpr_priv->dest_domain_id) {
|
||||||
|
gpr_subsys_notif_register("gpr_adsp",
|
||||||
|
AUDIO_NOTIFIER_ADSP_DOMAIN,
|
||||||
|
&adsp_service_nb);
|
||||||
|
} else if (GPR_DOMAIN_MODEM == gpr_priv->dest_domain_id) {
|
||||||
|
gpr_subsys_notif_register("gpr_modem",
|
||||||
|
AUDIO_NOTIFIER_MODEM_DOMAIN,
|
||||||
|
&modem_service_nb);
|
||||||
|
} else {
|
||||||
|
dev_err(dev, "%s: invalid dest_domain_id %s\n", __func__,
|
||||||
|
gpr_priv->dest_domain_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
dev_set_drvdata(dev, gpr);
|
dev_info(dev, "%s: registered via subsys_notif_register for domain id(%d)",
|
||||||
gpr->ch = rpdev->ept;
|
__func__, gpr_priv->dest_domain_id );
|
||||||
gpr->dev = dev;
|
|
||||||
spin_lock_init(&gpr->svcs_lock);
|
dev_set_drvdata(dev, gpr_priv);
|
||||||
idr_init(&gpr->svcs_idr);
|
gpr_priv->ch = rpdev->ept;
|
||||||
|
gpr_priv->dev = dev;
|
||||||
|
spin_lock_init(&gpr_priv->svcs_lock);
|
||||||
|
idr_init(&gpr_priv->svcs_idr);
|
||||||
of_register_gpr_devices(dev);
|
of_register_gpr_devices(dev);
|
||||||
|
|
||||||
|
ret = snd_event_client_register(&rpdev->dev, &gpr_ssr_ops, NULL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev,"%s: Registration with SND event fwk failed ret = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gpr_remove_device(struct device *dev, void *null)
|
static int gpr_remove_device(struct device *dev, void *null)
|
||||||
{
|
{
|
||||||
struct gpr_device *adev = to_gpr_device(dev);
|
struct gpr_device *adev = to_gpr_device(dev);
|
||||||
|
|
||||||
device_unregister(&adev->dev);
|
device_unregister(&adev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpr_remove(struct rpmsg_device *rpdev)
|
static void gpr_remove(struct rpmsg_device *rpdev)
|
||||||
{
|
{
|
||||||
|
struct device *dev = &rpdev->dev;
|
||||||
|
snd_event_client_deregister(&rpdev->dev);
|
||||||
|
dev_info(dev, "%s: deregistering via subsys_notif_register for domain_id(%d)",
|
||||||
|
__func__, gpr_priv->dest_domain_id );
|
||||||
|
if (GPR_DOMAIN_ADSP == gpr_priv->dest_domain_id)
|
||||||
|
{
|
||||||
|
gpr_subsys_notif_deregister("gpr_adsp");
|
||||||
|
}
|
||||||
|
else if(GPR_DOMAIN_MODEM == gpr_priv->dest_domain_id)
|
||||||
|
{
|
||||||
|
gpr_subsys_notif_deregister("gpr_modem");
|
||||||
|
}
|
||||||
device_for_each_child(&rpdev->dev, NULL, gpr_remove_device);
|
device_for_each_child(&rpdev->dev, NULL, gpr_remove_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user