Lines Matching +full:q6adm +full:- +full:routing
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
18 #include "q6adm.h"
21 #include "q6dsp-common.h"
22 #include "q6dsp-errno.h"
53 struct q6adm *adm;
56 struct q6adm { struct
90 static struct q6copp *q6adm_find_copp(struct q6adm *adm, int port_idx, in q6adm_find_copp()
97 spin_lock_irqsave(&adm->copps_list_lock, flags); in q6adm_find_copp()
98 list_for_each_entry(c, &adm->copps_list, node) { in q6adm_find_copp()
99 if ((port_idx == c->afe_port) && (copp_idx == c->copp_idx)) { in q6adm_find_copp()
101 kref_get(&c->refcount); in q6adm_find_copp()
106 spin_unlock_irqrestore(&adm->copps_list_lock, flags); in q6adm_find_copp()
115 struct q6adm *adm = c->adm; in q6adm_free_copp()
118 spin_lock_irqsave(&adm->copps_list_lock, flags); in q6adm_free_copp()
119 clear_bit(c->copp_idx, &adm->copp_bitmap[c->afe_port]); in q6adm_free_copp()
120 list_del(&c->node); in q6adm_free_copp()
121 spin_unlock_irqrestore(&adm->copps_list_lock, flags); in q6adm_free_copp()
127 struct aprv2_ibasic_rsp_result_t *result = data->payload; in q6adm_callback()
129 struct apr_hdr *hdr = &data->hdr; in q6adm_callback()
131 struct q6adm *adm = dev_get_drvdata(&adev->dev); in q6adm_callback()
133 if (!data->payload_size) in q6adm_callback()
136 copp_idx = (hdr->token) & 0XFF; in q6adm_callback()
137 port_idx = ((hdr->token) >> 16) & 0xFF; in q6adm_callback()
139 dev_err(&adev->dev, "Invalid port idx %d token %d\n", in q6adm_callback()
140 port_idx, hdr->token); in q6adm_callback()
144 dev_err(&adev->dev, "Invalid copp idx %d token %d\n", in q6adm_callback()
145 copp_idx, hdr->token); in q6adm_callback()
149 switch (hdr->opcode) { in q6adm_callback()
151 if (result->status != 0) { in q6adm_callback()
152 dev_err(&adev->dev, "cmd = 0x%x return error = 0x%x\n", in q6adm_callback()
153 result->opcode, result->status); in q6adm_callback()
155 switch (result->opcode) { in q6adm_callback()
162 copp->result = *result; in q6adm_callback()
163 wake_up(&copp->wait); in q6adm_callback()
164 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_callback()
167 adm->result = *result; in q6adm_callback()
168 wake_up(&adm->matrix_map_wait); in q6adm_callback()
172 dev_err(&adev->dev, "Unknown Cmd: 0x%x\n", in q6adm_callback()
173 result->opcode); in q6adm_callback()
183 } __packed *open = data->payload; in q6adm_callback()
189 if (open->copp_id == INVALID_COPP_ID) { in q6adm_callback()
190 dev_err(&adev->dev, "Invalid coppid rxed %d\n", in q6adm_callback()
191 open->copp_id); in q6adm_callback()
192 copp->result.status = ADSP_EBADPARAM; in q6adm_callback()
193 wake_up(&copp->wait); in q6adm_callback()
194 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_callback()
197 copp->result.opcode = hdr->opcode; in q6adm_callback()
198 copp->id = open->copp_id; in q6adm_callback()
199 wake_up(&copp->wait); in q6adm_callback()
200 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_callback()
204 dev_err(&adev->dev, "Unknown cmd:0x%x\n", in q6adm_callback()
205 hdr->opcode); in q6adm_callback()
212 static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx) in q6adm_alloc_copp()
217 idx = find_first_zero_bit(&adm->copp_bitmap[port_idx], in q6adm_alloc_copp()
221 return ERR_PTR(-EBUSY); in q6adm_alloc_copp()
225 return ERR_PTR(-ENOMEM); in q6adm_alloc_copp()
227 set_bit(idx, &adm->copp_bitmap[port_idx]); in q6adm_alloc_copp()
228 c->copp_idx = idx; in q6adm_alloc_copp()
229 c->afe_port = port_idx; in q6adm_alloc_copp()
230 c->adm = adm; in q6adm_alloc_copp()
232 init_waitqueue_head(&c->wait); in q6adm_alloc_copp()
237 static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp, in q6adm_apr_send_copp_pkt()
240 struct device *dev = adm->dev; in q6adm_apr_send_copp_pkt()
241 uint32_t opcode = pkt->hdr.opcode; in q6adm_apr_send_copp_pkt()
244 mutex_lock(&adm->lock); in q6adm_apr_send_copp_pkt()
245 copp->result.opcode = 0; in q6adm_apr_send_copp_pkt()
246 copp->result.status = 0; in q6adm_apr_send_copp_pkt()
247 ret = apr_send_pkt(adm->apr, pkt); in q6adm_apr_send_copp_pkt()
250 ret = -EINVAL; in q6adm_apr_send_copp_pkt()
256 ret = wait_event_timeout(copp->wait, in q6adm_apr_send_copp_pkt()
257 (copp->result.opcode == opcode) || in q6adm_apr_send_copp_pkt()
258 (copp->result.opcode == rsp_opcode), in q6adm_apr_send_copp_pkt()
261 ret = wait_event_timeout(copp->wait, in q6adm_apr_send_copp_pkt()
262 (copp->result.opcode == opcode), in q6adm_apr_send_copp_pkt()
267 ret = -ETIMEDOUT; in q6adm_apr_send_copp_pkt()
268 } else if (copp->result.status > 0) { in q6adm_apr_send_copp_pkt()
270 copp->result.status); in q6adm_apr_send_copp_pkt()
271 ret = -EINVAL; in q6adm_apr_send_copp_pkt()
275 mutex_unlock(&adm->lock); in q6adm_apr_send_copp_pkt()
279 static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp, in q6adm_device_close()
289 close.hdr.dest_port = copp->id; in q6adm_device_close()
296 static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm, in q6adm_find_matching_copp()
306 spin_lock_irqsave(&adm->copps_list_lock, flags); in q6adm_find_matching_copp()
308 list_for_each_entry(c, &adm->copps_list, node) { in q6adm_find_matching_copp()
309 if ((port_id == c->afe_port) && (topology == c->topology) && in q6adm_find_matching_copp()
310 (mode == c->mode) && (rate == c->rate) && in q6adm_find_matching_copp()
311 (bit_width == c->bit_width) && (app_type == c->app_type)) { in q6adm_find_matching_copp()
313 kref_get(&c->refcount); in q6adm_find_matching_copp()
316 spin_unlock_irqrestore(&adm->copps_list_lock, flags); in q6adm_find_matching_copp()
321 static int q6adm_device_open(struct q6adm *adm, struct q6copp *copp, in q6adm_device_open()
334 return -ENOMEM; in q6adm_device_open()
338 pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, in q6adm_device_open()
341 pkt->hdr.pkt_size = pkt_size; in q6adm_device_open()
342 pkt->hdr.src_port = afe_port; in q6adm_device_open()
343 pkt->hdr.dest_port = afe_port; in q6adm_device_open()
344 pkt->hdr.token = port_id << 16 | copp->copp_idx; in q6adm_device_open()
345 pkt->hdr.opcode = ADM_CMD_DEVICE_OPEN_V5; in q6adm_device_open()
346 open->flags = ADM_LEGACY_DEVICE_SESSION; in q6adm_device_open()
347 open->mode_of_operation = path; in q6adm_device_open()
348 open->endpoint_id_1 = afe_port; in q6adm_device_open()
349 open->topology_id = topology; in q6adm_device_open()
350 open->dev_num_channel = channel_mode & 0x00FF; in q6adm_device_open()
351 open->bit_width = bit_width; in q6adm_device_open()
352 open->sample_rate = rate; in q6adm_device_open()
354 ret = q6dsp_map_channels(&open->dev_channel_mapping[0], in q6adm_device_open()
368 * q6adm_open() - open adm and grab a free copp
387 struct q6adm *adm = dev_get_drvdata(dev->parent); in q6adm_open()
394 return ERR_PTR(-EINVAL); in q6adm_open()
400 dev_err(dev, "Found Matching Copp 0x%x\n", copp->copp_idx); in q6adm_open()
404 spin_lock_irqsave(&adm->copps_list_lock, flags); in q6adm_open()
407 spin_unlock_irqrestore(&adm->copps_list_lock, flags); in q6adm_open()
411 list_add_tail(&copp->node, &adm->copps_list); in q6adm_open()
412 spin_unlock_irqrestore(&adm->copps_list_lock, flags); in q6adm_open()
414 kref_init(&copp->refcount); in q6adm_open()
415 copp->topology = topology; in q6adm_open()
416 copp->mode = perf_mode; in q6adm_open()
417 copp->rate = rate; in q6adm_open()
418 copp->channels = channel_mode; in q6adm_open()
419 copp->bit_width = bit_width; in q6adm_open()
420 copp->app_type = app_type; in q6adm_open()
425 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_open()
434 * q6adm_get_copp_id() - get copp index
443 return -EINVAL; in q6adm_get_copp_id()
445 return copp->copp_idx; in q6adm_get_copp_id()
450 * q6adm_matrix_map() - Map asm streams and afe ports using payload
462 struct q6adm *adm = dev_get_drvdata(dev->parent); in q6adm_matrix_map()
477 return -ENOMEM; in q6adm_matrix_map()
484 pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, in q6adm_matrix_map()
487 pkt->hdr.pkt_size = pkt_size; in q6adm_matrix_map()
488 pkt->hdr.token = 0; in q6adm_matrix_map()
489 pkt->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; in q6adm_matrix_map()
490 route->num_sessions = 1; in q6adm_matrix_map()
494 route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; in q6adm_matrix_map()
497 route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; in q6adm_matrix_map()
504 node->session_id = payload_map.session_id; in q6adm_matrix_map()
505 node->num_copps = payload_map.num_copps; in q6adm_matrix_map()
514 return -EINVAL; in q6adm_matrix_map()
521 return -EINVAL; in q6adm_matrix_map()
524 copps_list[i] = copp->id; in q6adm_matrix_map()
525 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_matrix_map()
528 mutex_lock(&adm->lock); in q6adm_matrix_map()
529 adm->result.status = 0; in q6adm_matrix_map()
530 adm->result.opcode = 0; in q6adm_matrix_map()
532 ret = apr_send_pkt(adm->apr, pkt); in q6adm_matrix_map()
534 dev_err(dev, "routing for stream %d failed ret %d\n", in q6adm_matrix_map()
538 ret = wait_event_timeout(adm->matrix_map_wait, in q6adm_matrix_map()
539 adm->result.opcode == pkt->hdr.opcode, in q6adm_matrix_map()
542 dev_err(dev, "routing for stream %d failed\n", in q6adm_matrix_map()
544 ret = -ETIMEDOUT; in q6adm_matrix_map()
546 } else if (adm->result.status > 0) { in q6adm_matrix_map()
548 adm->result.status); in q6adm_matrix_map()
549 ret = -EINVAL; in q6adm_matrix_map()
554 mutex_unlock(&adm->lock); in q6adm_matrix_map()
561 * q6adm_close() - Close adm copp
570 struct q6adm *adm = dev_get_drvdata(dev->parent); in q6adm_close()
573 ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx); in q6adm_close()
575 dev_err(adm->dev, "Failed to close copp %d\n", ret); in q6adm_close()
579 kref_put(&copp->refcount, q6adm_free_copp); in q6adm_close()
587 struct device *dev = &adev->dev; in q6adm_probe()
588 struct q6adm *adm; in q6adm_probe()
592 return -ENOMEM; in q6adm_probe()
594 adm->apr = adev; in q6adm_probe()
596 adm->dev = dev; in q6adm_probe()
597 q6core_get_svc_api_info(adev->svc_id, &adm->ainfo); in q6adm_probe()
598 mutex_init(&adm->lock); in q6adm_probe()
599 init_waitqueue_head(&adm->matrix_map_wait); in q6adm_probe()
601 INIT_LIST_HEAD(&adm->copps_list); in q6adm_probe()
602 spin_lock_init(&adm->copps_list_lock); in q6adm_probe()
609 { .compatible = "qcom,q6adm" },
619 .name = "qcom-q6adm",