brintos

brintos / linux-shallow public Read only

0
0
Text · 5.3 KiB · be1d3e6 Raw
290 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.4 *5 * @File	ctresource.c6 *7 * @Brief8 * This file contains the implementation of some generic helper functions.9 *10 * @Author	Liu Chun11 * @Date 	May 15 200812 */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 	25620 21/* Resource allocation based on bit-map management mechanism */22static int23get_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 void 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}119 120static void rsc_master(struct rsc *rsc)121{122	rsc->conj = rsc->idx;123}124 125static const struct rsc_ops rsc_generic_ops = {126	.index		= rsc_index,127	.output_slot	= audio_ring_slot,128	.master		= rsc_master,129	.next_conj	= rsc_next_conj,130};131 132int133rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)134{135	int err = 0;136 137	rsc->idx = idx;138	rsc->conj = idx;139	rsc->type = type;140	rsc->msr = msr;141	rsc->hw = hw;142	rsc->ops = &rsc_generic_ops;143	if (!hw) {144		rsc->ctrl_blk = NULL;145		return 0;146	}147 148	switch (type) {149	case SRC:150		err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);151		break;152	case AMIXER:153		err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);154		break;155	case SRCIMP:156	case SUM:157	case DAIO:158		break;159	default:160		dev_err(((struct hw *)hw)->card->dev,161			"Invalid resource type value %d!\n", type);162		return -EINVAL;163	}164 165	if (err) {166		dev_err(((struct hw *)hw)->card->dev,167			"Failed to get resource control block!\n");168		return err;169	}170 171	return 0;172}173 174int rsc_uninit(struct rsc *rsc)175{176	if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {177		switch (rsc->type) {178		case SRC:179			rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);180			break;181		case AMIXER:182			rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);183			break;184		case SUM:185		case DAIO:186			break;187		default:188			dev_err(((struct hw *)rsc->hw)->card->dev,189				"Invalid resource type value %d!\n",190				rsc->type);191			break;192		}193 194		rsc->hw = rsc->ctrl_blk = NULL;195	}196 197	rsc->idx = rsc->conj = 0;198	rsc->type = NUM_RSCTYP;199	rsc->msr = 0;200 201	return 0;202}203 204int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,205		 unsigned int amount, struct hw *hw)206{207	int err = 0;208 209	mgr->type = NUM_RSCTYP;210 211	mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);212	if (!mgr->rscs)213		return -ENOMEM;214 215	switch (type) {216	case SRC:217		err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);218		break;219	case SRCIMP:220		err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);221		break;222	case AMIXER:223		err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);224		break;225	case DAIO:226		err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);227		break;228	case SUM:229		break;230	default:231		dev_err(hw->card->dev,232			"Invalid resource type value %d!\n", type);233		err = -EINVAL;234		goto error;235	}236 237	if (err) {238		dev_err(hw->card->dev,239			"Failed to get manager control block!\n");240		goto error;241	}242 243	mgr->type = type;244	mgr->avail = mgr->amount = amount;245	mgr->hw = hw;246 247	return 0;248 249error:250	kfree(mgr->rscs);251	return err;252}253 254int rsc_mgr_uninit(struct rsc_mgr *mgr)255{256	kfree(mgr->rscs);257	mgr->rscs = NULL;258 259	if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {260		switch (mgr->type) {261		case SRC:262			mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);263			break;264		case SRCIMP:265			mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);266			break;267		case AMIXER:268			mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);269			break;270		case DAIO:271			mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);272			break;273		case SUM:274			break;275		default:276			dev_err(((struct hw *)mgr->hw)->card->dev,277				"Invalid resource type value %d!\n",278				mgr->type);279			break;280		}281 282		mgr->hw = mgr->ctrl_blk = NULL;283	}284 285	mgr->type = NUM_RSCTYP;286	mgr->avail = mgr->amount = 0;287 288	return 0;289}290