Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d146e7c authored by Xiaoyu Ye's avatar Xiaoyu Ye
Browse files

driver: soc: apr: Clean up files and codes related to SMD



APR files and codes based on SMD are no longer needed for
future targets. Clean up them from kernel 4.9 codebase.

CRs-Fixed: 2006836
Change-Id: I03bc1088dd54d900974c2ed5ce59a1c419ff95b8
Signed-off-by: default avatarXiaoyu Ye <benyxy@codeaurora.org>
parent deda3be7
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o
obj-$(CONFIG_MSM_QDSP6_APRV3) += apr.o apr_v3.o apr_tal.o
obj-$(CONFIG_MSM_QDSP6_APRV2_GLINK) += apr.o apr_v2.o apr_tal_glink.o
obj-$(CONFIG_MSM_QDSP6_APRV3_GLINK) += apr.o apr_v3.o apr_tal_glink.o
obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += msm_audio_ion.o
+0 −298
Original line number Diff line number Diff line
/* Copyright (c) 2010-2011, 2013-2014, 2016-2017 The Linux Foundation.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <soc/qcom/smd.h>
#include <linux/qdsp6v2/apr_tal.h>

static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = {
	{
		"apr_audio_svc",
		"apr_voice_svc",
	},
	{
		"apr_audio_svc",
		"apr_voice_svc",
	},
};

struct apr_svc_ch_dev apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX];

int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
			struct apr_pkt_priv *pkt_priv, int len)
{
	int w_len;
	unsigned long flags;

	spin_lock_irqsave(&apr_ch->w_lock, flags);
	if (smd_write_avail(apr_ch->ch) < len) {
		spin_unlock_irqrestore(&apr_ch->w_lock, flags);
		return -EAGAIN;
	}

	w_len = smd_write(apr_ch->ch, data, len);
	spin_unlock_irqrestore(&apr_ch->w_lock, flags);

	pr_debug("apr_tal:w_len = %d\n", w_len);

	if (w_len != len) {
		pr_err("apr_tal: Error in write\n");
		return -ENETRESET;
	}
	return w_len;
}

int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
			struct apr_pkt_priv *pkt_priv, int len)
{
	int rc = 0, retries = 0;

	if (!apr_ch->ch)
		return -EINVAL;

	do {
		if (rc == -EAGAIN)
			udelay(50);

		rc = __apr_tal_write(apr_ch, data, pkt_priv, len);
	} while (rc == -EAGAIN && retries++ < 300);

	if (rc == -EAGAIN)
		pr_err("apr_tal: TIMEOUT for write\n");

	return rc;
}

static void apr_tal_notify(void *priv, unsigned int event)
{
	struct apr_svc_ch_dev *apr_ch = priv;
	int len, r_len, sz;
	int pkt_cnt = 0;
	unsigned long flags;

	pr_debug("event = %d\n", event);
	switch (event) {
	case SMD_EVENT_DATA:
		pkt_cnt = 0;
		spin_lock_irqsave(&apr_ch->lock, flags);
check_pending:
		len = smd_read_avail(apr_ch->ch);
		if (len < 0) {
			pr_err("apr_tal: Invalid Read Event :%d\n", len);
			spin_unlock_irqrestore(&apr_ch->lock, flags);
			return;
		}
		sz = smd_cur_packet_size(apr_ch->ch);
		if (sz < 0) {
			pr_debug("pkt size is zero\n");
			spin_unlock_irqrestore(&apr_ch->lock, flags);
			return;
		}
		if (!len && !sz && !pkt_cnt)
			goto check_write_avail;
		if (!len) {
			pr_debug("len = %d pkt_cnt = %d\n", len, pkt_cnt);
			spin_unlock_irqrestore(&apr_ch->lock, flags);
			return;
		}
		r_len = smd_read_from_cb(apr_ch->ch, apr_ch->data, len);
		if (len != r_len) {
			pr_err("apr_tal: Invalid Read\n");
			spin_unlock_irqrestore(&apr_ch->lock, flags);
			return;
		}
		pkt_cnt++;
		pr_debug("%d %d %d\n", len, sz, pkt_cnt);
		if (apr_ch->func)
			apr_ch->func(apr_ch->data, r_len, apr_ch->priv);
		goto check_pending;
check_write_avail:
		if (smd_write_avail(apr_ch->ch))
			wake_up(&apr_ch->wait);
		spin_unlock_irqrestore(&apr_ch->lock, flags);
		break;
	case SMD_EVENT_OPEN:
		pr_debug("apr_tal: SMD_EVENT_OPEN\n");
		apr_ch->smd_state = 1;
		wake_up(&apr_ch->wait);
		break;
	case SMD_EVENT_CLOSE:
		pr_debug("apr_tal: SMD_EVENT_CLOSE\n");
		break;
	}
}

int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
			int num_of_intents, uint32_t size)
{
	/* Rx intents configuration is required for Glink
	 * but not for SMD. No-op for this function.
	 */
	return 0;
}

struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest,
				uint32_t dl, apr_svc_cb_fn func, void *priv)
{
	int rc;

	if ((clnt >= APR_CLIENT_MAX) || (dest >= APR_DEST_MAX) ||
						(dl >= APR_DL_MAX)) {
		pr_err("apr_tal: Invalid params\n");
		return NULL;
	}

	if (apr_svc_ch[dl][dest][clnt].ch) {
		pr_err("apr_tal: This channel alreday openend\n");
		return NULL;
	}

	mutex_lock(&apr_svc_ch[dl][dest][clnt].m_lock);
	if (!apr_svc_ch[dl][dest][clnt].dest_state) {
		rc = wait_event_timeout(apr_svc_ch[dl][dest][clnt].dest,
			apr_svc_ch[dl][dest][clnt].dest_state,
				msecs_to_jiffies(APR_OPEN_TIMEOUT_MS));
		if (rc == 0) {
			pr_err("apr_tal:open timeout\n");
			mutex_unlock(&apr_svc_ch[dl][dest][clnt].m_lock);
			return NULL;
		}
		pr_debug("apr_tal:Wakeup done\n");
		apr_svc_ch[dl][dest][clnt].dest_state = 0;
	}
	rc = smd_named_open_on_edge(svc_names[dest][clnt], dest,
			&apr_svc_ch[dl][dest][clnt].ch,
			&apr_svc_ch[dl][dest][clnt],
			apr_tal_notify);
	if (rc < 0) {
		pr_err("apr_tal: smd_open failed %s\n",
					svc_names[dest][clnt]);
		mutex_unlock(&apr_svc_ch[dl][dest][clnt].m_lock);
		return NULL;
	}
	rc = wait_event_timeout(apr_svc_ch[dl][dest][clnt].wait,
		(apr_svc_ch[dl][dest][clnt].smd_state == 1), 5 * HZ);
	if (rc == 0) {
		pr_err("apr_tal:TIMEOUT for OPEN event\n");
		mutex_unlock(&apr_svc_ch[dl][dest][clnt].m_lock);
		apr_tal_close(&apr_svc_ch[dl][dest][clnt]);
		return NULL;
	}

	smd_disable_read_intr(apr_svc_ch[dl][dest][clnt].ch);

	if (!apr_svc_ch[dl][dest][clnt].dest_state) {
		apr_svc_ch[dl][dest][clnt].dest_state = 1;
		pr_debug("apr_tal:Waiting for apr svc init\n");
		msleep(200);
		pr_debug("apr_tal:apr svc init done\n");
	}
	apr_svc_ch[dl][dest][clnt].smd_state = 0;

	apr_svc_ch[dl][dest][clnt].func = func;
	apr_svc_ch[dl][dest][clnt].priv = priv;
	mutex_unlock(&apr_svc_ch[dl][dest][clnt].m_lock);

	return &apr_svc_ch[dl][dest][clnt];
}

int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
{
	int r;

	if (!apr_ch->ch)
		return -EINVAL;

	mutex_lock(&apr_ch->m_lock);
	r = smd_close(apr_ch->ch);
	apr_ch->ch = NULL;
	apr_ch->func = NULL;
	apr_ch->priv = NULL;
	mutex_unlock(&apr_ch->m_lock);
	return r;
}

static int apr_smd_probe(struct platform_device *pdev)
{
	int dest;
	int clnt;

	if (pdev->id == APR_DEST_MODEM) {
		pr_info("apr_tal:Modem Is Up\n");
		dest = APR_DEST_MODEM;
		if (!strcmp(pdev->name, "apr_audio_svc"))
			clnt = APR_CLIENT_AUDIO;
		else
			clnt = APR_CLIENT_VOICE;
		apr_svc_ch[APR_DL_SMD][dest][clnt].dest_state = 1;
		wake_up(&apr_svc_ch[APR_DL_SMD][dest][clnt].dest);
	} else if (pdev->id == APR_DEST_QDSP6) {
		pr_info("apr_tal:Q6 Is Up\n");
		dest = APR_DEST_QDSP6;
		clnt = APR_CLIENT_AUDIO;
		apr_svc_ch[APR_DL_SMD][dest][clnt].dest_state = 1;
		wake_up(&apr_svc_ch[APR_DL_SMD][dest][clnt].dest);
	} else
		pr_err("apr_tal:Invalid Dest Id: %d\n", pdev->id);

	return 0;
}

static struct platform_driver apr_q6_driver = {
	.probe = apr_smd_probe,
	.driver = {
		.name = "apr_audio_svc",
		.owner = THIS_MODULE,
	},
};

static struct platform_driver apr_modem_driver = {
	.probe = apr_smd_probe,
	.driver = {
		.name = "apr_voice_svc",
		.owner = THIS_MODULE,
	},
};

static int __init apr_tal_init(void)
{
	int i, j, k;

	for (i = 0; i < APR_DL_MAX; i++)
		for (j = 0; j < APR_DEST_MAX; j++)
			for (k = 0; k < APR_CLIENT_MAX; k++) {
				init_waitqueue_head(&apr_svc_ch[i][j][k].wait);
				init_waitqueue_head(&apr_svc_ch[i][j][k].dest);
				spin_lock_init(&apr_svc_ch[i][j][k].lock);
				spin_lock_init(&apr_svc_ch[i][j][k].w_lock);
				mutex_init(&apr_svc_ch[i][j][k].m_lock);
			}
	platform_driver_register(&apr_q6_driver);
	platform_driver_register(&apr_modem_driver);
	return 0;
}
device_initcall(apr_tal_init);
+0 −17
Original line number Diff line number Diff line
@@ -75,8 +75,6 @@ int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
		int num_of_intents, uint32_t size);


#if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \
	 defined(CONFIG_MSM_QDSP6_APRV3_GLINK)
struct apr_svc_ch_dev {
	void               *handle;
	spinlock_t         w_lock;
@@ -88,20 +86,5 @@ struct apr_svc_ch_dev {
	unsigned int       channel_state;
	bool               if_remote_intent_ready;
};
#else
struct apr_svc_ch_dev {
	struct smd_channel *ch;
	spinlock_t         lock;
	spinlock_t         w_lock;
	struct mutex       m_lock;
	apr_svc_cb_fn      func;
	char               data[APR_MAX_BUF];
	wait_queue_head_t  wait;
	void               *priv;
	uint32_t           smd_state;
	wait_queue_head_t  dest;
	uint32_t           dest_state;
};
#endif

#endif