Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
0004  *
0005  * @File    ctresource.c
0006  *
0007  * @Brief
0008  * This file contains the implementation of some generic helper functions.
0009  *
0010  * @Author  Liu Chun
0011  * @Date    May 15 2008
0012  */
0013 
0014 #include "ctresource.h"
0015 #include "cthardware.h"
0016 #include <linux/err.h>
0017 #include <linux/slab.h>
0018 
0019 #define AUDIO_SLOT_BLOCK_NUM    256
0020 
0021 /* Resource allocation based on bit-map management mechanism */
0022 static int
0023 get_resource(u8 *rscs, unsigned int amount,
0024          unsigned int multi, unsigned int *ridx)
0025 {
0026     int i, j, k, n;
0027 
0028     /* Check whether there are sufficient resources to meet request. */
0029     for (i = 0, n = multi; i < amount; i++) {
0030         j = i / 8;
0031         k = i % 8;
0032         if (rscs[j] & ((u8)1 << k)) {
0033             n = multi;
0034             continue;
0035         }
0036         if (!(--n))
0037             break; /* found sufficient contiguous resources */
0038     }
0039 
0040     if (i >= amount) {
0041         /* Can not find sufficient contiguous resources */
0042         return -ENOENT;
0043     }
0044 
0045     /* Mark the contiguous bits in resource bit-map as used */
0046     for (n = multi; n > 0; n--) {
0047         j = i / 8;
0048         k = i % 8;
0049         rscs[j] |= ((u8)1 << k);
0050         i--;
0051     }
0052 
0053     *ridx = i + 1;
0054 
0055     return 0;
0056 }
0057 
0058 static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
0059 {
0060     unsigned int i, j, k, n;
0061 
0062     /* Mark the contiguous bits in resource bit-map as used */
0063     for (n = multi, i = idx; n > 0; n--) {
0064         j = i / 8;
0065         k = i % 8;
0066         rscs[j] &= ~((u8)1 << k);
0067         i++;
0068     }
0069 
0070     return 0;
0071 }
0072 
0073 int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
0074 {
0075     int err;
0076 
0077     if (n > mgr->avail)
0078         return -ENOENT;
0079 
0080     err = get_resource(mgr->rscs, mgr->amount, n, ridx);
0081     if (!err)
0082         mgr->avail -= n;
0083 
0084     return err;
0085 }
0086 
0087 int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
0088 {
0089     put_resource(mgr->rscs, n, idx);
0090     mgr->avail += n;
0091 
0092     return 0;
0093 }
0094 
0095 static const unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
0096     /* SRC channel is at Audio Ring slot 1 every 16 slots. */
0097     [SRC]       = 0x1,
0098     [AMIXER]    = 0x4,
0099     [SUM]       = 0xc,
0100 };
0101 
0102 static int rsc_index(const struct rsc *rsc)
0103 {
0104     return rsc->conj;
0105 }
0106 
0107 static int audio_ring_slot(const struct rsc *rsc)
0108 {
0109     return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
0110 }
0111 
0112 static void rsc_next_conj(struct rsc *rsc)
0113 {
0114     unsigned int i;
0115     for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
0116         i++;
0117     rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
0118 }
0119 
0120 static void rsc_master(struct rsc *rsc)
0121 {
0122     rsc->conj = rsc->idx;
0123 }
0124 
0125 static const struct rsc_ops rsc_generic_ops = {
0126     .index      = rsc_index,
0127     .output_slot    = audio_ring_slot,
0128     .master     = rsc_master,
0129     .next_conj  = rsc_next_conj,
0130 };
0131 
0132 int
0133 rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
0134 {
0135     int err = 0;
0136 
0137     rsc->idx = idx;
0138     rsc->conj = idx;
0139     rsc->type = type;
0140     rsc->msr = msr;
0141     rsc->hw = hw;
0142     rsc->ops = &rsc_generic_ops;
0143     if (!hw) {
0144         rsc->ctrl_blk = NULL;
0145         return 0;
0146     }
0147 
0148     switch (type) {
0149     case SRC:
0150         err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
0151         break;
0152     case AMIXER:
0153         err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
0154         break;
0155     case SRCIMP:
0156     case SUM:
0157     case DAIO:
0158         break;
0159     default:
0160         dev_err(((struct hw *)hw)->card->dev,
0161             "Invalid resource type value %d!\n", type);
0162         return -EINVAL;
0163     }
0164 
0165     if (err) {
0166         dev_err(((struct hw *)hw)->card->dev,
0167             "Failed to get resource control block!\n");
0168         return err;
0169     }
0170 
0171     return 0;
0172 }
0173 
0174 int rsc_uninit(struct rsc *rsc)
0175 {
0176     if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
0177         switch (rsc->type) {
0178         case SRC:
0179             rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
0180             break;
0181         case AMIXER:
0182             rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
0183             break;
0184         case SUM:
0185         case DAIO:
0186             break;
0187         default:
0188             dev_err(((struct hw *)rsc->hw)->card->dev,
0189                 "Invalid resource type value %d!\n",
0190                 rsc->type);
0191             break;
0192         }
0193 
0194         rsc->hw = rsc->ctrl_blk = NULL;
0195     }
0196 
0197     rsc->idx = rsc->conj = 0;
0198     rsc->type = NUM_RSCTYP;
0199     rsc->msr = 0;
0200 
0201     return 0;
0202 }
0203 
0204 int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
0205          unsigned int amount, struct hw *hw)
0206 {
0207     int err = 0;
0208 
0209     mgr->type = NUM_RSCTYP;
0210 
0211     mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);
0212     if (!mgr->rscs)
0213         return -ENOMEM;
0214 
0215     switch (type) {
0216     case SRC:
0217         err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
0218         break;
0219     case SRCIMP:
0220         err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
0221         break;
0222     case AMIXER:
0223         err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
0224         break;
0225     case DAIO:
0226         err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
0227         break;
0228     case SUM:
0229         break;
0230     default:
0231         dev_err(hw->card->dev,
0232             "Invalid resource type value %d!\n", type);
0233         err = -EINVAL;
0234         goto error;
0235     }
0236 
0237     if (err) {
0238         dev_err(hw->card->dev,
0239             "Failed to get manager control block!\n");
0240         goto error;
0241     }
0242 
0243     mgr->type = type;
0244     mgr->avail = mgr->amount = amount;
0245     mgr->hw = hw;
0246 
0247     return 0;
0248 
0249 error:
0250     kfree(mgr->rscs);
0251     return err;
0252 }
0253 
0254 int rsc_mgr_uninit(struct rsc_mgr *mgr)
0255 {
0256     kfree(mgr->rscs);
0257     mgr->rscs = NULL;
0258 
0259     if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
0260         switch (mgr->type) {
0261         case SRC:
0262             mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
0263             break;
0264         case SRCIMP:
0265             mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
0266             break;
0267         case AMIXER:
0268             mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
0269             break;
0270         case DAIO:
0271             mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
0272             break;
0273         case SUM:
0274             break;
0275         default:
0276             dev_err(((struct hw *)mgr->hw)->card->dev,
0277                 "Invalid resource type value %d!\n",
0278                 mgr->type);
0279             break;
0280         }
0281 
0282         mgr->hw = mgr->ctrl_blk = NULL;
0283     }
0284 
0285     mgr->type = NUM_RSCTYP;
0286     mgr->avail = mgr->amount = 0;
0287 
0288     return 0;
0289 }