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}
v5.14.15
  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(DIV_ROUND_UP(amount, 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}