diff options
author | Nicolin Chen <b42378@freescale.com> | 2013-05-13 17:39:28 +0800 |
---|---|---|
committer | Nicolin Chen <b42378@freescale.com> | 2013-07-10 18:16:54 +0800 |
commit | 6ea66e8d56f8b2f741852b4863f308924080df79 (patch) | |
tree | e3f95bef58d1b33819e62cf31617d85390cfa474 /drivers | |
parent | 88bd5dc3b7f51a293417e68d827c0a213ba2a9e0 (diff) |
ENGR00265414-4 mxc: asrc: Reconstruct req_pair()
The old req_pair() constrained that only Pair B could afford 6 channels,
while actually not. So rewrite it to be more flexible.
Acked-by: Wang Shengjiu <b02247@freescale.com>
Signed-off-by: Nicolin Chen <b42378@freescale.com>
(cherry picked from commit adbc9dbba6ee46c05c0878a8e3bab118981d62c7)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mxc/asrc/mxc_asrc.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/drivers/mxc/asrc/mxc_asrc.c b/drivers/mxc/asrc/mxc_asrc.c index dc8d6fd69817..9a4e175e496e 100644 --- a/drivers/mxc/asrc/mxc_asrc.c +++ b/drivers/mxc/asrc/mxc_asrc.c @@ -321,34 +321,42 @@ int asrc_req_pair(int chn_num, enum asrc_pair_index *index) int err = 0; unsigned long lock_flags; struct asrc_pair *pair; + int imax = 0, busy = 0, i; + spin_lock_irqsave(&data_lock, lock_flags); - if (chn_num > 2) { - pair = &g_asrc->asrc_pair[ASRC_PAIR_B]; - if (pair->active || (chn_num > pair->chn_max)) - err = -EBUSY; - else { - *index = ASRC_PAIR_B; - pair->chn_num = chn_num; - pair->active = 1; + for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) { + pair = &g_asrc->asrc_pair[i]; + if (chn_num > pair->chn_max) { + imax++; + continue; + } else if (pair->active) { + busy++; + continue; } + /* Save the current qualified pair */ + *index = i; + + /* Check if this pair is a perfect one */ + if (chn_num == pair->chn_max) + break; + } + + if (imax >= ASRC_PAIR_MAX_NUM) { + pr_err("No pair could afford requested channel number.\n"); + err = -EINVAL; + } else if (busy >= ASRC_PAIR_MAX_NUM) { + pr_err("All pairs are busy now.\n"); + err = -EBUSY; + } else if (busy + imax >= ASRC_PAIR_MAX_NUM) { + pr_err("All affordable pairs are busy now.\n"); + err = -EBUSY; } else { - pair = &g_asrc->asrc_pair[ASRC_PAIR_A]; - if (pair->active || (pair->chn_max == 0)) { - pair = &g_asrc->asrc_pair[ASRC_PAIR_C]; - if (pair->active || (pair->chn_max == 0)) - err = -EBUSY; - else { - *index = ASRC_PAIR_C; - pair->chn_num = 2; - pair->active = 1; - } - } else { - *index = ASRC_PAIR_A; - pair->chn_num = 2; - pair->active = 1; - } + pair = &g_asrc->asrc_pair[*index]; + pair->chn_num = chn_num; + pair->active = 1; } + spin_unlock_irqrestore(&data_lock, lock_flags); if (!err) { @@ -1857,6 +1865,11 @@ static int asrc_write_proc_attr(struct file *file, const char *buffer, reg = na | (nb << g_asrc->mxc_asrc_data->channel_bits) | (nc << (g_asrc->mxc_asrc_data->channel_bits * 2)); + /* Update chn_max */ + g_asrc->asrc_pair[ASRC_PAIR_A].chn_max = na; + g_asrc->asrc_pair[ASRC_PAIR_B].chn_max = nb; + g_asrc->asrc_pair[ASRC_PAIR_C].chn_max = nc; + clk_enable(g_asrc->mxc_asrc_data->asrc_core_clk); __raw_writel(reg, g_asrc->vaddr + ASRC_ASRCNCR_REG); clk_disable(g_asrc->mxc_asrc_data->asrc_core_clk); |