blob: 5d91a9b4a340e0c3fdb05d7898bb2edb4c430090 [file] [log] [blame]
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +01001/*
2 * Copyright (c) 2016, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the Intel Corporation nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
29 */
30
31#include <stdint.h>
32#include <stddef.h>
33#include <errno.h>
Pierre-Louis Bossart81708a52018-04-04 18:46:50 -050034#include <sof/sof.h>
35#include <sof/lock.h>
36#include <sof/list.h>
37#include <sof/stream.h>
38#include <sof/alloc.h>
39#include <sof/audio/component.h>
40#include <sof/audio/pipeline.h>
Liam Girdwood425aa5e2017-06-06 20:34:10 +010041#include <uapi/ipc.h>
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010042
43struct comp_data {
44 struct list_item list; /* list of components */
45 spinlock_t lock;
46};
47
48static struct comp_data *cd;
49
Liam Girdwood425aa5e2017-06-06 20:34:10 +010050static struct comp_driver *get_drv(uint32_t type)
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010051{
52 struct list_item *clist;
Liam Girdwood425aa5e2017-06-06 20:34:10 +010053 struct comp_driver *drv = NULL;
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010054
55 spin_lock(&cd->lock);
56
Liam Girdwood425aa5e2017-06-06 20:34:10 +010057 /* search driver list for driver type */
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010058 list_for_item(clist, &cd->list) {
59
60 drv = container_of(clist, struct comp_driver, list);
Liam Girdwood425aa5e2017-06-06 20:34:10 +010061 if (drv->type == type)
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010062 goto out;
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010063 }
64
Liam Girdwood425aa5e2017-06-06 20:34:10 +010065 /* not found */
66 drv = NULL;
67
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +010068out:
69 spin_unlock(&cd->lock);
Liam Girdwood425aa5e2017-06-06 20:34:10 +010070 return drv;
71}
72
73struct comp_dev *comp_new(struct sof_ipc_comp *comp)
74{
75 struct comp_dev *cdev;
76 struct comp_driver *drv;
77
78 /* find the driver for our new component */
79 drv = get_drv(comp->type);
80 if (drv == NULL) {
81 trace_comp_error("eCD");
Ranjani Sridharan210989d2018-03-25 17:34:04 -070082 trace_error_value(comp->type);
Liam Girdwood425aa5e2017-06-06 20:34:10 +010083 return NULL;
84 }
85
86 /* create the new component */
87 cdev = drv->ops.new(comp);
88 if (cdev == NULL) {
89 trace_comp_error("eCN");
90 return NULL;
91 }
92
93 /* init component */
94 memcpy(&cdev->comp, comp, sizeof(*comp));
95 cdev->drv = drv;
Liam Girdwood425aa5e2017-06-06 20:34:10 +010096 spinlock_init(&cdev->lock);
97 list_init(&cdev->bsource_list);
98 list_init(&cdev->bsink_list);
99
100 return cdev;
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +0100101}
102
103int comp_register(struct comp_driver *drv)
104{
105 spin_lock(&cd->lock);
106 list_item_prepend(&drv->list, &cd->list);
107 spin_unlock(&cd->lock);
108
109 return 0;
110}
111
112void comp_unregister(struct comp_driver *drv)
113{
114 spin_lock(&cd->lock);
115 list_item_del(&drv->list);
116 spin_unlock(&cd->lock);
117}
118
Ranjani Sridharan62004082017-09-06 22:01:40 +0100119int comp_set_state(struct comp_dev *dev, int cmd)
120{
121 int ret = 0;
122
123 switch (cmd) {
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700124 case COMP_TRIGGER_START:
Wu Zhigang51985172018-07-19 09:22:12 +0800125 if (dev->state == COMP_STATE_PREPARE) {
Liam Girdwoode7b21922017-09-20 23:29:35 +0100126 dev->state = COMP_STATE_ACTIVE;
127 } else {
128 trace_comp_error("CES");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700129 trace_error_value(dev->state);
Liam Girdwoode7b21922017-09-20 23:29:35 +0100130 ret = -EINVAL;
131 }
132 break;
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700133 case COMP_TRIGGER_RELEASE:
Liam Girdwoode7b21922017-09-20 23:29:35 +0100134 if (dev->state == COMP_STATE_PAUSED) {
135 dev->state = COMP_STATE_ACTIVE;
136 } else {
137 trace_comp_error("CEr");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700138 trace_error_value(dev->state);
Liam Girdwoode7b21922017-09-20 23:29:35 +0100139 ret = -EINVAL;
140 }
Ranjani Sridharan62004082017-09-06 22:01:40 +0100141 break;
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700142 case COMP_TRIGGER_STOP:
143 case COMP_TRIGGER_XRUN:
Wu Zhigang51985172018-07-19 09:22:12 +0800144 if (dev->state == COMP_STATE_ACTIVE ||
145 dev->state == COMP_STATE_PAUSED) {
Liam Girdwoodb083e582017-10-12 16:05:44 +0100146 dev->state = COMP_STATE_PREPARE;
Ranjani Sridharan62004082017-09-06 22:01:40 +0100147 } else {
148 trace_comp_error("CEs");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700149 trace_error_value(dev->state);
Ranjani Sridharan62004082017-09-06 22:01:40 +0100150 ret = -EINVAL;
151 }
152 break;
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700153 case COMP_TRIGGER_PAUSE:
Ranjani Sridharan62004082017-09-06 22:01:40 +0100154 /* only support pausing for running */
Liam Girdwood4ad0a662017-09-20 12:21:53 +0100155 if (dev->state == COMP_STATE_ACTIVE)
Ranjani Sridharan62004082017-09-06 22:01:40 +0100156 dev->state = COMP_STATE_PAUSED;
157 else {
158 trace_comp_error("CEp");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700159 trace_error_value(dev->state);
Ranjani Sridharan62004082017-09-06 22:01:40 +0100160 ret = -EINVAL;
161 }
162 break;
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700163 case COMP_TRIGGER_RESET:
Liam Girdwoodb083e582017-10-12 16:05:44 +0100164 /* reset always succeeds */
Liam Girdwoodb083e582017-10-12 16:05:44 +0100165 if (dev->state == COMP_STATE_ACTIVE ||
166 dev->state == COMP_STATE_PAUSED) {
167 trace_comp_error("CER");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700168 trace_error_value(dev->state);
Liam Girdwoodb083e582017-10-12 16:05:44 +0100169 ret = 0;
170 }
Wu Zhigang563ab552018-07-18 16:42:00 +0800171 dev->state = COMP_STATE_READY;
Liam Girdwoodb083e582017-10-12 16:05:44 +0100172 break;
Liam Girdwood7ec3a7c2018-03-28 18:05:37 -0700173 case COMP_TRIGGER_PREPARE:
Liam Girdwoodb083e582017-10-12 16:05:44 +0100174 if (dev->state == COMP_STATE_PREPARE ||
175 dev->state == COMP_STATE_READY) {
176 dev->state = COMP_STATE_PREPARE;
177 } else {
178 trace_comp_error("CEP");
Ranjani Sridharan210989d2018-03-25 17:34:04 -0700179 trace_error_value(dev->state);
Liam Girdwoodb083e582017-10-12 16:05:44 +0100180 ret = -EINVAL;
181 }
182 break;
Ranjani Sridharan62004082017-09-06 22:01:40 +0100183 default:
Ranjani Sridharan62004082017-09-06 22:01:40 +0100184 break;
185 }
186
187 return ret;
188}
189
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +0100190void sys_comp_init(void)
191{
Liam Girdwood1f6aee52018-03-01 16:13:05 +0000192 cd = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*cd));
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +0100193 list_init(&cd->list);
194 spinlock_init(&cd->lock);
195}