diff options
Diffstat (limited to 'sound/pci/ctxfi/ctdaio.c')
| -rw-r--r-- | sound/pci/ctxfi/ctdaio.c | 228 |
1 files changed, 95 insertions, 133 deletions
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 0c00eb4088ef..1c8f8efd836c 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -1,10 +1,7 @@ -/** +// SPDX-License-Identifier: GPL-2.0-only +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * * @File ctdaio.c * * @Brief @@ -13,7 +10,6 @@ * * @Author Liu Chun * @Date May 23 2008 - * */ #include "ctdaio.h" @@ -22,8 +18,6 @@ #include <linux/slab.h> #include <linux/kernel.h> -#define DAIO_OUT_MAX SPDIFOO - struct daio_usage { unsigned short data; }; @@ -33,7 +27,7 @@ struct daio_rsc_idx { unsigned short right; }; -struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { +static const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { [LINEO1] = {.left = 0x00, .right = 0x01}, [LINEO2] = {.left = 0x18, .right = 0x19}, [LINEO3] = {.left = 0x08, .right = 0x09}, @@ -44,23 +38,24 @@ struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { [SPDIFI1] = {.left = 0x95, .right = 0x9d}, }; -struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { +static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { [LINEO1] = {.left = 0x40, .right = 0x41}, [LINEO2] = {.left = 0x60, .right = 0x61}, [LINEO3] = {.left = 0x50, .right = 0x51}, [LINEO4] = {.left = 0x70, .right = 0x71}, [LINEIM] = {.left = 0x45, .right = 0xc5}, [MIC] = {.left = 0x55, .right = 0xd5}, + [RCA] = {.left = 0x30, .right = 0x31}, [SPDIFOO] = {.left = 0x00, .right = 0x01}, [SPDIFIO] = {.left = 0x05, .right = 0x85}, }; -static int daio_master(struct rsc *rsc) +static void daio_master(struct rsc *rsc) { /* Actually, this is not the resource index of DAIO. * For DAO, it is the input mapper index. And, for DAI, * it is the output time-slot index. */ - return rsc->conj = rsc->idx; + rsc->conj = rsc->idx; } static int daio_index(const struct rsc *rsc) @@ -68,36 +63,36 @@ static int daio_index(const struct rsc *rsc) return rsc->conj; } -static int daio_out_next_conj(struct rsc *rsc) +static void daio_out_next_conj(struct rsc *rsc) { - return rsc->conj += 2; + rsc->conj += 2; } -static int daio_in_next_conj_20k1(struct rsc *rsc) +static void daio_in_next_conj_20k1(struct rsc *rsc) { - return rsc->conj += 0x200; + rsc->conj += 0x200; } -static int daio_in_next_conj_20k2(struct rsc *rsc) +static void daio_in_next_conj_20k2(struct rsc *rsc) { - return rsc->conj += 0x100; + rsc->conj += 0x100; } -static struct rsc_ops daio_out_rsc_ops = { +static const struct rsc_ops daio_out_rsc_ops = { .master = daio_master, .next_conj = daio_out_next_conj, .index = daio_index, .output_slot = NULL, }; -static struct rsc_ops daio_in_rsc_ops_20k1 = { +static const struct rsc_ops daio_in_rsc_ops_20k1 = { .master = daio_master, .next_conj = daio_in_next_conj_20k1, .index = NULL, .output_slot = daio_index, }; -static struct rsc_ops daio_in_rsc_ops_20k2 = { +static const struct rsc_ops daio_in_rsc_ops_20k2 = { .master = daio_master, .next_conj = daio_in_next_conj_20k2, .index = NULL, @@ -129,6 +124,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) case LINEO4: return 6; case LINEIM: return 4; case MIC: return 5; + case RCA: return 3; default: return -EINVAL; } default: @@ -140,19 +136,19 @@ static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) { - ((struct hw *)dao->hw)->dao_get_spos(dao->ctrl_blk, spos); + dao->hw->dao_get_spos(dao->ctrl_blk, spos); return 0; } static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) { - ((struct hw *)dao->hw)->dao_set_spos(dao->ctrl_blk, spos); + dao->hw->dao_set_spos(dao->ctrl_blk, spos); return 0; } static int dao_commit_write(struct dao *dao) { - ((struct hw *)dao->hw)->dao_commit_write(dao->hw, + dao->hw->dao_commit_write(dao->hw, daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); return 0; } @@ -163,7 +159,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input) struct daio *daio = &dao->daio; int i; - entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL); + entry = kcalloc(daio->rscl.msr, sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; @@ -192,7 +188,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input) struct daio *daio = &dao->daio; int i; - entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL); + entry = kcalloc(daio->rscr.msr, sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; @@ -215,55 +211,33 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input) return 0; } -static int dao_clear_left_input(struct dao *dao) +static int dao_clear_input(struct dao *dao, unsigned int start, unsigned int end) { - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; + unsigned int i; - if (!dao->imappers[0]) + if (!dao->imappers[start]) return 0; - - entry = dao->imappers[0]; - dao->mgr->imap_delete(dao->mgr, entry); - /* Program conjugate resources */ - for (i = 1; i < daio->rscl.msr; i++) { - entry = dao->imappers[i]; - dao->mgr->imap_delete(dao->mgr, entry); + for (i = start; i < end; i++) { + dao->mgr->imap_delete(dao->mgr, dao->imappers[i]); dao->imappers[i] = NULL; } - kfree(dao->imappers[0]); - dao->imappers[0] = NULL; - return 0; } -static int dao_clear_right_input(struct dao *dao) -{ - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; - - if (!dao->imappers[daio->rscl.msr]) - return 0; - - entry = dao->imappers[daio->rscl.msr]; - dao->mgr->imap_delete(dao->mgr, entry); - /* Program conjugate resources */ - for (i = 1; i < daio->rscr.msr; i++) { - entry = dao->imappers[daio->rscl.msr + i]; - dao->mgr->imap_delete(dao->mgr, entry); - dao->imappers[daio->rscl.msr + i] = NULL; - } - kfree(dao->imappers[daio->rscl.msr]); - dao->imappers[daio->rscl.msr] = NULL; +static int dao_clear_left_input(struct dao *dao) +{ + return dao_clear_input(dao, 0, dao->daio.rscl.msr); +} - return 0; +static int dao_clear_right_input(struct dao *dao) +{ + return dao_clear_input(dao, dao->daio.rscl.msr, + dao->daio.rscl.msr + dao->daio.rscr.msr); } -static struct dao_rsc_ops dao_ops = { +static const struct dao_rsc_ops dao_ops = { .set_spos = dao_spdif_set_spos, .commit_write = dao_commit_write, .get_spos = dao_spdif_get_spos, @@ -277,16 +251,14 @@ static struct dao_rsc_ops dao_ops = { static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) { src->ops->master(src); - ((struct hw *)dai->hw)->dai_srt_set_srcm(dai->ctrl_blk, - src->ops->index(src)); + dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src)); return 0; } static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) { src->ops->master(src); - ((struct hw *)dai->hw)->dai_srt_set_srco(dai->ctrl_blk, - src->ops->index(src)); + dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src)); return 0; } @@ -297,30 +269,30 @@ static int dai_set_srt_msr(struct dai *dai, unsigned int msr) for (rsr = 0; msr > 1; msr >>= 1) rsr++; - ((struct hw *)dai->hw)->dai_srt_set_rsr(dai->ctrl_blk, rsr); + dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); return 0; } static int dai_set_enb_src(struct dai *dai, unsigned int enb) { - ((struct hw *)dai->hw)->dai_srt_set_ec(dai->ctrl_blk, enb); + dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb); return 0; } static int dai_set_enb_srt(struct dai *dai, unsigned int enb) { - ((struct hw *)dai->hw)->dai_srt_set_et(dai->ctrl_blk, enb); + dai->hw->dai_srt_set_et(dai->ctrl_blk, enb); return 0; } static int dai_commit_write(struct dai *dai) { - ((struct hw *)dai->hw)->dai_commit_write(dai->hw, + dai->hw->dai_commit_write(dai->hw, daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); return 0; } -static struct dai_rsc_ops dai_ops = { +static const struct dai_rsc_ops dai_ops = { .set_srt_srcl = dai_set_srt_srcl, .set_srt_srcr = dai_set_srt_srcr, .set_srt_msr = dai_set_srt_msr, @@ -331,12 +303,12 @@ static struct dai_rsc_ops dai_ops = { static int daio_rsc_init(struct daio *daio, const struct daio_desc *desc, - void *hw) + struct hw *hw) { int err; unsigned int idx_l, idx_r; - switch (((struct hw *)hw)->chip_type) { + switch (hw->chip_type) { case ATC20K1: idx_l = idx_20k1[desc->type].left; idx_r = idx_20k1[desc->type].right; @@ -357,10 +329,10 @@ static int daio_rsc_init(struct daio *daio, goto error1; /* Set daio->rscl/r->ops to daio specific ones */ - if (desc->type <= DAIO_OUT_MAX) { + if (desc->output) { daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; } else { - switch (((struct hw *)hw)->chip_type) { + switch (hw->chip_type) { case ATC20K1: daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; break; @@ -372,6 +344,7 @@ static int daio_rsc_init(struct daio *daio, } } daio->type = desc->type; + daio->output = desc->output; return 0; @@ -400,7 +373,8 @@ static int dao_rsc_init(struct dao *dao, if (err) return err; - dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL); + dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2), + GFP_KERNEL); if (!dao->imappers) { err = -ENOMEM; goto error1; @@ -417,7 +391,7 @@ static int dao_rsc_init(struct dao *dao, hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); conf = (desc->msr & 0x7) | (desc->passthru << 3); - hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk, + hw->daio_mgr_dao_init(hw, mgr->mgr.ctrl_blk, daio_device_index(dao->daio.type, hw), conf); hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, daio_device_index(dao->daio.type, hw)); @@ -445,7 +419,7 @@ static int dao_rsc_uninit(struct dao *dao) kfree(dao->imappers); dao->imappers = NULL; } - ((struct hw *)dao->hw)->dao_put_ctrl_blk(dao->ctrl_blk); + dao->hw->dao_put_ctrl_blk(dao->ctrl_blk); dao->hw = dao->ctrl_blk = NULL; daio_rsc_uninit(&dao->daio); @@ -460,6 +434,7 @@ static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc) dsc.type = dao->daio.type; dsc.msr = desc->msr; dsc.passthru = desc->passthru; + dsc.output = dao->daio.output; dao_rsc_uninit(dao); return dao_rsc_init(dao, &dsc, mgr); } @@ -502,7 +477,7 @@ error1: static int dai_rsc_uninit(struct dai *dai) { - ((struct hw *)dai->hw)->dai_put_ctrl_blk(dai->ctrl_blk); + dai->hw->dai_put_ctrl_blk(dai->ctrl_blk); dai->hw = dai->ctrl_blk = NULL; daio_rsc_uninit(&dai->daio); return 0; @@ -530,42 +505,43 @@ static int get_daio_rsc(struct daio_mgr *mgr, struct daio **rdaio) { int err; - struct dai *dai = NULL; - struct dao *dao = NULL; - unsigned long flags; *rdaio = NULL; /* Check whether there are sufficient daio resources to meet request. */ - spin_lock_irqsave(&mgr->mgr_lock, flags); - err = daio_mgr_get_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + err = daio_mgr_get_rsc(&mgr->mgr, desc->type); + } if (err) { - printk(KERN_ERR "Can't meet DAIO resource request!\n"); + dev_err(mgr->card->dev, + "Can't meet DAIO resource request!\n"); return err; } + err = -ENOMEM; /* Allocate mem for daio resource */ - if (desc->type <= DAIO_OUT_MAX) { - dao = kzalloc(sizeof(*dao), GFP_KERNEL); - if (!dao) { - err = -ENOMEM; + if (desc->output) { + struct dao *dao = kzalloc(sizeof(*dao), GFP_KERNEL); + if (!dao) goto error; - } + err = dao_rsc_init(dao, desc, mgr); - if (err) + if (err) { + kfree(dao); goto error; + } *rdaio = &dao->daio; } else { - dai = kzalloc(sizeof(*dai), GFP_KERNEL); - if (!dai) { - err = -ENOMEM; + struct dai *dai = kzalloc(sizeof(*dai), GFP_KERNEL); + if (!dai) goto error; - } + err = dai_rsc_init(dai, desc, mgr); - if (err) + if (err) { + kfree(dai); goto error; + } *rdaio = &dai->daio; } @@ -576,29 +552,22 @@ static int get_daio_rsc(struct daio_mgr *mgr, return 0; error: - if (dao) - kfree(dao); - else if (dai) - kfree(dai); - - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + daio_mgr_put_rsc(&mgr->mgr, desc->type); + } return err; } static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) { - unsigned long flags; - mgr->daio_disable(mgr, daio); mgr->commit_write(mgr); - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, daio->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); + scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { + daio_mgr_put_rsc(&mgr->mgr, daio->type); + } - if (daio->type <= DAIO_OUT_MAX) { + if (daio->output) { dao_rsc_uninit(container_of(daio, struct dao, daio)); kfree(container_of(daio, struct dao, daio)); } else { @@ -613,7 +582,7 @@ static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio) { struct hw *hw = mgr->mgr.hw; - if (DAIO_OUT_MAX >= daio->type) { + if (daio->output) { hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, daio_device_index(daio->type, hw)); } else { @@ -627,7 +596,7 @@ static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio) { struct hw *hw = mgr->mgr.hw; - if (DAIO_OUT_MAX >= daio->type) { + if (daio->output) { hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, daio_device_index(daio->type, hw)); } else { @@ -652,34 +621,26 @@ static int daio_map_op(void *data, struct imapper *entry) static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) { - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); if (!entry->addr && mgr->init_imap_added) { input_mapper_delete(&mgr->imappers, mgr->init_imap, daio_map_op, mgr); mgr->init_imap_added = 0; } - err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; + return input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); } static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) { - unsigned long flags; int err; - spin_lock_irqsave(&mgr->imap_lock, flags); + guard(spinlock_irqsave)(&mgr->imap_lock); err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); if (list_empty(&mgr->imappers)) { input_mapper_add(&mgr->imappers, mgr->init_imap, daio_map_op, mgr); mgr->init_imap_added = 1; } - spin_unlock_irqrestore(&mgr->imap_lock, flags); return err; } @@ -692,7 +653,7 @@ static int daio_mgr_commit_write(struct daio_mgr *mgr) return 0; } -int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) +int daio_mgr_create(struct hw *hw, void **rdaio_mgr) { int err, i; struct daio_mgr *daio_mgr; @@ -727,12 +688,13 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) daio_mgr->imap_add = daio_imap_add; daio_mgr->imap_delete = daio_imap_delete; daio_mgr->commit_write = daio_mgr_commit_write; + daio_mgr->card = hw->card; for (i = 0; i < 8; i++) { - ((struct hw *)hw)->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); - ((struct hw *)hw)->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); + hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); + hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); } - ((struct hw *)hw)->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); + hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); *rdaio_mgr = daio_mgr; @@ -745,14 +707,14 @@ error1: return err; } -int daio_mgr_destroy(struct daio_mgr *daio_mgr) +int daio_mgr_destroy(void *ptr) { - unsigned long flags; + struct daio_mgr *daio_mgr = ptr; /* free daio input mapper list */ - spin_lock_irqsave(&daio_mgr->imap_lock, flags); - free_input_mapper_list(&daio_mgr->imappers); - spin_unlock_irqrestore(&daio_mgr->imap_lock, flags); + scoped_guard(spinlock_irqsave, &daio_mgr->imap_lock) { + free_input_mapper_list(&daio_mgr->imappers); + } rsc_mgr_uninit(&daio_mgr->mgr); kfree(daio_mgr); |
