blob: acef55e50cd3271908dbda3ace446d07c08f145d [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
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530144 pr_err("%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 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530221 pr_err("%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 ;
347 if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) ||
348 (slave_port_id == 0)) {
349 pr_err("SLIMbus: invalid slave port id: %d",
350 slave_port_id);
351 ret = -EINVAL;
352 goto err;
353 }
354 /* look for the valid port range and chose the
355 * payload accordingly
356 */
357 if (slave_port_id <=
358 SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
359 payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
360 } else if (slave_port_id <
361 SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) {
362 payload_tx_1 = payload_tx_1 |
363 (1 <<
364 (slave_port_id -
365 SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
366 } else {
367 ret = -EINVAL;
368 goto err;
369 }
370 multi_chan_cfg_reg_addr =
371 SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
372 /* write to interface device */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530373 ret = wcd9xxx_interface_reg_write(wcd9xxx,
374 multi_chan_cfg_reg_addr,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800375 payload_tx_0);
376 if (ret < 0) {
377 pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
378 __func__,
379 multi_chan_cfg_reg_addr,
380 payload_tx_0, ret);
381 goto err;
382 }
383 multi_chan_cfg_reg_addr =
384 SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
385 /* ports 8,9 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530386 ret = wcd9xxx_interface_reg_write(wcd9xxx,
387 multi_chan_cfg_reg_addr,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800388 payload_tx_1);
389 if (ret < 0) {
390 pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
391 __func__,
392 multi_chan_cfg_reg_addr,
393 payload_tx_1, ret);
394 goto err;
395 }
396 /* configure the slave port for water mark and enable*/
397 wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
398 SLAVE_PORT_WATER_MARK_SHIFT) +
399 SLAVE_PORT_ENABLE;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530400 ret = wcd9xxx_interface_reg_write(wcd9xxx,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800401 SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
402 wm_payload);
403 if (ret < 0) {
404 pr_err("%s:watermark set failure for port[%d] ret[%d]",
405 __func__,
406 slave_port_id, ret);
407 }
408 }
409
410 /* slim_define_ch api */
411 prop.prot = SLIM_AUTO_ISO;
412 prop.baser = SLIM_RATE_4000HZ;
413 prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
414 prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
415 prop.ratem = (rate/4000);
416 prop.sampleszbits = 16;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530417 ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800418 true, &grph);
419 if (ret < 0) {
420 pr_err("%s: slim_define_ch failed ret[%d]\n",
421 __func__, ret);
422 goto err;
423 }
424 for (i = 0; i < ch_cnt; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530425 ret = slim_connect_src(wcd9xxx->slim, sph[i],
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800426 ch_h[i]);
427 if (ret < 0) {
428 pr_err("%s: slim_connect_src failed ret[%d]\n",
429 __func__, ret);
430 goto err;
431 }
432 }
433 /* slim_control_ch */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530434 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800435 true);
436 if (ret < 0) {
437 pr_err("%s: slim_control_ch failed ret[%d]\n",
438 __func__, ret);
439 goto err;
440 }
441 for (i = 0; i < ch_cnt; i++) {
442 idx = (ch_num[i] - BASE_CH_NUM);
443 tx[idx].grph = grph;
444 }
445 return 0;
446err:
447 /* release all acquired handles */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530448 wcd9xxx_close_slim_sch_tx(wcd9xxx, ch_num, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800449 return ret;
450}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530451EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_tx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800452
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530453int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800454 unsigned int ch_cnt)
455{
456 u16 grph = 0;
457 u32 sph[SLIM_MAX_RX_PORTS] = {0};
458 int i = 0 , idx = 0;
459 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530460 struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800461
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530462 pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800463 for (i = 0; i < ch_cnt; i++) {
464 idx = (ch_num[i] - BASE_CH_NUM -
465 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
466 sph[i] = rx[idx].sph;
467 grph = rx[idx].grph;
468 }
469
470 /* slim_disconnect_port */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530471 ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800472 if (ret < 0) {
473 pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
474 __func__, ret);
475 }
476 /* slim_control_ch (REMOVE) */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530477 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800478 if (ret < 0) {
479 pr_err("%s: slim_control_ch failed ret[%d]\n",
480 __func__, ret);
481 goto err;
482 }
483 for (i = 0; i < ch_cnt; i++) {
484 idx = (ch_num[i] - BASE_CH_NUM -
485 SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
486 rx[idx].grph = 0;
487 }
488err:
489 return ret;
490}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530491EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800492
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530493int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800494 unsigned int ch_cnt)
495{
496 u16 grph = 0;
497 u32 sph[SLIM_MAX_TX_PORTS] = {0};
498 int ret = 0;
499 int i = 0 , idx = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530500 struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800501
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530502 pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800503 for (i = 0; i < ch_cnt; i++) {
504 idx = (ch_num[i] - BASE_CH_NUM);
505 sph[i] = tx[idx].sph;
506 grph = tx[idx].grph;
507 }
508 /* slim_disconnect_port */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530509 ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800510 if (ret < 0) {
511 pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
512 __func__, ret);
513 }
514 /* slim_control_ch (REMOVE) */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530515 ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800516 if (ret < 0) {
517 pr_err("%s: slim_control_ch failed ret[%d]\n",
518 __func__, ret);
519 goto err;
520 }
521 for (i = 0; i < ch_cnt; i++) {
522 idx = (ch_num[i] - BASE_CH_NUM);
523 tx[idx].grph = 0;
524 }
525err:
526 return ret;
527}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530528EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_tx);