Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0-only
  2/**
  3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
  4 *
 
 
 
 
  5 * @File	ctresource.c
  6 *
  7 * @Brief
  8 * This file contains the implementation of some generic helper functions.
  9 *
 10 * @Author	Liu Chun
 11 * @Date 	May 15 2008
 
 12 */
 13
 14#include "ctresource.h"
 15#include "cthardware.h"
 16#include <linux/err.h>
 17#include <linux/slab.h>
 18
 19#define AUDIO_SLOT_BLOCK_NUM 	256
 20
 21/* Resource allocation based on bit-map management mechanism */
 22static int
 23get_resource(u8 *rscs, unsigned int amount,
 24	     unsigned int multi, unsigned int *ridx)
 25{
 26	int i, j, k, n;
 27
 28	/* Check whether there are sufficient resources to meet request. */
 29	for (i = 0, n = multi; i < amount; i++) {
 30		j = i / 8;
 31		k = i % 8;
 32		if (rscs[j] & ((u8)1 << k)) {
 33			n = multi;
 34			continue;
 35		}
 36		if (!(--n))
 37			break; /* found sufficient contiguous resources */
 38	}
 39
 40	if (i >= amount) {
 41		/* Can not find sufficient contiguous resources */
 42		return -ENOENT;
 43	}
 44
 45	/* Mark the contiguous bits in resource bit-map as used */
 46	for (n = multi; n > 0; n--) {
 47		j = i / 8;
 48		k = i % 8;
 49		rscs[j] |= ((u8)1 << k);
 50		i--;
 51	}
 52
 53	*ridx = i + 1;
 54
 55	return 0;
 56}
 57
 58static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
 59{
 60	unsigned int i, j, k, n;
 61
 62	/* Mark the contiguous bits in resource bit-map as used */
 63	for (n = multi, i = idx; n > 0; n--) {
 64		j = i / 8;
 65		k = i % 8;
 66		rscs[j] &= ~((u8)1 << k);
 67		i++;
 68	}
 69
 70	return 0;
 71}
 72
 73int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
 74{
 75	int err;
 76
 77	if (n > mgr->avail)
 78		return -ENOENT;
 79
 80	err = get_resource(mgr->rscs, mgr->amount, n, ridx);
 81	if (!err)
 82		mgr->avail -= n;
 83
 84	return err;
 85}
 86
 87int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
 88{
 89	put_resource(mgr->rscs, n, idx);
 90	mgr->avail += n;
 91
 92	return 0;
 93}
 94
 95static const unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
 96	/* SRC channel is at Audio Ring slot 1 every 16 slots. */
 97	[SRC]		= 0x1,
 98	[AMIXER]	= 0x4,
 99	[SUM]		= 0xc,
