blob: d7ed9194260ed42599a50d814b7009cc50a6d8d3 [file] [log] [blame]
Joonwoo Park91d95462012-08-02 10:55:54 -07001/*
Duy Truong790f06d2013-02-13 16:38:12 -08002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Joonwoo Park91d95462012-08-02 10:55:54 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/uaccess.h>
18#include <linux/err.h>
19#include <mach/qdsp6v2/apr.h>
20#include <mach/qdsp6v2/apr_tal.h>
21#include <mach/qdsp6v2/dsp_debug.h>
Joonwoo Park91d95462012-08-02 10:55:54 -070022
Ravishankar Sarawadi14dfeac2012-09-25 19:28:57 -070023static const char *lpass_subsys_name = "lpass";
24
Joonwoo Park91d95462012-08-02 10:55:54 -070025struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
26 uint32_t src_port, void *priv)
27{
28 struct apr_client *client;
29 int client_id = 0;
30 int svc_idx = 0;
31 int svc_id = 0;
32 int dest_id = 0;
33 int temp_port = 0;
34 struct apr_svc *svc = NULL;
35 int rc = 0;
36
37 if (!dest || !svc_name || !svc_fn)
38 return NULL;
39
40 if (!strncmp(dest, "ADSP", 4))
41 dest_id = APR_DEST_QDSP6;
42 else if (!strncmp(dest, "MODEM", 5)) {
43 dest_id = APR_DEST_MODEM;
44 } else {
45 pr_err("APR: wrong destination\n");
46 goto done;
47 }
48
49 if (dest_id == APR_DEST_QDSP6 &&
50 apr_get_q6_state() == APR_SUBSYS_DOWN) {
51 pr_info("%s: Wait for Lpass to bootup\n", __func__);
52 rc = apr_wait_for_device_up(dest_id);
53 if (rc == 0) {
54 pr_err("%s: DSP is not Up\n", __func__);
55 return NULL;
56 }
57 pr_info("%s: Lpass Up\n", __func__);
58 } else if (dest_id == APR_DEST_MODEM &&
59 (apr_get_modem_state() == APR_SUBSYS_DOWN)) {
60 pr_info("%s: Wait for modem to bootup\n", __func__);
61 rc = apr_wait_for_device_up(dest_id);
62 if (rc == 0) {
63 pr_err("%s: Modem is not Up\n", __func__);
64 return NULL;
65 }
66 pr_info("%s: modem Up\n", __func__);
67 }
68
69 if (apr_get_svc(svc_name, dest_id, &client_id, &svc_idx, &svc_id)) {
70 pr_err("%s: apr_get_svc failed\n", __func__);
71 goto done;
72 }
73
74 /* APRv1 loads ADSP image automatically */
75 apr_load_adsp_image();
76
77 client = apr_get_client(dest_id, client_id);
78 mutex_lock(&client->m_lock);
79 if (!client->handle) {
80 client->handle = apr_tal_open(client_id, dest_id, APR_DL_SMD,
81 apr_cb_func, NULL);
82 if (!client->handle) {
83 svc = NULL;
84 pr_err("APR: Unable to open handle\n");
85 mutex_unlock(&client->m_lock);
86 goto done;
87 }
88 }
89 mutex_unlock(&client->m_lock);
90 svc = &client->svc[svc_idx];
91 mutex_lock(&svc->m_lock);
92 client->id = client_id;
93 if (svc->need_reset) {
94 mutex_unlock(&svc->m_lock);
95 pr_err("APR: Service needs reset\n");
96 goto done;
97 }
98 svc->priv = priv;
99 svc->id = svc_id;
100 svc->dest_id = dest_id;
101 svc->client_id = client_id;
102 if (src_port != 0xFFFFFFFF) {
103 temp_port = ((src_port >> 8) * 8) + (src_port & 0xFF);
104 pr_debug("port = %d t_port = %d\n", src_port, temp_port);
105 if (temp_port >= APR_MAX_PORTS || temp_port < 0) {
106 pr_err("APR: temp_port out of bounds\n");
107 mutex_unlock(&svc->m_lock);
108 return NULL;
109 }
110 if (!svc->port_cnt && !svc->svc_cnt)
111 client->svc_cnt++;
112 svc->port_cnt++;
113 svc->port_fn[temp_port] = svc_fn;
114 svc->port_priv[temp_port] = priv;
115 } else {
116 if (!svc->fn) {
117 if (!svc->port_cnt && !svc->svc_cnt)
118 client->svc_cnt++;
119 svc->fn = svc_fn;
120 if (svc->port_cnt)
121 svc->svc_cnt++;
122 }
123 }
124
125 mutex_unlock(&svc->m_lock);
126done:
127 return svc;
128}
129
130void apr_set_subsys_state(void)
131{
132 apr_set_q6_state(APR_SUBSYS_UP);
133 apr_set_modem_state(APR_SUBSYS_UP);
134}
Ravishankar Sarawadi14dfeac2012-09-25 19:28:57 -0700135
136const char *apr_get_lpass_subsys_name(void)
137{
138 return lpass_subsys_name;
139}