summaryrefslogtreecommitdiff
path: root/sound/pci/ctxfi/ctdaio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ctxfi/ctdaio.c')
-rw-r--r--sound/pci/ctxfi/ctdaio.c228
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);