100};
101
102static int rsc_index(const struct rsc *rsc)
103{
104    return rsc->conj;
105}
106
107static int audio_ring_slot(const struct rsc *rsc)
108{
109    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
110}
111
112static int rsc_next_conj(struct rsc *rsc)
113{
114	unsigned int i;
115	for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
116		i++;
117	rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
118	return rsc->conj;
119}
120
121static int rsc_master(struct rsc *rsc)
122{
123	return rsc->conj = rsc->idx;
124}
125
126static const struct rsc_ops rsc_generic_ops = {
127	.index		= rsc_index,
128	.output_slot	= audio_ring_slot,
129	.master		= rsc_master,
130	.next_conj	= rsc_next_conj,
131};
132
133int
134rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
135{
136	int err = 0;
137
138	rsc->idx = idx;
139	rsc->conj = idx;
140	rsc->type = type;
141	rsc->msr = msr;
142	rsc->hw = hw;
143	rsc->ops = &rsc_generic_ops;
144	if (!hw) {
145		rsc->ctrl_blk = NULL;
146		return 0;
147	}
148
149	switch (type) {
150	case SRC:
151		err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
152		break;
153	case AMIXER:
154		err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
155		break;
156	case SRCIMP:
157	case SUM:
158	case DAIO:
159		break;
160	default:
161		dev_err(((struct hw *)hw)->card->dev,
162			"Invalid resource type value %d!\n", type);
163		return -EINVAL;
164	}
165
166	if (err) {
167		dev_err(((struct hw *)hw)->card->dev,
168			"Failed to get resource control block!\n");
169		return err;
170	}
171
172	return 0;
173}
174
175int rsc_uninit(struct rsc *rsc)
176{
177	if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
178		switch (rsc->type) {
179		case SRC:
180			rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
181			break;
182		case AMIXER:
183			rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
184			break;
185		case SUM:
186		case DAIO:
187			break;
188		default:
189			dev_err(((struct hw *)rsc->hw)->card->dev,
190				"Invalid resource type value %d!\n",
191				rsc->type);
192			break;
193		}
194
195		rsc->hw = rsc->ctrl_blk = NULL;
196	}
197
198	rsc->idx = rsc->conj = 0;
199	rsc->type = NUM_RSCTYP;
200	rsc->msr = 0;
201
202	return 0;
203}
204
205int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
206		 unsigned int amount, struct hw *hw)
207{
208	int err = 0;
209
210	mgr->type = NUM_RSCTYP;
211
212	mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
213	if (!mgr->rscs)
214		return -ENOMEM;
215
216	switch (type) {
217	case SRC:
218		err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
219		break;
220	case SRCIMP:
221		err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
222		break;
223	case AMIXER:
224		err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
225		break;
226	case DAIO:
227		err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
228		break;
229	case SUM:
230		break;
231	default:
232		dev_err(hw->card->dev,
233			"Invalid resource type value %d!\n", type);
234		err = -EINVAL;
235		goto error;
236	}
237
238	if (err) {
239		dev_err(hw->card->dev,
240			"Failed to get manager control block!\n");
241		goto error;
242	}
243
244	mgr->type = type;
245	mgr->avail = mgr->amount = amount;
246	mgr->hw = hw;
247
248	return 0;
249
250error:
251	kfree(mgr->rscs);
252	return err;
253}
254
255int rsc_mgr_uninit(struct rsc_mgr *mgr)
256{
257	kfree(mgr->rscs);
258	mgr->rscs = NULL;
259
260	if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
261		switch (mgr->type) {
262		case SRC:
263			mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
264			break;
265		case SRCIMP:
266			mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
267			break;
268		case AMIXER:
269			mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
270			break;
271		case DAIO:
272			mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
273			break;
274		case SUM:
275			break;
276		default:
277			dev_err(((struct hw *)mgr->hw)->card->dev,
278				"Invalid resource type value %d!\n",
279				mgr->type);
280			break;
281		}
282
283		mgr->hw = mgr->ctrl_blk = NULL;
284	}
285
286	mgr->type = NUM_RSCTYP;
287	mgr->avail = mgr->amount = 0;
288
289	return 0;
290}
v4.17
 
  1/**
  2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
  3 *
  4 * This source file is released under GPL v2 license (no other versions).
  5 * See the COPYING file included in the main directory of this source
  6 * distribution for the license terms and conditions.
  7 *
  8 * @File	ctresource.c
  9 *
 10 * @Brief
 11 * This file contains the implementation of some generic helper functions.
 12 *
 13 * @Author	Liu Chun
 14 * @Date 	May 15 2008
 15 *
 16 */
 17
 18#include "ctresource.h"
 19#include "cthardware.h"
 20#include <linux/err.h>
 21#include <linux/slab.h>
 22
 23#define AUDIO_SLOT_BLOCK_NUM 	256
 24
 25/* Resource allocation based on bit-map management mechanism */
 26static int
 27get_resource(u8 *rscs, unsigned int amount,
 28	     unsigned int multi, unsigned int *ridx)
 29{
 30	int i, j, k, n;
 31
 32	/* Check whether there are sufficient resources to meet request. */
 33	for (i = 0, n = multi; i < amount; i++) {
 34		j = i / 8;
 35		k = i % 8;
 36		if (rscs[j] & ((u8)1 << k)) {
 37			n = multi;
 38			continue;
 39		}
 40		if (!(--n))
 41			break; /* found sufficient contiguous resources */
 42	}
 43
 44	if (i >= amount) {
 45		/* Can not find sufficient contiguous resources */
 46		return -ENOENT;
 47	}
 48
 49	/* Mark the contiguous bits in resource bit-map as used */
 50	for (n = multi; n > 0; n--) {
 51		j = i / 8;
 52		k = i % 8;
 53		rscs[j] |= ((u8)1 << k);
 54		i--;
 55	}
 56
 57	*ridx = i + 1;
 58
 59	return 0;
 60}
 61
 62static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
 63{
 64	unsigned int i, j, k, n;
 65
 66	/* Mark the contiguous bits in resource bit-map as used */
 67	for (n = multi, i = idx; n > 0; n--) {
 68		j = i / 8;
 69		k = i % 8;
 70		rscs[j] &= ~((u8)1 << k);
 71		i++;
 72	}
 73
 74	return 0;
 75}
 76
 77int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
 78{
 79	int err;
 80
 81	if (n > mgr->avail)
 82		return -ENOENT;
 83
 84	err = get_resource(mgr->rscs, mgr->amount, n, ridx);
 85	if (!err)
 86		mgr->avail -= n;
 87
 88	return err;
 89}
 90
 91int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
 92{
 93	put_resource(mgr->rscs, n, idx);
 94	mgr->avail += n;
 95
 96	return 0;
 97}
 98
 99static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
