0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
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
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;
0038 }
0039
0040 if (i >= amount) {
0041
0042 return -ENOENT;
0043 }
0044
0045
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
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
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 }