blob: 3aff7f17ecb6edd03d304a444eb7d2c768dc54ec [file] [log] [blame]
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/slab.h>
13#include <linux/mutex.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053014#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080015
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053016struct wcd9xxx_slim_sch_rx {
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080017 u32 sph;
18 u32 ch_num;
19 u16 ch_h;
20 u16 grph;
21};
22
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053023struct wcd9xxx_slim_sch_tx {
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080024 u32 sph;
25 u32 ch_num;
26 u16 ch_h;
27 u16 grph;
28};
29
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053030struct wcd9xxx_slim_sch {
31 struct wcd9xxx_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
32 struct wcd9xxx_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080033};
34
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053035static struct wcd9xxx_slim_sch sh_ch;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080036
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053037static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
38 u8 wcd9xxx_pgd_la);
39static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
40 u8 wcd9xxx_pgd_la);
41static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx);
42static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080043
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053044int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080045{
46 int ret = 0;
47
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053048 ret = wcd9xxx_alloc_slim_sh_ch_rx(wcd9xxx, wcd9xxx_pgd_la);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080049 if (ret) {
50 pr_err("%s: Failed to alloc rx slimbus shared channels\n",
51 __func__);
52 goto rx_err;
53 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053054 ret = wcd9xxx_alloc_slim_sh_ch_tx(wcd9xxx, wcd9xxx_pgd_la);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080055 if (ret) {
56 pr_err("%s: Failed to alloc tx slimbus shared channels\n",
57 __func__);
58 goto tx_err;
59 }
60 return 0;
61tx_err:
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053062 wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080063rx_err:
64 return ret;
65}
66
67
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053068int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080069{
70 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053071 ret = wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080072 if (ret < 0) {
73 pr_err("%s: fail to dealloc rx slim ports\n", __func__);
74 goto err;
75 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053076 ret = wcd9xxx_dealloc_slim_sh_ch_tx(wcd9xxx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080077 if (ret < 0) {
78 pr_err("%s: fail to dealloc tx slim ports\n", __func__);
79 goto err;
80 }
81err:
82 return ret;
83}
84
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053085int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080086 unsigned int *rx_ch,
87 unsigned int *tx_ch)
88{
89 int ch_idx = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053090 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
91 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080092
93 for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++)
94 rx_ch[ch_idx] = rx[ch_idx].ch_num;
95 for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++)
96 tx_ch[ch_idx] = tx[ch_idx].ch_num;
97 return 0;
98}
99
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530100static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
101 u8 wcd9xxx_pgd_la)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800102{
103 int ret = 0;
104 u8 ch_idx ;
105 u16 slave_port_id = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530106 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800107
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530108 /*
109 * DSP requires channel number to be between 128 and 255.
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800110 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530111 pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800112 for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) {
113 slave_port_id = (ch_idx + 1 +
114 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
115 rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530116 ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800117 &rx[ch_idx].sph, SLIM_SINK);
118 if (ret < 0) {
119 pr_err("%s: slave port failure id[%d] ret[%d]\n",
120 __func__, slave_port_id, ret);
121 goto err;
122 }
123
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530124 ret = slim_query_ch(wcd9xxx->slim, rx[ch_idx].ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800125 &rx[ch_idx].ch_h);
126 if (ret < 0) {
127 pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
128 __func__, rx[ch_idx].ch_num, ret);
129 goto err;
130 }
131 }
132err:
133 return ret;
134}
135
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530136static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
137 u8 wcd9xxx_pgd_la)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800138{
139 int ret = 0;
140 u8 ch_idx ;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530141 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800142 u16 slave_port_id = 0;
143
Swaminathan Sathappan362a17c2012-04-25 18:09:46 -0700144 pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800145 /* DSP requires channel number to be between 128 and 255. For RX port
146 * use channel numbers from 138 to 144, for TX port
147 * use channel numbers from 128 to 137
148 */
149 for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) {
150 slave_port_id = ch_idx;
151 tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530152 ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800153 &tx[ch_idx].sph, SLIM_SRC);
154 if (ret < 0) {
155 pr_err("%s: slave port failure id[%d] ret[%d]\n",
156 __func__, slave_port_id, ret);
157 goto err;
158 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530159 ret = slim_query_ch(wcd9xxx->slim, tx[ch_idx].ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800160 &tx[ch_idx].ch_h);
161 if (ret < 0) {
162 pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
163 __func__, tx[ch_idx].ch_num, ret);
164 goto err;
165 }
166 }
167err:
168 return ret;
169}
170
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530171static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800172{
173 int idx = 0;
174 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530175 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800176 /* slim_dealloc_ch */
177 for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530178 ret = slim_dealloc_ch(wcd9xxx->slim, rx[idx].ch_h);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800179 if (ret < 0) {
180 pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
181 __func__, ret, rx[idx].ch_h);
182 }
183 }
184 memset(sh_ch.rx, 0, sizeof(sh_ch.rx));
185 return ret;
186}
187
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530188static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800189{
190 int idx = 0;
191 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530192 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800193 /* slim_dealloc_ch */
194 for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530195 ret = slim_dealloc_ch(wcd9xxx->slim, tx[idx].ch_h);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800196 if (ret < 0) {
197 pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
198 __func__, ret, tx[idx].ch_h);
199 }
200 }
201 memset(sh_ch.tx, 0, sizeof(sh_ch.tx));
202 return ret;
203}
204
205/* Enable slimbus slave device for RX path */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530206int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800207 unsigned int ch_cnt, unsigned int rate)
208{
209 u8 i = 0;
210 u16 grph;
211 u32 sph[SLIM_MAX_RX_PORTS] = {0};
212 u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
213 u16 slave_port_id;
214 u8 payload_rx = 0, wm_payload = 0;
215 int ret, idx = 0;
216 unsigned short multi_chan_cfg_reg_addr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530217 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800218 struct slim_ch prop;
219
220 /* Configure slave interface device */
Swaminathan Sathappan362a17c2012-04-25 18:09:46 -0700221 pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800222
223 for (i = 0; i < ch_cnt; i++) {
224 idx = (ch_num[i] - BASE_CH_NUM -
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530225 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800226 ch_h[i] = rx[idx].ch_h;
227 sph[i] = rx[idx].sph;
228 slave_port_id = idx + 1;
229 if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS) ||
230 (slave_port_id == 0)) {
231 pr_err("Slimbus: invalid slave port id: %d",
232 slave_port_id);
233 ret = -EINVAL;
234 goto err;
235 }
236 slave_port_id += SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
237 /* look for the valid port range and chose the
238 * payload accordingly
239 */
240 if ((slave_port_id >
241 SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) &&
Helen Zeng4a7abdb2012-02-21 18:20:46 -0800242 (slave_port_id <=
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800243 SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) {
244 payload_rx = payload_rx |
245 (1 <<
246 (slave_port_id -
247 SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID));
248 } else {
249 ret = -EINVAL;
250 goto err;
251 }
252 multi_chan_cfg_reg_addr =
253 SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id);
254 /* write to interface device */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530255 ret = wcd9xxx_interface_reg_write(wcd9xxx,
256 multi_chan_cfg_reg_addr,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800257 payload_rx);
258 if (ret < 0) {
259 pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
260 __func__,
261 multi_chan_cfg_reg_addr,
262 payload_rx, ret);
263 goto err;
264 }
265 /* configure the slave port for water mark and enable*/
266 wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
267 SLAVE_PORT_WATER_MARK_SHIFT) +
268 SLAVE_PORT_ENABLE;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530269 ret = wcd9xxx_interface_reg_write(wcd9xxx,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800270 SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
271 wm_payload);
272 if (ret < 0) {
273 pr_err("%s:watermark set failure for port[%d] ret[%d]",
274 __func__, slave_port_id, ret);
275 }
276 }
277
278 /* slim_define_ch api */
279 prop.prot = SLIM_AUTO_ISO;
280 prop.baser = SLIM_RATE_4000HZ;
281 prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
282 prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
283 prop.ratem = (rate/4000);
284 prop.sampleszbits = 16;
285
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530286 ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800287 true, &grph);
288 if (ret < 0) {
289 pr_err("%s: slim_define_ch failed ret[%d]\n",
290 __func__, ret);
291 goto err;
292 }
293 for (i = 0; i < ch_cnt; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530294 ret = slim_connect_sink(wcd9xxx->slim, &sph[i],
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800295 1, ch_h[i]);
296 if (ret < 0) {
297 pr_err("%s: slim_connect_sink failed ret[%d]\n",
298 __func__, ret);
299 goto err_close_slim_sch;
300 }
301 }
302 /* slim_control_ch */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530303 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800304 true);
305 if (ret < 0) {
306 pr_err("%s: slim_control_ch failed ret[%d]\n",
307 __func__, ret);
308 goto err_close_slim_sch;
309 }
310 for (i = 0; i < ch_cnt; i++) {
311 idx = (ch_num[i] - BASE_CH_NUM -
312 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
313 rx[idx].grph = grph;
314 }
315 return 0;
316
317err_close_slim_sch:
318 /* release all acquired handles */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530319 wcd9xxx_close_slim_sch_rx(wcd9xxx, ch_num, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800320err:
321 return ret;
322}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530323EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_rx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800324
325/* Enable slimbus slave device for RX path */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530326int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800327 unsigned int ch_cnt, unsigned int rate)
328{
329 u8 i = 0;
330 u8 payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0;
331 u16 grph;
332 u32 sph[SLIM_MAX_TX_PORTS] = {0};
333 u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
334 u16 idx = 0, slave_port_id;
335 int ret = 0;
336 unsigned short multi_chan_cfg_reg_addr;
337
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530338 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800339 struct slim_ch prop;
340
341 pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
342 for (i = 0; i < ch_cnt; i++) {
343 idx = (ch_num[i] - BASE_CH_NUM);
344 ch_h[i] = tx[idx].ch_h;
345 sph[i] = tx[idx].sph;
346 slave_port_id = idx ;
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800347 if (slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) {
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800348 pr_err("SLIMbus: invalid slave port id: %d",
349 slave_port_id);
350 ret = -EINVAL;
351 goto err;
352 }
353 /* look for the valid port range and chose the
354 * payload accordingly
355 */
356 if (slave_port_id <=
357 SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
358 payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700359 } else if (slave_port_id <=
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800360 SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) {
361 payload_tx_1 = payload_tx_1 |
362 (1 <<
363 (slave_port_id -
364 SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
365 } else {
366 ret = -EINVAL;
367 goto err;
368 }
369 multi_chan_cfg_reg_addr =
370 SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
371 /* write to interface device */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530372 ret = wcd9xxx_interface_reg_write(wcd9xxx,
373 multi_chan_cfg_reg_addr,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800374 payload_tx_0);
375 if (ret < 0) {
376 pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
377 __func__,
378 multi_chan_cfg_reg_addr,
379 payload_tx_0, ret);
380 goto err;
381 }
382 multi_chan_cfg_reg_addr =
383 SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
384 /* ports 8,9 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530385 ret = wcd9xxx_interface_reg_write(wcd9xxx,
386 multi_chan_cfg_reg_addr,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800387 payload_tx_1);
388 if (ret < 0) {
389 pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
390 __func__,
391 multi_chan_cfg_reg_addr,
392 payload_tx_1, ret);
393 goto err;
394 }
395 /* configure the slave port for water mark and enable*/
396 wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
397 SLAVE_PORT_WATER_MARK_SHIFT) +
398 SLAVE_PORT_ENABLE;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530399 ret = wcd9xxx_interface_reg_write(wcd9xxx,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800400 SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
401 wm_payload);
402 if (ret < 0) {
403 pr_err("%s:watermark set failure for port[%d] ret[%d]",
404 __func__,
405 slave_port_id, ret);
406 }
407 }
408
409 /* slim_define_ch api */
410 prop.prot = SLIM_AUTO_ISO;
411 prop.baser = SLIM_RATE_4000HZ;
412 prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
413 prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
414 prop.ratem = (rate/4000);
415 prop.sampleszbits = 16;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530416 ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800417 true, &grph);
418 if (ret < 0) {
419 pr_err("%s: slim_define_ch failed ret[%d]\n",
420 __func__, ret);
421 goto err;
422 }
423 for (i = 0; i < ch_cnt; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530424 ret = slim_connect_src(wcd9xxx->slim, sph[i],
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800425 ch_h[i]);
426 if (ret < 0) {
427 pr_err("%s: slim_connect_src failed ret[%d]\n",
428 __func__, ret);
429 goto err;
430 }
431 }
432 /* slim_control_ch */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530433 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800434 true);
435 if (ret < 0) {
436 pr_err("%s: slim_control_ch failed ret[%d]\n",
437 __func__, ret);
438 goto err;
439 }
440 for (i = 0; i < ch_cnt; i++) {
441 idx = (ch_num[i] - BASE_CH_NUM);
442 tx[idx].grph = grph;
443 }
444 return 0;
445err:
446 /* release all acquired handles */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530447 wcd9xxx_close_slim_sch_tx(wcd9xxx, ch_num, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800448 return ret;
449}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530450EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_tx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800451
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530452int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800453 unsigned int ch_cnt)
454{
455 u16 grph = 0;
456 u32 sph[SLIM_MAX_RX_PORTS] = {0};
457 int i = 0 , idx = 0;
458 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530459 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800460
Swaminathan Sathappan362a17c2012-04-25 18:09:46 -0700461 pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800462 for (i = 0; i < ch_cnt; i++) {
463 idx = (ch_num[i] - BASE_CH_NUM -
464 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
465 sph[i] = rx[idx].sph;
466 grph = rx[idx].grph;
467 }
468
469 /* slim_disconnect_port */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530470 ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800471 if (ret < 0) {
472 pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
473 __func__, ret);
474 }
475 /* slim_control_ch (REMOVE) */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530476 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800477 if (ret < 0) {
478 pr_err("%s: slim_control_ch failed ret[%d]\n",
479 __func__, ret);
480 goto err;
481 }
482 for (i = 0; i < ch_cnt; i++) {
483 idx = (ch_num[i] - BASE_CH_NUM -
484 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
485 rx[idx].grph = 0;
486 }
487err:
488 return ret;
489}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530490EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800491
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530492int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800493 unsigned int ch_cnt)
494{
495 u16 grph = 0;
496 u32 sph[SLIM_MAX_TX_PORTS] = {0};
497 int ret = 0;
498 int i = 0 , idx = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530499 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800500
Swaminathan Sathappan362a17c2012-04-25 18:09:46 -0700501 pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800502 for (i = 0; i < ch_cnt; i++) {
503 idx = (ch_num[i] - BASE_CH_NUM);
504 sph[i] = tx[idx].sph;
505 grph = tx[idx].grph;
506 }
507 /* slim_disconnect_port */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530508 ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800509 if (ret < 0) {
510 pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
511 __func__, ret);
512 }
513 /* slim_control_ch (REMOVE) */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530514 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800515 if (ret < 0) {
516 pr_err("%s: slim_control_ch failed ret[%d]\n",
517 __func__, ret);
518 goto err;
519 }
520 for (i = 0; i < ch_cnt; i++) {
521 idx = (ch_num[i] - BASE_CH_NUM);
522 tx[idx].grph = 0;
523 }
524err:
525 return ret;
526}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530527EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_tx);