100	/* SRC channel is at Audio Ring slot 1 every 16 slots. */
101	[SRC]		= 0x1,
102	[AMIXER]	= 0x4,
103	[SUM]		= 0xc,
104};
105
106static int rsc_index(const struct rsc *rsc)
107{
108    return rsc->conj;
109}
110
111static int audio_ring_slot(const struct rsc *rsc)
112{
113    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
114}
115
116static int rsc_next_conj(struct rsc *rsc)
117{
118	unsigned int i;
119	for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
120		i++;
121	rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
122	return rsc->conj;
123}
124
125static int rsc_master(struct rsc *rsc)
126{
127	return rsc->conj = rsc->idx;
128}
129
130static const struct rsc_ops rsc_generic_ops = {
131	.index		= rsc_index,
132	.output_slot	= audio_ring_slot,
133	.master		= rsc_master,
134	.next_conj	= rsc_next_conj,
135};
136
137int
138rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
139{
140	int err = 0;
141
142	rsc->idx = idx;
143	rsc->conj = idx;
144	rsc->type = type;
145	rsc->msr = msr;
146	rsc->hw = hw;
147	rsc->ops = &rsc_generic_ops;
148	if (!hw) {
149		rsc->ctrl_blk = NULL;
150		return 0;
151	}
152
153	switch (type) {
154	case SRC:
155		err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
156		break;
157	case AMIXER:
158		err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
159		break;
160	case SRCIMP:
161	case SUM:
162	case DAIO:
163		break;
164	default:
165		dev_err(((struct hw *)hw)->card->dev,
166			"Invalid resource type value %d!\n", type);
167		return -EINVAL;
168	}
169
170	if (err) {
171		dev_err(((struct hw *)hw)->card->dev,
172			"Failed to get resource control block!\n");
173		return err;
174	}
175
176	return 0;
177}
178
179int rsc_uninit(struct rsc *rsc)
180{
181	if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
182		switch (rsc->type) {
183		case SRC:
184			rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
185			break;
186		case AMIXER:
187			rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
188			break;
189		case SUM:
190		case DAIO:
191			break;
192		default:
193			dev_err(((struct hw *)rsc->hw)->card->dev,
194				"Invalid resource type value %d!\n",
195				rsc->type);
196			break;
197		}
198
199		rsc->hw = rsc->ctrl_blk = NULL;
200	}
201
202	rsc->idx = rsc->conj = 0;
203	rsc->type = NUM_RSCTYP;
204	rsc->msr = 0;
205
206	return 0;
207}
208
209int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
210		 unsigned int amount, struct hw *hw)
211{
212	int err = 0;
213
214	mgr->type = NUM_RSCTYP;
215
216	mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
217	if (!mgr->rscs)
218		return -ENOMEM;
219
220	switch (type) {
221	case SRC:
222		err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
223		break;
224	case SRCIMP:
225		err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
226		break;
227	case AMIXER:
228		err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
229		break;
230	case DAIO:
231		err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
232		break;
233	case SUM:
234		break;
235	default:
236		dev_err(hw->card->dev,
237			"Invalid resource type value %d!\n", type);
238		err = -EINVAL;
239		goto error;
240	}
241
242	if (err) {
243		dev_err(hw->card->dev,
244			"Failed to get manager control block!\n");
245		goto error;
246	}
247
248	mgr->type = type;
249	mgr->avail = mgr->amount = amount;
250	mgr->hw = hw;
251
252	return 0;
253
254error:
255	kfree(mgr->rscs);
256	return err;
257}
258
259int rsc_mgr_uninit(struct rsc_mgr *mgr)
260{
261	kfree(mgr->rscs);
262	mgr->rscs = NULL;
263
264	if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
265		switch (mgr->type) {
266		case SRC:
267			mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
268			break;
269		case SRCIMP:
270			mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
271			break;
272		case AMIXER:
273			mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
274			break;
275		case DAIO:
276			mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
277			break;
278		case SUM:
279			break;
280		default:
281			dev_err(((struct hw *)mgr->hw)->card->dev,
282				"Invalid resource type value %d!\n",
283				mgr->type);
284			break;
285		}
286
287		mgr->hw = mgr->ctrl_blk = NULL;
288	}
289
290	mgr->type = NUM_RSCTYP;
291	mgr->avail = mgr->amount = 0;
292
293	return 0;
294}