blob: ed494e451232640e19ac4a55405ab56256a300ea [file] [log] [blame]
Joonwoo Park91d95462012-08-02 10:55:54 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
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/types.h>
15#include <linux/uaccess.h>
16#include <linux/spinlock.h>
17#include <linux/kernel.h>
18#include <mach/qdsp6v2/apr.h>
19#include <mach/qdsp6v2/apr_tal.h>
20#include <mach/qdsp6v2/dsp_debug.h>
21
Ravishankar Sarawadi14dfeac2012-09-25 19:28:57 -070022static const char *lpass_subsys_name = "adsp";
23
Joonwoo Park91d95462012-08-02 10:55:54 -070024struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
25 uint32_t src_port, void *priv)
26{
27 struct apr_client *client;
28 int client_id = 0;
29 int svc_idx = 0;
30 int svc_id = 0;
31 int dest_id = 0;
32 int temp_port = 0;
33 struct apr_svc *svc = NULL;
34 int rc = 0;
35
36 if (!dest || !svc_name || !svc_fn)
37 return NULL;
38
39 if (!strncmp(dest, "ADSP", 4))
40 dest_id = APR_DEST_QDSP6;
41 else if (!strncmp(dest, "MODEM", 5)) {
42 dest_id = APR_DEST_MODEM;
43 } else {
44 pr_err("APR: wrong destination\n");
45 goto done;
46 }
47
48 if ((dest_id == APR_DEST_QDSP6)) {
49 if (apr_get_q6_state() != APR_SUBSYS_LOADED) {
50 pr_err("%s: adsp not up\n", __func__);
51 return NULL;
52 }
Ravishankar Sarawadi14dfeac2012-09-25 19:28:57 -070053 pr_info("%s: adsp Up\n", __func__);
Joonwoo Park91d95462012-08-02 10:55:54 -070054 } else if ((dest_id == APR_DEST_MODEM) &&
55 (apr_get_modem_state() == APR_SUBSYS_DOWN)) {
56 pr_info("%s: Wait for modem to bootup\n", __func__);
57 rc = apr_wait_for_device_up(dest_id);
58 if (rc == 0) {
59 pr_err("%s: Modem is not Up\n", __func__);
60 return NULL;
61 }
62 pr_info("%s: modem Up\n", __func__);
63 }
64
65 if (apr_get_svc(svc_name, dest_id, &client_id, &svc_idx, &svc_id)) {
66 pr_err("%s: apr_get_svc failed\n", __func__);
67 goto done;
68 }
69
70 /* APRv2 doen't load ADSP image automatically */
71
72 client = apr_get_client(dest_id, client_id);
73 mutex_lock(&client->m_lock);
74 if (!client->handle) {
75 client->handle = apr_tal_open(client_id, dest_id, APR_DL_SMD,
76 apr_cb_func, NULL);
77 if (!client->handle) {
78 svc = NULL;
79 pr_err("APR: Unable to open handle\n");
80 mutex_unlock(&client->m_lock);
81 goto done;
82 }
83 }
84 mutex_unlock(&client->m_lock);
85 svc = &client->svc[svc_idx];
86 mutex_lock(&svc->m_lock);
87 client->id = client_id;
88 if (svc->need_reset) {
89 mutex_unlock(&svc->m_lock);
90 pr_err("APR: Service needs reset\n");
91 goto done;
92 }
93 svc->priv = priv;
94 svc->id = svc_id;
95 svc->dest_id = dest_id;
96 svc->client_id = client_id;
97 if (src_port != 0xFFFFFFFF) {
98 temp_port = ((src_port >> 8) * 8) + (src_port & 0xFF);
99 pr_debug("port = %d t_port = %d\n", src_port, temp_port);
100 if (temp_port >= APR_MAX_PORTS || temp_port < 0) {
101 pr_err("APR: temp_port out of bounds\n");
102 mutex_unlock(&svc->m_lock);
103 return NULL;
104 }
105 if (!svc->port_cnt && !svc->svc_cnt)
106 client->svc_cnt++;
107 svc->port_cnt++;
108 svc->port_fn[temp_port] = svc_fn;
109 svc->port_priv[temp_port] = priv;
110 } else {
111 if (!svc->fn) {
112 if (!svc->port_cnt && !svc->svc_cnt)
113 client->svc_cnt++;
114 svc->fn = svc_fn;
115 if (svc->port_cnt)
116 svc->svc_cnt++;
117 }
118 }
119
120 mutex_unlock(&svc->m_lock);
121done:
122 return svc;
123}
124
125void apr_set_subsys_state(void)
126{
127 apr_set_q6_state(APR_SUBSYS_DOWN);
128 apr_set_modem_state(APR_SUBSYS_UP);
129}
Ravishankar Sarawadi14dfeac2012-09-25 19:28:57 -0700130
131const char *apr_get_lpass_subsys_name(void)
132{
133 return lpass_subsys_name;
134}