blob: 5815fad3e54659d8be4af42b0f322b01ffc8d3e1 [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>
34#include <reef/reef.h>
35#include <reef/lock.h>
36#include <reef/list.h>
37#include <reef/stream.h>
38#include <reef/alloc.h>
39#include <reef/audio/component.h>
40#include <reef/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");
82 trace_value(comp->type);
83 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) {
124 case COMP_CMD_START:
Liam Girdwoodfdf1a372017-10-05 22:03:21 +0100125 if (dev->state == COMP_STATE_PREPARE ||
126 dev->state == COMP_STATE_PAUSED) {
Liam Girdwoode7b21922017-09-20 23:29:35 +0100127 dev->state = COMP_STATE_ACTIVE;
128 } else {
129 trace_comp_error("CES");
Liam Girdwoodbe41b682017-09-21 16:48:18 +0100130 trace_value(dev->state);
Liam Girdwoode7b21922017-09-20 23:29:35 +0100131 ret = -EINVAL;
132 }
133 break;
Ranjani Sridharan62004082017-09-06 22:01:40 +0100134 case COMP_CMD_RELEASE:
Liam Girdwoode7b21922017-09-20 23:29:35 +0100135 if (dev->state == COMP_STATE_PAUSED) {
136 dev->state = COMP_STATE_ACTIVE;
137 } else {
138 trace_comp_error("CEr");
Liam Girdwoodbe41b682017-09-21 16:48:18 +0100139 trace_value(dev->state);
Liam Girdwoode7b21922017-09-20 23:29:35 +0100140 ret = -EINVAL;
141 }
Ranjani Sridharan62004082017-09-06 22:01:40 +0100142 break;
143 case COMP_CMD_STOP:
Liam Girdwoode7b21922017-09-20 23:29:35 +0100144 if (dev->state == COMP_STATE_ACTIVE) {
Liam Girdwoodb083e582017-10-12 16:05:44 +0100145 dev->state = COMP_STATE_PREPARE;
Ranjani Sridharan62004082017-09-06 22:01:40 +0100146 } else {
147 trace_comp_error("CEs");
Liam Girdwoodbe41b682017-09-21 16:48:18 +0100148 trace_value(dev->state);
Ranjani Sridharan62004082017-09-06 22:01:40 +0100149 ret = -EINVAL;
150 }
151 break;
152 case COMP_CMD_PAUSE:
153 /* only support pausing for running */
Liam Girdwood4ad0a662017-09-20 12:21:53 +0100154 if (dev->state == COMP_STATE_ACTIVE)
Ranjani Sridharan62004082017-09-06 22:01:40 +0100155 dev->state = COMP_STATE_PAUSED;
156 else {
157 trace_comp_error("CEp");
Liam Girdwoodbe41b682017-09-21 16:48:18 +0100158 trace_value(dev->state);
Ranjani Sridharan62004082017-09-06 22:01:40 +0100159 ret = -EINVAL;
160 }
161 break;
Liam Girdwoodb083e582017-10-12 16:05:44 +0100162 case COMP_CMD_RESET:
163 /* reset always succeeds */
164 dev->state = COMP_STATE_READY;
165 if (dev->state == COMP_STATE_ACTIVE ||
166 dev->state == COMP_STATE_PAUSED) {
167 trace_comp_error("CER");
168 trace_value(dev->state);
169 ret = 0;
170 }
171 break;
172 case COMP_CMD_PREPARE:
173 if (dev->state == COMP_STATE_PREPARE ||
174 dev->state == COMP_STATE_READY) {
175 dev->state = COMP_STATE_PREPARE;
176 } else {
177 trace_comp_error("CEP");
178 trace_value(dev->state);
179 ret = -EINVAL;
180 }
181 break;
Ranjani Sridharan62004082017-09-06 22:01:40 +0100182 default:
Ranjani Sridharan62004082017-09-06 22:01:40 +0100183 break;
184 }
185
186 return ret;
187}
188
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +0100189void sys_comp_init(void)
190{
Liam Girdwood50f7b0e2017-06-06 12:52:15 +0100191 cd = rzalloc(RZONE_SYS, RFLAGS_NONE, sizeof(*cd));
Liam Girdwoodc0dfb4e2016-09-21 15:57:22 +0100192 list_init(&cd->list);
193 spinlock_init(&cd->lock);
194}