root/sound/pci/ctxfi/ctresource.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_resource
  2. put_resource
  3. mgr_get_resource
  4. mgr_put_resource
  5. rsc_index
  6. audio_ring_slot
  7. rsc_next_conj
  8. rsc_master
  9. rsc_init
  10. rsc_uninit
  11. rsc_mgr_init
  12. rsc_mgr_uninit

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

/* [<][>][^][v][top][bottom][index][help] */