123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /**
- * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
- *
- * This source file is released under GPL v2 license (no other versions).
- * See the COPYING file included in the main directory of this source
- * distribution for the license terms and conditions.
- *
- * @File ctresource.c
- *
- * @Brief
- * This file contains the implementation of some generic helper functions.
- *
- * @Author Liu Chun
- * @Date May 15 2008
- *
- */
- #include "ctresource.h"
- #include "cthardware.h"
- #include <linux/err.h>
- #include <linux/slab.h>
- #define AUDIO_SLOT_BLOCK_NUM 256
- /* Resource allocation based on bit-map management mechanism */
- static int
- get_resource(u8 *rscs, unsigned int amount,
- unsigned int multi, unsigned int *ridx)
- {
- int i, j, k, n;
- /* Check whether there are sufficient resources to meet request. */
- for (i = 0, n = multi; i < amount; i++) {
- j = i / 8;
- k = i % 8;
- if (rscs[j] & ((u8)1 << k)) {
- n = multi;
- continue;
- }
- if (!(--n))
- break; /* found sufficient contiguous resources */
- }
- if (i >= amount) {
- /* Can not find sufficient contiguous resources */
- return -ENOENT;
- }
- /* Mark the contiguous bits in resource bit-map as used */
- for (n = multi; n > 0; n--) {
- j = i / 8;
- k = i % 8;
- rscs[j] |= ((u8)1 << k);
- i--;
- }
- *ridx = i + 1;
- return 0;
- }
- static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
- {
- unsigned int i, j, k, n;
- /* Mark the contiguous bits in resource bit-map as used */
- for (n = multi, i = idx; n > 0; n--) {
- j = i / 8;
- k = i % 8;
- rscs[j] &= ~((u8)1 << k);
- i++;
- }
- return 0;
- }
- int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
- {
- int err;
- if (n > mgr->avail)
- return -ENOENT;
- err = get_resource(mgr->rscs, mgr->amount, n, ridx);
- if (!err)
- mgr->avail -= n;
- return err;
- }
- int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
- {
- put_resource(mgr->rscs, n, idx);
- mgr->avail += n;
- return 0;
- }
- static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
- /* SRC channel is at Audio Ring slot 1 every 16 slots. */
- [SRC] = 0x1,
- [AMIXER] = 0x4,
- [SUM] = 0xc,
- };
- static int rsc_index(const struct rsc *rsc)
- {
- return rsc->conj;
- }
- static int audio_ring_slot(const struct rsc *rsc)
- {
- return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
- }
- static int rsc_next_conj(struct rsc *rsc)
- {
- unsigned int i;
- for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
- i++;
- rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
- return rsc->conj;
- }
- static int rsc_master(struct rsc *rsc)
- {
- return rsc->conj = rsc->idx;
- }
- static const struct rsc_ops rsc_generic_ops = {
- .index = rsc_index,
- .output_slot = audio_ring_slot,
- .master = rsc_master,
- .next_conj = rsc_next_conj,
- };
- int
- rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
- {
- int err = 0;
- rsc->idx = idx;
- rsc->conj = idx;
- rsc->type = type;
- rsc->msr = msr;
- rsc->hw = hw;
- rsc->ops = &rsc_generic_ops;
- if (!hw) {
- rsc->ctrl_blk = NULL;
- return 0;
- }
- switch (type) {
- case SRC:
- err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
- break;
- case AMIXER:
- err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
- break;
- case SRCIMP:
- case SUM:
- case DAIO:
- break;
- default:
- dev_err(((struct hw *)hw)->card->dev,
- "Invalid resource type value %d!\n", type);
- return -EINVAL;
- }
- if (err) {
- dev_err(((struct hw *)hw)->card->dev,
- "Failed to get resource control block!\n");
- return err;
- }
- return 0;
- }
- int rsc_uninit(struct rsc *rsc)
- {
- if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
- switch (rsc->type) {
- case SRC:
- rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
- break;
- case AMIXER:
- rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
- break;
- case SUM:
- case DAIO:
- break;
- default:
- dev_err(((struct hw *)rsc->hw)->card->dev,
- "Invalid resource type value %d!\n",
- rsc->type);
- break;
- }
- rsc->hw = rsc->ctrl_blk = NULL;
- }
- rsc->idx = rsc->conj = 0;
- rsc->type = NUM_RSCTYP;
- rsc->msr = 0;
- return 0;
- }
- int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
- unsigned int amount, struct hw *hw)
- {
- int err = 0;
- mgr->type = NUM_RSCTYP;
- mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
- if (!mgr->rscs)
- return -ENOMEM;
- switch (type) {
- case SRC:
- err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
- break;
- case SRCIMP:
- err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
- break;
- case AMIXER:
- err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
- break;
- case DAIO:
- err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
- break;
- case SUM:
- break;
- default:
- dev_err(hw->card->dev,
- "Invalid resource type value %d!\n", type);
- err = -EINVAL;
- goto error;
- }
- if (err) {
- dev_err(hw->card->dev,
- "Failed to get manager control block!\n");
- goto error;
- }
- mgr->type = type;
- mgr->avail = mgr->amount = amount;
- mgr->hw = hw;
- return 0;
- error:
- kfree(mgr->rscs);
- return err;
- }
- int rsc_mgr_uninit(struct rsc_mgr *mgr)
- {
- if (NULL != mgr->rscs) {
- kfree(mgr->rscs);
- mgr->rscs = NULL;
- }
- if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
- switch (mgr->type) {
- case SRC:
- mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
- break;
- case SRCIMP:
- mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
- break;
- case AMIXER:
- mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
- break;
- case DAIO:
- mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
- break;
- case SUM:
- break;
- default:
- dev_err(((struct hw *)mgr->hw)->card->dev,
- "Invalid resource type value %d!\n",
- mgr->type);
- break;
- }
- mgr->hw = mgr->ctrl_blk = NULL;
- }
- mgr->type = NUM_RSCTYP;
- mgr->avail = mgr->amount = 0;
- return 0;
- }
|