2009-05-14 08:05:58 +02:00
/**
* 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 )
{
2009-06-08 14:57:57 +02:00
int i , j , k , n ;
2009-05-14 08:05:58 +02:00
/* 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 )
{
2009-06-08 14:57:57 +02:00
unsigned int i , j , k , n ;
2009-05-14 08:05:58 +02:00
/* 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 )
{
2009-06-08 14:57:57 +02:00
int err ;
2009-05-14 08:05:58 +02:00
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 ;
}
2015-11-08 23:40:41 +01:00
static const struct rsc_ops rsc_generic_ops = {
2009-05-14 08:05:58 +02:00
. index = rsc_index ,
. output_slot = audio_ring_slot ,
. master = rsc_master ,
. next_conj = rsc_next_conj ,
} ;
2014-09-29 14:33:21 +05:30
int
rsc_init ( struct rsc * rsc , u32 idx , enum RSCTYP type , u32 msr , struct hw * hw )
2009-05-14 08:05:58 +02:00
{
int err = 0 ;
rsc - > idx = idx ;
rsc - > conj = idx ;
rsc - > type = type ;
rsc - > msr = msr ;
rsc - > hw = hw ;
rsc - > ops = & rsc_generic_ops ;
2009-07-22 17:12:34 +02:00
if ( ! hw ) {
2009-05-14 08:05:58 +02:00
rsc - > ctrl_blk = NULL ;
return 0 ;
}
switch ( type ) {
case SRC :
2014-09-29 14:33:22 +05:30
err = hw - > src_rsc_get_ctrl_blk ( & rsc - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case AMIXER :
2014-09-29 14:33:22 +05:30
err = hw - > amixer_rsc_get_ctrl_blk ( & rsc - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case SRCIMP :
case SUM :
case DAIO :
break ;
default :
2014-09-29 14:33:26 +05:30
dev_err ( ( ( struct hw * ) hw ) - > card - > dev ,
" Invalid resource type value %d! \n " , type ) ;
2009-05-14 08:05:58 +02:00
return - EINVAL ;
}
if ( err ) {
2014-09-29 14:33:26 +05:30
dev_err ( ( ( struct hw * ) hw ) - > card - > dev ,
" Failed to get resource control block! \n " ) ;
2009-05-14 08:05:58 +02:00
return err ;
}
return 0 ;
}
int rsc_uninit ( struct rsc * rsc )
{
if ( ( NULL ! = rsc - > hw ) & & ( NULL ! = rsc - > ctrl_blk ) ) {
switch ( rsc - > type ) {
case SRC :
2014-09-29 14:33:22 +05:30
rsc - > hw - > src_rsc_put_ctrl_blk ( rsc - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case AMIXER :
2014-09-29 14:33:22 +05:30
rsc - > hw - > amixer_rsc_put_ctrl_blk ( rsc - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case SUM :
case DAIO :
break ;
default :
2014-09-29 14:33:26 +05:30
dev_err ( ( ( struct hw * ) rsc - > hw ) - > card - > dev ,
" Invalid resource type value %d! \n " ,
2014-08-26 19:01:43 +05:30
rsc - > type ) ;
2009-05-14 08:05:58 +02:00
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 ,
2014-09-29 14:33:22 +05:30
unsigned int amount , struct hw * hw )
2009-05-14 08:05:58 +02:00
{
int err = 0 ;
mgr - > type = NUM_RSCTYP ;
mgr - > rscs = kzalloc ( ( ( amount + 8 - 1 ) / 8 ) , GFP_KERNEL ) ;
2009-07-22 17:12:34 +02:00
if ( ! mgr - > rscs )
2009-05-14 08:05:58 +02:00
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 :
2014-09-29 14:33:26 +05:30
dev_err ( hw - > card - > dev ,
" Invalid resource type value %d! \n " , type ) ;
2009-05-14 08:05:58 +02:00
err = - EINVAL ;
goto error ;
}
if ( err ) {
2014-09-29 14:33:26 +05:30
dev_err ( hw - > card - > dev ,
" Failed to get manager control block! \n " ) ;
2009-05-14 08:05:58 +02:00
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 )
{
2017-08-31 20:36:42 +05:30
kfree ( mgr - > rscs ) ;
mgr - > rscs = NULL ;
2009-05-14 08:05:58 +02:00
if ( ( NULL ! = mgr - > hw ) & & ( NULL ! = mgr - > ctrl_blk ) ) {
switch ( mgr - > type ) {
case SRC :
2014-09-29 14:33:22 +05:30
mgr - > hw - > src_mgr_put_ctrl_blk ( mgr - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case SRCIMP :
2014-09-29 14:33:22 +05:30
mgr - > hw - > srcimp_mgr_put_ctrl_blk ( mgr - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case AMIXER :
2014-09-29 14:33:22 +05:30
mgr - > hw - > amixer_mgr_put_ctrl_blk ( mgr - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case DAIO :
2014-09-29 14:33:22 +05:30
mgr - > hw - > daio_mgr_put_ctrl_blk ( mgr - > ctrl_blk ) ;
2009-05-14 08:05:58 +02:00
break ;
case SUM :
break ;
default :
2014-09-29 14:33:26 +05:30
dev_err ( ( ( struct hw * ) mgr - > hw ) - > card - > dev ,
" Invalid resource type value %d! \n " ,
2014-08-26 19:01:43 +05:30
mgr - > type ) ;
2009-05-14 08:05:58 +02:00
break ;
}
mgr - > hw = mgr - > ctrl_blk = NULL ;
}
mgr - > type = NUM_RSCTYP ;
mgr - > avail = mgr - > amount = 0 ;
return 0 ;
}