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}
v3.15
 
  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 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 rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
 
138{
139	int err = 0;
140
141	rsc->idx = idx;
142	rsc->conj = idx;
143	rsc->type = type;
144	rsc->msr = msr;
145	rsc->hw = hw;
146	rsc->ops = &rsc_generic_ops;
147	if (!hw) {
148		rsc->ctrl_blk = NULL;
149		return 0;
150	}
151
152	switch (type) {
153	case SRC:
154		err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
155		break;
156	case AMIXER:
157		err = ((struct hw *)hw)->
158				amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
159		break;
160	case SRCIMP:
161	case SUM:
162	case DAIO:
163		break;
164	default:
165		printk(KERN_ERR
166		       "ctxfi: Invalid resource type value %d!\n", type);
167		return -EINVAL;
168	}
169
170	if (err) {
171		printk(KERN_ERR
172		       "ctxfi: 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			((struct hw *)rsc->hw)->
185				src_rsc_put_ctrl_blk(rsc->ctrl_blk);
186			break;
187		case AMIXER:
188			((struct hw *)rsc->hw)->
189				amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
190			break;
191		case SUM:
192		case DAIO:
193			break;
194		default:
195			printk(KERN_ERR "ctxfi: "
196			       "Invalid resource type value %d!\n", rsc->type);
 
197			break;
198		}
199
200		rsc->hw = rsc->ctrl_blk = NULL;
201	}
202
203	rsc->idx = rsc->conj = 0;
204	rsc->type = NUM_RSCTYP;
205	rsc->msr = 0;
206
207	return 0;
208}
209
210int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
211		 unsigned int amount, void *hw_obj)
212{
213	int err = 0;
214	struct hw *hw = hw_obj;
215
216	mgr->type = NUM_RSCTYP;
217
218	mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
219	if (!mgr->rscs)
220		return -ENOMEM;
221
222	switch (type) {
223	case SRC:
224		err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
225		break;
226	case SRCIMP:
227		err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
228		break;
229	case AMIXER:
230		err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
231		break;
232	case DAIO:
233		err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
234		break;
235	case SUM:
236		break;
237	default:
238		printk(KERN_ERR
239		       "ctxfi: Invalid resource type value %d!\n", type);
240		err = -EINVAL;
241		goto error;
242	}
243
244	if (err) {
245		printk(KERN_ERR
246		       "ctxfi: Failed to get manager control block!\n");
247		goto error;
248	}
249
250	mgr->type = type;
251	mgr->avail = mgr->amount = amount;
252	mgr->hw = hw;
253
254	return 0;
255
256error:
257	kfree(mgr->rscs);
258	return err;
259}
260
261int rsc_mgr_uninit(struct rsc_mgr *mgr)
262{
263	if (NULL != mgr->rscs) {
264		kfree(mgr->rscs);
265		mgr->rscs = NULL;
266	}
267
268	if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
269		switch (mgr->type) {
270		case SRC:
271			((struct hw *)mgr->hw)->
272				src_mgr_put_ctrl_blk(mgr->ctrl_blk);
273			break;
274		case SRCIMP:
275			((struct hw *)mgr->hw)->
276				srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
277			break;
278		case AMIXER:
279			((struct hw *)mgr->hw)->
280				amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
281			break;
282		case DAIO:
283			((struct hw *)mgr->hw)->
284				daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
285			break;
286		case SUM:
287			break;
288		default:
289			printk(KERN_ERR "ctxfi: "
290			       "Invalid resource type value %d!\n", mgr->type);
 
291			break;
292		}
293
294		mgr->hw = mgr->ctrl_blk = NULL;
295	}
296
297	mgr->type = NUM_RSCTYP;
298	mgr->avail = mgr->amount = 0;
299
300	return 0;
301}