162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * @File	ctdaio.c
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * @Brief
862306a36Sopenharmony_ci * This file contains the implementation of Digital Audio Input Output
962306a36Sopenharmony_ci * resource management object.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * @Author	Liu Chun
1262306a36Sopenharmony_ci * @Date 	May 23 2008
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "ctdaio.h"
1662306a36Sopenharmony_ci#include "cthardware.h"
1762306a36Sopenharmony_ci#include "ctimap.h"
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/kernel.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define DAIO_OUT_MAX		SPDIFOO
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct daio_usage {
2462306a36Sopenharmony_ci	unsigned short data;
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistruct daio_rsc_idx {
2862306a36Sopenharmony_ci	unsigned short left;
2962306a36Sopenharmony_ci	unsigned short right;
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
3362306a36Sopenharmony_ci	[LINEO1] = {.left = 0x00, .right = 0x01},
3462306a36Sopenharmony_ci	[LINEO2] = {.left = 0x18, .right = 0x19},
3562306a36Sopenharmony_ci	[LINEO3] = {.left = 0x08, .right = 0x09},
3662306a36Sopenharmony_ci	[LINEO4] = {.left = 0x10, .right = 0x11},
3762306a36Sopenharmony_ci	[LINEIM] = {.left = 0x1b5, .right = 0x1bd},
3862306a36Sopenharmony_ci	[SPDIFOO] = {.left = 0x20, .right = 0x21},
3962306a36Sopenharmony_ci	[SPDIFIO] = {.left = 0x15, .right = 0x1d},
4062306a36Sopenharmony_ci	[SPDIFI1] = {.left = 0x95, .right = 0x9d},
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
4462306a36Sopenharmony_ci	[LINEO1] = {.left = 0x40, .right = 0x41},
4562306a36Sopenharmony_ci	[LINEO2] = {.left = 0x60, .right = 0x61},
4662306a36Sopenharmony_ci	[LINEO3] = {.left = 0x50, .right = 0x51},
4762306a36Sopenharmony_ci	[LINEO4] = {.left = 0x70, .right = 0x71},
4862306a36Sopenharmony_ci	[LINEIM] = {.left = 0x45, .right = 0xc5},
4962306a36Sopenharmony_ci	[MIC]	 = {.left = 0x55, .right = 0xd5},
5062306a36Sopenharmony_ci	[SPDIFOO] = {.left = 0x00, .right = 0x01},
5162306a36Sopenharmony_ci	[SPDIFIO] = {.left = 0x05, .right = 0x85},
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic void daio_master(struct rsc *rsc)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	/* Actually, this is not the resource index of DAIO.
5762306a36Sopenharmony_ci	 * For DAO, it is the input mapper index. And, for DAI,
5862306a36Sopenharmony_ci	 * it is the output time-slot index. */
5962306a36Sopenharmony_ci	rsc->conj = rsc->idx;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic int daio_index(const struct rsc *rsc)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	return rsc->conj;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic void daio_out_next_conj(struct rsc *rsc)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	rsc->conj += 2;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic void daio_in_next_conj_20k1(struct rsc *rsc)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	rsc->conj += 0x200;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic void daio_in_next_conj_20k2(struct rsc *rsc)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	rsc->conj += 0x100;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic const struct rsc_ops daio_out_rsc_ops = {
8362306a36Sopenharmony_ci	.master		= daio_master,
8462306a36Sopenharmony_ci	.next_conj	= daio_out_next_conj,
8562306a36Sopenharmony_ci	.index		= daio_index,
8662306a36Sopenharmony_ci	.output_slot	= NULL,
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic const struct rsc_ops daio_in_rsc_ops_20k1 = {
9062306a36Sopenharmony_ci	.master		= daio_master,
9162306a36Sopenharmony_ci	.next_conj	= daio_in_next_conj_20k1,
9262306a36Sopenharmony_ci	.index		= NULL,
9362306a36Sopenharmony_ci	.output_slot	= daio_index,
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic const struct rsc_ops daio_in_rsc_ops_20k2 = {
9762306a36Sopenharmony_ci	.master		= daio_master,
9862306a36Sopenharmony_ci	.next_conj	= daio_in_next_conj_20k2,
9962306a36Sopenharmony_ci	.index		= NULL,
10062306a36Sopenharmony_ci	.output_slot	= daio_index,
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	switch (hw->chip_type) {
10662306a36Sopenharmony_ci	case ATC20K1:
10762306a36Sopenharmony_ci		switch (type) {
10862306a36Sopenharmony_ci		case SPDIFOO:	return 0;
10962306a36Sopenharmony_ci		case SPDIFIO:	return 0;
11062306a36Sopenharmony_ci		case SPDIFI1:	return 1;
11162306a36Sopenharmony_ci		case LINEO1:	return 4;
11262306a36Sopenharmony_ci		case LINEO2:	return 7;
11362306a36Sopenharmony_ci		case LINEO3:	return 5;
11462306a36Sopenharmony_ci		case LINEO4:	return 6;
11562306a36Sopenharmony_ci		case LINEIM:	return 7;
11662306a36Sopenharmony_ci		default:	return -EINVAL;
11762306a36Sopenharmony_ci		}
11862306a36Sopenharmony_ci	case ATC20K2:
11962306a36Sopenharmony_ci		switch (type) {
12062306a36Sopenharmony_ci		case SPDIFOO:	return 0;
12162306a36Sopenharmony_ci		case SPDIFIO:	return 0;
12262306a36Sopenharmony_ci		case LINEO1:	return 4;
12362306a36Sopenharmony_ci		case LINEO2:	return 7;
12462306a36Sopenharmony_ci		case LINEO3:	return 5;
12562306a36Sopenharmony_ci		case LINEO4:	return 6;
12662306a36Sopenharmony_ci		case LINEIM:	return 4;
12762306a36Sopenharmony_ci		case MIC:	return 5;
12862306a36Sopenharmony_ci		default:	return -EINVAL;
12962306a36Sopenharmony_ci		}
13062306a36Sopenharmony_ci	default:
13162306a36Sopenharmony_ci		return -EINVAL;
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic int dao_spdif_get_spos(struct dao *dao, unsigned int *spos)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	dao->hw->dao_get_spos(dao->ctrl_blk, spos);
14062306a36Sopenharmony_ci	return 0;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic int dao_spdif_set_spos(struct dao *dao, unsigned int spos)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	dao->hw->dao_set_spos(dao->ctrl_blk, spos);
14662306a36Sopenharmony_ci	return 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic int dao_commit_write(struct dao *dao)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	dao->hw->dao_commit_write(dao->hw,
15262306a36Sopenharmony_ci		daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk);
15362306a36Sopenharmony_ci	return 0;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic int dao_set_left_input(struct dao *dao, struct rsc *input)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	struct imapper *entry;
15962306a36Sopenharmony_ci	struct daio *daio = &dao->daio;
16062306a36Sopenharmony_ci	int i;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL);
16362306a36Sopenharmony_ci	if (!entry)
16462306a36Sopenharmony_ci		return -ENOMEM;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	dao->ops->clear_left_input(dao);
16762306a36Sopenharmony_ci	/* Program master and conjugate resources */
16862306a36Sopenharmony_ci	input->ops->master(input);
16962306a36Sopenharmony_ci	daio->rscl.ops->master(&daio->rscl);
17062306a36Sopenharmony_ci	for (i = 0; i < daio->rscl.msr; i++, entry++) {
17162306a36Sopenharmony_ci		entry->slot = input->ops->output_slot(input);
17262306a36Sopenharmony_ci		entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl);
17362306a36Sopenharmony_ci		dao->mgr->imap_add(dao->mgr, entry);
17462306a36Sopenharmony_ci		dao->imappers[i] = entry;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		input->ops->next_conj(input);
17762306a36Sopenharmony_ci		daio->rscl.ops->next_conj(&daio->rscl);
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci	input->ops->master(input);
18062306a36Sopenharmony_ci	daio->rscl.ops->master(&daio->rscl);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return 0;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic int dao_set_right_input(struct dao *dao, struct rsc *input)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct imapper *entry;
18862306a36Sopenharmony_ci	struct daio *daio = &dao->daio;
18962306a36Sopenharmony_ci	int i;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL);
19262306a36Sopenharmony_ci	if (!entry)
19362306a36Sopenharmony_ci		return -ENOMEM;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	dao->ops->clear_right_input(dao);
19662306a36Sopenharmony_ci	/* Program master and conjugate resources */
19762306a36Sopenharmony_ci	input->ops->master(input);
19862306a36Sopenharmony_ci	daio->rscr.ops->master(&daio->rscr);
19962306a36Sopenharmony_ci	for (i = 0; i < daio->rscr.msr; i++, entry++) {
20062306a36Sopenharmony_ci		entry->slot = input->ops->output_slot(input);
20162306a36Sopenharmony_ci		entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr);
20262306a36Sopenharmony_ci		dao->mgr->imap_add(dao->mgr, entry);
20362306a36Sopenharmony_ci		dao->imappers[daio->rscl.msr + i] = entry;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		input->ops->next_conj(input);
20662306a36Sopenharmony_ci		daio->rscr.ops->next_conj(&daio->rscr);
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci	input->ops->master(input);
20962306a36Sopenharmony_ci	daio->rscr.ops->master(&daio->rscr);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	return 0;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic int dao_clear_left_input(struct dao *dao)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	struct imapper *entry;
21762306a36Sopenharmony_ci	struct daio *daio = &dao->daio;
21862306a36Sopenharmony_ci	int i;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (!dao->imappers[0])
22162306a36Sopenharmony_ci		return 0;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	entry = dao->imappers[0];
22462306a36Sopenharmony_ci	dao->mgr->imap_delete(dao->mgr, entry);
22562306a36Sopenharmony_ci	/* Program conjugate resources */
22662306a36Sopenharmony_ci	for (i = 1; i < daio->rscl.msr; i++) {
22762306a36Sopenharmony_ci		entry = dao->imappers[i];
22862306a36Sopenharmony_ci		dao->mgr->imap_delete(dao->mgr, entry);
22962306a36Sopenharmony_ci		dao->imappers[i] = NULL;
23062306a36Sopenharmony_ci	}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	kfree(dao->imappers[0]);
23362306a36Sopenharmony_ci	dao->imappers[0] = NULL;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return 0;
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic int dao_clear_right_input(struct dao *dao)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct imapper *entry;
24162306a36Sopenharmony_ci	struct daio *daio = &dao->daio;
24262306a36Sopenharmony_ci	int i;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (!dao->imappers[daio->rscl.msr])
24562306a36Sopenharmony_ci		return 0;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	entry = dao->imappers[daio->rscl.msr];
24862306a36Sopenharmony_ci	dao->mgr->imap_delete(dao->mgr, entry);
24962306a36Sopenharmony_ci	/* Program conjugate resources */
25062306a36Sopenharmony_ci	for (i = 1; i < daio->rscr.msr; i++) {
25162306a36Sopenharmony_ci		entry = dao->imappers[daio->rscl.msr + i];
25262306a36Sopenharmony_ci		dao->mgr->imap_delete(dao->mgr, entry);
25362306a36Sopenharmony_ci		dao->imappers[daio->rscl.msr + i] = NULL;
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	kfree(dao->imappers[daio->rscl.msr]);
25762306a36Sopenharmony_ci	dao->imappers[daio->rscl.msr] = NULL;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	return 0;
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic const struct dao_rsc_ops dao_ops = {
26362306a36Sopenharmony_ci	.set_spos		= dao_spdif_set_spos,
26462306a36Sopenharmony_ci	.commit_write		= dao_commit_write,
26562306a36Sopenharmony_ci	.get_spos		= dao_spdif_get_spos,
26662306a36Sopenharmony_ci	.reinit			= dao_rsc_reinit,
26762306a36Sopenharmony_ci	.set_left_input		= dao_set_left_input,
26862306a36Sopenharmony_ci	.set_right_input	= dao_set_right_input,
26962306a36Sopenharmony_ci	.clear_left_input	= dao_clear_left_input,
27062306a36Sopenharmony_ci	.clear_right_input	= dao_clear_right_input,
27162306a36Sopenharmony_ci};
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic int dai_set_srt_srcl(struct dai *dai, struct rsc *src)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	src->ops->master(src);
27662306a36Sopenharmony_ci	dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src));
27762306a36Sopenharmony_ci	return 0;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic int dai_set_srt_srcr(struct dai *dai, struct rsc *src)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	src->ops->master(src);
28362306a36Sopenharmony_ci	dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src));
28462306a36Sopenharmony_ci	return 0;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic int dai_set_srt_msr(struct dai *dai, unsigned int msr)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	unsigned int rsr;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	for (rsr = 0; msr > 1; msr >>= 1)
29262306a36Sopenharmony_ci		rsr++;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr);
29562306a36Sopenharmony_ci	return 0;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistatic int dai_set_enb_src(struct dai *dai, unsigned int enb)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb);
30162306a36Sopenharmony_ci	return 0;
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic int dai_set_enb_srt(struct dai *dai, unsigned int enb)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	dai->hw->dai_srt_set_et(dai->ctrl_blk, enb);
30762306a36Sopenharmony_ci	return 0;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic int dai_commit_write(struct dai *dai)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	dai->hw->dai_commit_write(dai->hw,
31362306a36Sopenharmony_ci		daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
31462306a36Sopenharmony_ci	return 0;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic const struct dai_rsc_ops dai_ops = {
31862306a36Sopenharmony_ci	.set_srt_srcl		= dai_set_srt_srcl,
31962306a36Sopenharmony_ci	.set_srt_srcr		= dai_set_srt_srcr,
32062306a36Sopenharmony_ci	.set_srt_msr		= dai_set_srt_msr,
32162306a36Sopenharmony_ci	.set_enb_src		= dai_set_enb_src,
32262306a36Sopenharmony_ci	.set_enb_srt		= dai_set_enb_srt,
32362306a36Sopenharmony_ci	.commit_write		= dai_commit_write,
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic int daio_rsc_init(struct daio *daio,
32762306a36Sopenharmony_ci			 const struct daio_desc *desc,
32862306a36Sopenharmony_ci			 struct hw *hw)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	int err;
33162306a36Sopenharmony_ci	unsigned int idx_l, idx_r;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	switch (hw->chip_type) {
33462306a36Sopenharmony_ci	case ATC20K1:
33562306a36Sopenharmony_ci		idx_l = idx_20k1[desc->type].left;
33662306a36Sopenharmony_ci		idx_r = idx_20k1[desc->type].right;
33762306a36Sopenharmony_ci		break;
33862306a36Sopenharmony_ci	case ATC20K2:
33962306a36Sopenharmony_ci		idx_l = idx_20k2[desc->type].left;
34062306a36Sopenharmony_ci		idx_r = idx_20k2[desc->type].right;
34162306a36Sopenharmony_ci		break;
34262306a36Sopenharmony_ci	default:
34362306a36Sopenharmony_ci		return -EINVAL;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci	err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw);
34662306a36Sopenharmony_ci	if (err)
34762306a36Sopenharmony_ci		return err;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw);
35062306a36Sopenharmony_ci	if (err)
35162306a36Sopenharmony_ci		goto error1;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	/* Set daio->rscl/r->ops to daio specific ones */
35462306a36Sopenharmony_ci	if (desc->type <= DAIO_OUT_MAX) {
35562306a36Sopenharmony_ci		daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops;
35662306a36Sopenharmony_ci	} else {
35762306a36Sopenharmony_ci		switch (hw->chip_type) {
35862306a36Sopenharmony_ci		case ATC20K1:
35962306a36Sopenharmony_ci			daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1;
36062306a36Sopenharmony_ci			break;
36162306a36Sopenharmony_ci		case ATC20K2:
36262306a36Sopenharmony_ci			daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2;
36362306a36Sopenharmony_ci			break;
36462306a36Sopenharmony_ci		default:
36562306a36Sopenharmony_ci			break;
36662306a36Sopenharmony_ci		}
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci	daio->type = desc->type;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return 0;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cierror1:
37362306a36Sopenharmony_ci	rsc_uninit(&daio->rscl);
37462306a36Sopenharmony_ci	return err;
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic int daio_rsc_uninit(struct daio *daio)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	rsc_uninit(&daio->rscl);
38062306a36Sopenharmony_ci	rsc_uninit(&daio->rscr);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	return 0;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic int dao_rsc_init(struct dao *dao,
38662306a36Sopenharmony_ci			const struct daio_desc *desc,
38762306a36Sopenharmony_ci			struct daio_mgr *mgr)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct hw *hw = mgr->mgr.hw;
39062306a36Sopenharmony_ci	unsigned int conf;
39162306a36Sopenharmony_ci	int err;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw);
39462306a36Sopenharmony_ci	if (err)
39562306a36Sopenharmony_ci		return err;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2),
39862306a36Sopenharmony_ci				GFP_KERNEL);
39962306a36Sopenharmony_ci	if (!dao->imappers) {
40062306a36Sopenharmony_ci		err = -ENOMEM;
40162306a36Sopenharmony_ci		goto error1;
40262306a36Sopenharmony_ci	}
40362306a36Sopenharmony_ci	dao->ops = &dao_ops;
40462306a36Sopenharmony_ci	dao->mgr = mgr;
40562306a36Sopenharmony_ci	dao->hw = hw;
40662306a36Sopenharmony_ci	err = hw->dao_get_ctrl_blk(&dao->ctrl_blk);
40762306a36Sopenharmony_ci	if (err)
40862306a36Sopenharmony_ci		goto error2;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
41162306a36Sopenharmony_ci			daio_device_index(dao->daio.type, hw));
41262306a36Sopenharmony_ci	hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	conf = (desc->msr & 0x7) | (desc->passthru << 3);
41562306a36Sopenharmony_ci	hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk,
41662306a36Sopenharmony_ci			daio_device_index(dao->daio.type, hw), conf);
41762306a36Sopenharmony_ci	hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
41862306a36Sopenharmony_ci			daio_device_index(dao->daio.type, hw));
41962306a36Sopenharmony_ci	hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	return 0;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cierror2:
42462306a36Sopenharmony_ci	kfree(dao->imappers);
42562306a36Sopenharmony_ci	dao->imappers = NULL;
42662306a36Sopenharmony_cierror1:
42762306a36Sopenharmony_ci	daio_rsc_uninit(&dao->daio);
42862306a36Sopenharmony_ci	return err;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic int dao_rsc_uninit(struct dao *dao)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	if (dao->imappers) {
43462306a36Sopenharmony_ci		if (dao->imappers[0])
43562306a36Sopenharmony_ci			dao_clear_left_input(dao);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci		if (dao->imappers[dao->daio.rscl.msr])
43862306a36Sopenharmony_ci			dao_clear_right_input(dao);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci		kfree(dao->imappers);
44162306a36Sopenharmony_ci		dao->imappers = NULL;
44262306a36Sopenharmony_ci	}
44362306a36Sopenharmony_ci	dao->hw->dao_put_ctrl_blk(dao->ctrl_blk);
44462306a36Sopenharmony_ci	dao->hw = dao->ctrl_blk = NULL;
44562306a36Sopenharmony_ci	daio_rsc_uninit(&dao->daio);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	return 0;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	struct daio_mgr *mgr = dao->mgr;
45362306a36Sopenharmony_ci	struct daio_desc dsc = {0};
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	dsc.type = dao->daio.type;
45662306a36Sopenharmony_ci	dsc.msr = desc->msr;
45762306a36Sopenharmony_ci	dsc.passthru = desc->passthru;
45862306a36Sopenharmony_ci	dao_rsc_uninit(dao);
45962306a36Sopenharmony_ci	return dao_rsc_init(dao, &dsc, mgr);
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic int dai_rsc_init(struct dai *dai,
46362306a36Sopenharmony_ci			const struct daio_desc *desc,
46462306a36Sopenharmony_ci			struct daio_mgr *mgr)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	int err;
46762306a36Sopenharmony_ci	struct hw *hw = mgr->mgr.hw;
46862306a36Sopenharmony_ci	unsigned int rsr, msr;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw);
47162306a36Sopenharmony_ci	if (err)
47262306a36Sopenharmony_ci		return err;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	dai->ops = &dai_ops;
47562306a36Sopenharmony_ci	dai->hw = mgr->mgr.hw;
47662306a36Sopenharmony_ci	err = hw->dai_get_ctrl_blk(&dai->ctrl_blk);
47762306a36Sopenharmony_ci	if (err)
47862306a36Sopenharmony_ci		goto error1;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1)
48162306a36Sopenharmony_ci		rsr++;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	hw->dai_srt_set_rsr(dai->ctrl_blk, rsr);
48462306a36Sopenharmony_ci	hw->dai_srt_set_drat(dai->ctrl_blk, 0);
48562306a36Sopenharmony_ci	/* default to disabling control of a SRC */
48662306a36Sopenharmony_ci	hw->dai_srt_set_ec(dai->ctrl_blk, 0);
48762306a36Sopenharmony_ci	hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */
48862306a36Sopenharmony_ci	hw->dai_commit_write(hw,
48962306a36Sopenharmony_ci		daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	return 0;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cierror1:
49462306a36Sopenharmony_ci	daio_rsc_uninit(&dai->daio);
49562306a36Sopenharmony_ci	return err;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic int dai_rsc_uninit(struct dai *dai)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	dai->hw->dai_put_ctrl_blk(dai->ctrl_blk);
50162306a36Sopenharmony_ci	dai->hw = dai->ctrl_blk = NULL;
50262306a36Sopenharmony_ci	daio_rsc_uninit(&dai->daio);
50362306a36Sopenharmony_ci	return 0;
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistatic int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type))
50962306a36Sopenharmony_ci		return -ENOENT;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	((struct daio_usage *)mgr->rscs)->data |= (0x1 << type);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	return 0;
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_cistatic int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	return 0;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int get_daio_rsc(struct daio_mgr *mgr,
52462306a36Sopenharmony_ci			const struct daio_desc *desc,
52562306a36Sopenharmony_ci			struct daio **rdaio)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	int err;
52862306a36Sopenharmony_ci	unsigned long flags;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	*rdaio = NULL;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* Check whether there are sufficient daio resources to meet request. */
53362306a36Sopenharmony_ci	spin_lock_irqsave(&mgr->mgr_lock, flags);
53462306a36Sopenharmony_ci	err = daio_mgr_get_rsc(&mgr->mgr, desc->type);
53562306a36Sopenharmony_ci	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
53662306a36Sopenharmony_ci	if (err) {
53762306a36Sopenharmony_ci		dev_err(mgr->card->dev,
53862306a36Sopenharmony_ci			"Can't meet DAIO resource request!\n");
53962306a36Sopenharmony_ci		return err;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	err = -ENOMEM;
54362306a36Sopenharmony_ci	/* Allocate mem for daio resource */
54462306a36Sopenharmony_ci	if (desc->type <= DAIO_OUT_MAX) {
54562306a36Sopenharmony_ci		struct dao *dao = kzalloc(sizeof(*dao), GFP_KERNEL);
54662306a36Sopenharmony_ci		if (!dao)
54762306a36Sopenharmony_ci			goto error;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci		err = dao_rsc_init(dao, desc, mgr);
55062306a36Sopenharmony_ci		if (err) {
55162306a36Sopenharmony_ci			kfree(dao);
55262306a36Sopenharmony_ci			goto error;
55362306a36Sopenharmony_ci		}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci		*rdaio = &dao->daio;
55662306a36Sopenharmony_ci	} else {
55762306a36Sopenharmony_ci		struct dai *dai = kzalloc(sizeof(*dai), GFP_KERNEL);
55862306a36Sopenharmony_ci		if (!dai)
55962306a36Sopenharmony_ci			goto error;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci		err = dai_rsc_init(dai, desc, mgr);
56262306a36Sopenharmony_ci		if (err) {
56362306a36Sopenharmony_ci			kfree(dai);
56462306a36Sopenharmony_ci			goto error;
56562306a36Sopenharmony_ci		}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci		*rdaio = &dai->daio;
56862306a36Sopenharmony_ci	}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	mgr->daio_enable(mgr, *rdaio);
57162306a36Sopenharmony_ci	mgr->commit_write(mgr);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	return 0;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cierror:
57662306a36Sopenharmony_ci	spin_lock_irqsave(&mgr->mgr_lock, flags);
57762306a36Sopenharmony_ci	daio_mgr_put_rsc(&mgr->mgr, desc->type);
57862306a36Sopenharmony_ci	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
57962306a36Sopenharmony_ci	return err;
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	unsigned long flags;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	mgr->daio_disable(mgr, daio);
58762306a36Sopenharmony_ci	mgr->commit_write(mgr);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	spin_lock_irqsave(&mgr->mgr_lock, flags);
59062306a36Sopenharmony_ci	daio_mgr_put_rsc(&mgr->mgr, daio->type);
59162306a36Sopenharmony_ci	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	if (daio->type <= DAIO_OUT_MAX) {
59462306a36Sopenharmony_ci		dao_rsc_uninit(container_of(daio, struct dao, daio));
59562306a36Sopenharmony_ci		kfree(container_of(daio, struct dao, daio));
59662306a36Sopenharmony_ci	} else {
59762306a36Sopenharmony_ci		dai_rsc_uninit(container_of(daio, struct dai, daio));
59862306a36Sopenharmony_ci		kfree(container_of(daio, struct dai, daio));
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	return 0;
60262306a36Sopenharmony_ci}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	struct hw *hw = mgr->mgr.hw;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	if (DAIO_OUT_MAX >= daio->type) {
60962306a36Sopenharmony_ci		hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
61062306a36Sopenharmony_ci				daio_device_index(daio->type, hw));
61162306a36Sopenharmony_ci	} else {
61262306a36Sopenharmony_ci		hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk,
61362306a36Sopenharmony_ci				daio_device_index(daio->type, hw));
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci	return 0;
61662306a36Sopenharmony_ci}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_cistatic int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	struct hw *hw = mgr->mgr.hw;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	if (DAIO_OUT_MAX >= daio->type) {
62362306a36Sopenharmony_ci		hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
62462306a36Sopenharmony_ci				daio_device_index(daio->type, hw));
62562306a36Sopenharmony_ci	} else {
62662306a36Sopenharmony_ci		hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk,
62762306a36Sopenharmony_ci				daio_device_index(daio->type, hw));
62862306a36Sopenharmony_ci	}
62962306a36Sopenharmony_ci	return 0;
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistatic int daio_map_op(void *data, struct imapper *entry)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr;
63562306a36Sopenharmony_ci	struct hw *hw = mgr->hw;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
63862306a36Sopenharmony_ci	hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
63962306a36Sopenharmony_ci	hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
64062306a36Sopenharmony_ci	hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	return 0;
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	unsigned long flags;
64862306a36Sopenharmony_ci	int err;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	spin_lock_irqsave(&mgr->imap_lock, flags);
65162306a36Sopenharmony_ci	if (!entry->addr && mgr->init_imap_added) {
65262306a36Sopenharmony_ci		input_mapper_delete(&mgr->imappers, mgr->init_imap,
65362306a36Sopenharmony_ci							daio_map_op, mgr);
65462306a36Sopenharmony_ci		mgr->init_imap_added = 0;
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci	err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr);
65762306a36Sopenharmony_ci	spin_unlock_irqrestore(&mgr->imap_lock, flags);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	return err;
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_cistatic int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	unsigned long flags;
66562306a36Sopenharmony_ci	int err;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	spin_lock_irqsave(&mgr->imap_lock, flags);
66862306a36Sopenharmony_ci	err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr);
66962306a36Sopenharmony_ci	if (list_empty(&mgr->imappers)) {
67062306a36Sopenharmony_ci		input_mapper_add(&mgr->imappers, mgr->init_imap,
67162306a36Sopenharmony_ci							daio_map_op, mgr);
67262306a36Sopenharmony_ci		mgr->init_imap_added = 1;
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci	spin_unlock_irqrestore(&mgr->imap_lock, flags);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	return err;
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cistatic int daio_mgr_commit_write(struct daio_mgr *mgr)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	struct hw *hw = mgr->mgr.hw;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
68462306a36Sopenharmony_ci	return 0;
68562306a36Sopenharmony_ci}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ciint daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	int err, i;
69062306a36Sopenharmony_ci	struct daio_mgr *daio_mgr;
69162306a36Sopenharmony_ci	struct imapper *entry;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	*rdaio_mgr = NULL;
69462306a36Sopenharmony_ci	daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL);
69562306a36Sopenharmony_ci	if (!daio_mgr)
69662306a36Sopenharmony_ci		return -ENOMEM;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw);
69962306a36Sopenharmony_ci	if (err)
70062306a36Sopenharmony_ci		goto error1;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	spin_lock_init(&daio_mgr->mgr_lock);
70362306a36Sopenharmony_ci	spin_lock_init(&daio_mgr->imap_lock);
70462306a36Sopenharmony_ci	INIT_LIST_HEAD(&daio_mgr->imappers);
70562306a36Sopenharmony_ci	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
70662306a36Sopenharmony_ci	if (!entry) {
70762306a36Sopenharmony_ci		err = -ENOMEM;
70862306a36Sopenharmony_ci		goto error2;
70962306a36Sopenharmony_ci	}
71062306a36Sopenharmony_ci	entry->slot = entry->addr = entry->next = entry->user = 0;
71162306a36Sopenharmony_ci	list_add(&entry->list, &daio_mgr->imappers);
71262306a36Sopenharmony_ci	daio_mgr->init_imap = entry;
71362306a36Sopenharmony_ci	daio_mgr->init_imap_added = 1;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	daio_mgr->get_daio = get_daio_rsc;
71662306a36Sopenharmony_ci	daio_mgr->put_daio = put_daio_rsc;
71762306a36Sopenharmony_ci	daio_mgr->daio_enable = daio_mgr_enb_daio;
71862306a36Sopenharmony_ci	daio_mgr->daio_disable = daio_mgr_dsb_daio;
71962306a36Sopenharmony_ci	daio_mgr->imap_add = daio_imap_add;
72062306a36Sopenharmony_ci	daio_mgr->imap_delete = daio_imap_delete;
72162306a36Sopenharmony_ci	daio_mgr->commit_write = daio_mgr_commit_write;
72262306a36Sopenharmony_ci	daio_mgr->card = hw->card;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
72562306a36Sopenharmony_ci		hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i);
72662306a36Sopenharmony_ci		hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i);
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci	hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk);
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	*rdaio_mgr = daio_mgr;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	return 0;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cierror2:
73562306a36Sopenharmony_ci	rsc_mgr_uninit(&daio_mgr->mgr);
73662306a36Sopenharmony_cierror1:
73762306a36Sopenharmony_ci	kfree(daio_mgr);
73862306a36Sopenharmony_ci	return err;
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ciint daio_mgr_destroy(struct daio_mgr *daio_mgr)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	unsigned long flags;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	/* free daio input mapper list */
74662306a36Sopenharmony_ci	spin_lock_irqsave(&daio_mgr->imap_lock, flags);
74762306a36Sopenharmony_ci	free_input_mapper_list(&daio_mgr->imappers);
74862306a36Sopenharmony_ci	spin_unlock_irqrestore(&daio_mgr->imap_lock, flags);
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	rsc_mgr_uninit(&daio_mgr->mgr);
75162306a36Sopenharmony_ci	kfree(daio_mgr);
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	return 0;
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
756