 35ebf6e721
			
		
	
	
	35ebf6e721
	
	
	
		
			
			- replace NULL == xxx with !xxx - replace NULL != xxx with xxx - similar trivial cleanups Signed-off-by: Takashi Iwai <tiwai@suse.de>
		
			
				
	
	
		
			301 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * 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 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, void *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 = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
 | |
| 		break;
 | |
| 	case AMIXER:
 | |
| 		err = ((struct hw *)hw)->
 | |
| 				amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
 | |
| 		break;
 | |
| 	case SRCIMP:
 | |
| 	case SUM:
 | |
| 	case DAIO:
 | |
| 		break;
 | |
| 	default:
 | |
| 		printk(KERN_ERR
 | |
| 		       "ctxfi: Invalid resource type value %d!\n", type);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	if (err) {
 | |
| 		printk(KERN_ERR
 | |
| 		       "ctxfi: 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:
 | |
| 			((struct hw *)rsc->hw)->
 | |
| 				src_rsc_put_ctrl_blk(rsc->ctrl_blk);
 | |
| 			break;
 | |
| 		case AMIXER:
 | |
| 			((struct hw *)rsc->hw)->
 | |
| 				amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
 | |
| 			break;
 | |
| 		case SUM:
 | |
| 		case DAIO:
 | |
| 			break;
 | |
| 		default:
 | |
| 			printk(KERN_ERR "ctxfi: "
 | |
| 			       "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, void *hw_obj)
 | |
| {
 | |
| 	int err = 0;
 | |
| 	struct hw *hw = hw_obj;
 | |
| 
 | |
| 	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:
 | |
| 		printk(KERN_ERR
 | |
| 		       "ctxfi: Invalid resource type value %d!\n", type);
 | |
| 		err = -EINVAL;
 | |
| 		goto error;
 | |
| 	}
 | |
| 
 | |
| 	if (err) {
 | |
| 		printk(KERN_ERR
 | |
| 		       "ctxfi: 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:
 | |
| 			((struct hw *)mgr->hw)->
 | |
| 				src_mgr_put_ctrl_blk(mgr->ctrl_blk);
 | |
| 			break;
 | |
| 		case SRCIMP:
 | |
| 			((struct hw *)mgr->hw)->
 | |
| 				srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
 | |
| 			break;
 | |
| 		case AMIXER:
 | |
| 			((struct hw *)mgr->hw)->
 | |
| 				amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
 | |
| 			break;
 | |
| 		case DAIO:
 | |
| 			((struct hw *)mgr->hw)->
 | |
| 				daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
 | |
| 			break;
 | |
| 		case SUM:
 | |
| 			break;
 | |
| 		default:
 | |
| 			printk(KERN_ERR "ctxfi: "
 | |
| 			       "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;
 | |
| }
 |