linux/sound/pci/ctxfi/ctresource.c
<<
>>
Prefs
   1/**
   2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   3 *
   4 * This source file is released under GPL v2 license (no other versions).
   5 * See the COPYING file included in the main directory of this source
   6 * distribution for the license terms and conditions.
   7 *
   8 * @File        ctresource.c
   9 *
  10 * @Brief
  11 * This file contains the implementation of some generic helper functions.
  12 *
  13 * @Author      Liu Chun
  14 * @Date        May 15 2008
  15 *
  16 */
  17
  18#include "ctresource.h"
  19#include "cthardware.h"
  20#include <linux/err.h>
  21#include <linux/slab.h>
  22
  23#define AUDIO_SLOT_BLOCK_NUM    256
  24
  25/* Resource allocation based on bit-map management mechanism */
  26static int
  27get_resource(u8 *rscs, unsigned int amount,
  28             unsigned int multi, unsigned int *ridx)
  29{
  30        int i, j, k, n;
  31
  32        /* Check whether there are sufficient resources to meet request. */
  33        for (i = 0, n = multi; i < amount; i++) {
  34                j = i / 8;
  35                k = i % 8;
  36                if (rscs[j] & ((u8)1 << k)) {
  37                        n = multi;
  38                        continue;
  39                }
  40                if (!(--n))
  41                        break; /* found sufficient contiguous resources */
  42        }
  43
  44        if (i >= amount) {
  45                /* Can not find sufficient contiguous resources */
  46                return -ENOENT;
  47        }
  48
  49        /* Mark the contiguous bits in resource bit-map as used */
  50        for (n = multi; n > 0; n--) {
  51                j = i / 8;
  52                k = i % 8;
  53                rscs[j] |= ((u8)1 << k);
  54                i--;
  55        }
  56
  57        *ridx = i + 1;
  58
  59        return 0;
  60}
  61
  62static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
  63{
  64        unsigned int i, j, k, n;
  65
  66        /* Mark the contiguous bits in resource bit-map as used */
  67        for (n = multi, i = idx; n > 0; n--) {
  68                j = i / 8;
  69                k = i % 8;
  70                rscs[j] &= ~((u8)1 << k);
  71                i++;
  72        }
  73
  74        return 0;
  75}
  76
  77int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
  78{
  79        int err;
  80
  81        if (n > mgr->avail)
  82                return -ENOENT;
  83
  84        err = get_resource(mgr->rscs, mgr->amount, n, ridx);
  85        if (!err)
  86                mgr->avail -= n;
  87
  88        return err;
  89}
  90
  91int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
  92{
  93        put_resource(mgr->rscs, n, idx);
  94        mgr->avail += n;
  95
  96        return 0;
  97}
  98
  99static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
 100        /* SRC channel is at Audio Ring slot 1 every 16 slots. */
 101        [SRC]           = 0x1,
 102        [AMIXER]        = 0x4,
 103        [SUM]           = 0xc,
 104};
 105
 106static int rsc_index(const struct rsc *rsc)
 107{
 108    return rsc->conj;
 109}
 110
 111static int audio_ring_slot(const struct rsc *rsc)
 112{
 113    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
 114}
 115
 116static int rsc_next_conj(struct rsc *rsc)
 117{
 118        unsigned int i;
 119        for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
 120                i++;
 121        rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
 122        return rsc->conj;
 123}
 124
 125static int rsc_master(struct rsc *rsc)
 126{
 127        return rsc->conj = rsc->idx;
 128}
 129
 130static struct rsc_ops rsc_generic_ops = {
 131        .index          = rsc_index,
 132        .output_slot    = audio_ring_slot,
 133        .master         = rsc_master,
 134        .next_conj      = rsc_next_conj,
 135};
 136
 137int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
 138{
 139        int err = 0;
 140
 141        rsc->idx = idx;
 142        rsc->conj = idx;
 143        rsc->type = type;
 144        rsc->msr = msr;
 145        rsc->hw = hw;
 146        rsc->ops = &rsc_generic_ops;
 147        if (!hw) {
 148                rsc->ctrl_blk = NULL;
 149                return 0;
 150        }
 151
 152        switch (type) {
 153        case SRC:
 154                err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
 155                break;
 156        case AMIXER:
 157                err = ((struct hw *)hw)->
 158                                amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
 159                break;
 160        case SRCIMP:
 161        case SUM:
 162        case DAIO:
 163                break;
 164        default:
 165                printk(KERN_ERR
 166                       "ctxfi: Invalid resource type value %d!\n", type);
 167                return -EINVAL;
 168        }
 169
 170        if (err) {
 171                printk(KERN_ERR
 172                       "ctxfi: Failed to get resource control block!\n");
 173                return err;
 174        }
 175
 176        return 0;
 177}
 178
 179int rsc_uninit(struct rsc *rsc)
 180{
 181        if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
 182                switch (rsc->type) {
 183                case SRC:
 184                        ((struct hw *)rsc->hw)->
 185                                src_rsc_put_ctrl_blk(rsc->ctrl_blk);
 186                        break;
 187                case AMIXER:
 188                        ((struct hw *)rsc->hw)->
 189                                amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
 190                        break;
 191                case SUM:
 192                case DAIO:
 193                        break;
 194                default:
 195                        printk(KERN_ERR "ctxfi: "
 196                               "Invalid resource type value %d!\n", rsc->type);
 197                        break;
 198                }
 199
 200                rsc->hw = rsc->ctrl_blk = NULL;
 201        }
 202
 203        rsc->idx = rsc->conj = 0;
 204        rsc->type = NUM_RSCTYP;
 205        rsc->msr = 0;
 206
 207        return 0;
 208}
 209
 210int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
 211                 unsigned int amount, void *hw_obj)
 212{
 213        int err = 0;
 214        struct hw *hw = hw_obj;
 215
 216        mgr->type = NUM_RSCTYP;
 217
 218        mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
 219        if (!mgr->rscs)
 220                return -ENOMEM;
 221
 222        switch (type) {
 223        case SRC:
 224                err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
 225                break;
 226        case SRCIMP:
 227                err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
 228                break;
 229        case AMIXER:
 230                err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
 231                break;
 232        case DAIO:
 233                err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
 234                break;
 235        case SUM:
 236                break;
 237        default:
 238                printk(KERN_ERR
 239                       "ctxfi: Invalid resource type value %d!\n", type);
 240                err = -EINVAL;
 241                goto error;
 242        }
 243
 244        if (err) {
 245                printk(KERN_ERR
 246                       "ctxfi: Failed to get manager control block!\n");
 247                goto error;
 248        }
 249
 250        mgr->type = type;
 251        mgr->avail = mgr->amount = amount;
 252        mgr->hw = hw;
 253
 254        return 0;
 255
 256error:
 257        kfree(mgr->rscs);
 258        return err;
 259}
 260
 261int rsc_mgr_uninit(struct rsc_mgr *mgr)
 262{
 263        if (NULL != mgr->rscs) {
 264                kfree(mgr->rscs);
 265                mgr->rscs = NULL;
 266        }
 267
 268        if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
 269                switch (mgr->type) {
 270                case SRC:
 271                        ((struct hw *)mgr->hw)->
 272                                src_mgr_put_ctrl_blk(mgr->ctrl_blk);
 273                        break;
 274                case SRCIMP:
 275                        ((struct hw *)mgr->hw)->
 276                                srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
 277                        break;
 278                case AMIXER:
 279                        ((struct hw *)mgr->hw)->
 280                                amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
 281                        break;
 282                case DAIO:
 283                        ((struct hw *)mgr->hw)->
 284                                daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
 285                        break;
 286                case SUM:
 287                        break;
 288                default:
 289                        printk(KERN_ERR "ctxfi: "
 290                               "Invalid resource type value %d!\n", mgr->type);
 291                        break;
 292                }
 293
 294                mgr->hw = mgr->ctrl_blk = NULL;
 295        }
 296
 297        mgr->type = NUM_RSCTYP;
 298        mgr->avail = mgr->amount = 0;
 299
 300        return 0;
 301}
 302