18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/** 38c2ecf20Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * @File ctdaio.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * @Brief 88c2ecf20Sopenharmony_ci * This file contains the implementation of Digital Audio Input Output 98c2ecf20Sopenharmony_ci * resource management object. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * @Author Liu Chun 128c2ecf20Sopenharmony_ci * @Date May 23 2008 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "ctdaio.h" 168c2ecf20Sopenharmony_ci#include "cthardware.h" 178c2ecf20Sopenharmony_ci#include "ctimap.h" 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci#include <linux/kernel.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define DAIO_OUT_MAX SPDIFOO 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct daio_usage { 248c2ecf20Sopenharmony_ci unsigned short data; 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct daio_rsc_idx { 288c2ecf20Sopenharmony_ci unsigned short left; 298c2ecf20Sopenharmony_ci unsigned short right; 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { 338c2ecf20Sopenharmony_ci [LINEO1] = {.left = 0x00, .right = 0x01}, 348c2ecf20Sopenharmony_ci [LINEO2] = {.left = 0x18, .right = 0x19}, 358c2ecf20Sopenharmony_ci [LINEO3] = {.left = 0x08, .right = 0x09}, 368c2ecf20Sopenharmony_ci [LINEO4] = {.left = 0x10, .right = 0x11}, 378c2ecf20Sopenharmony_ci [LINEIM] = {.left = 0x1b5, .right = 0x1bd}, 388c2ecf20Sopenharmony_ci [SPDIFOO] = {.left = 0x20, .right = 0x21}, 398c2ecf20Sopenharmony_ci [SPDIFIO] = {.left = 0x15, .right = 0x1d}, 408c2ecf20Sopenharmony_ci [SPDIFI1] = {.left = 0x95, .right = 0x9d}, 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { 448c2ecf20Sopenharmony_ci [LINEO1] = {.left = 0x40, .right = 0x41}, 458c2ecf20Sopenharmony_ci [LINEO2] = {.left = 0x60, .right = 0x61}, 468c2ecf20Sopenharmony_ci [LINEO3] = {.left = 0x50, .right = 0x51}, 478c2ecf20Sopenharmony_ci [LINEO4] = {.left = 0x70, .right = 0x71}, 488c2ecf20Sopenharmony_ci [LINEIM] = {.left = 0x45, .right = 0xc5}, 498c2ecf20Sopenharmony_ci [MIC] = {.left = 0x55, .right = 0xd5}, 508c2ecf20Sopenharmony_ci [SPDIFOO] = {.left = 0x00, .right = 0x01}, 518c2ecf20Sopenharmony_ci [SPDIFIO] = {.left = 0x05, .right = 0x85}, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void daio_master(struct rsc *rsc) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci /* Actually, this is not the resource index of DAIO. 578c2ecf20Sopenharmony_ci * For DAO, it is the input mapper index. And, for DAI, 588c2ecf20Sopenharmony_ci * it is the output time-slot index. */ 598c2ecf20Sopenharmony_ci rsc->conj = rsc->idx; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic int daio_index(const struct rsc *rsc) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return rsc->conj; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void daio_out_next_conj(struct rsc *rsc) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci rsc->conj += 2; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void daio_in_next_conj_20k1(struct rsc *rsc) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci rsc->conj += 0x200; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic void daio_in_next_conj_20k2(struct rsc *rsc) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci rsc->conj += 0x100; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic const struct rsc_ops daio_out_rsc_ops = { 838c2ecf20Sopenharmony_ci .master = daio_master, 848c2ecf20Sopenharmony_ci .next_conj = daio_out_next_conj, 858c2ecf20Sopenharmony_ci .index = daio_index, 868c2ecf20Sopenharmony_ci .output_slot = NULL, 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic const struct rsc_ops daio_in_rsc_ops_20k1 = { 908c2ecf20Sopenharmony_ci .master = daio_master, 918c2ecf20Sopenharmony_ci .next_conj = daio_in_next_conj_20k1, 928c2ecf20Sopenharmony_ci .index = NULL, 938c2ecf20Sopenharmony_ci .output_slot = daio_index, 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic const struct rsc_ops daio_in_rsc_ops_20k2 = { 978c2ecf20Sopenharmony_ci .master = daio_master, 988c2ecf20Sopenharmony_ci .next_conj = daio_in_next_conj_20k2, 998c2ecf20Sopenharmony_ci .index = NULL, 1008c2ecf20Sopenharmony_ci .output_slot = daio_index, 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci switch (hw->chip_type) { 1068c2ecf20Sopenharmony_ci case ATC20K1: 1078c2ecf20Sopenharmony_ci switch (type) { 1088c2ecf20Sopenharmony_ci case SPDIFOO: return 0; 1098c2ecf20Sopenharmony_ci case SPDIFIO: return 0; 1108c2ecf20Sopenharmony_ci case SPDIFI1: return 1; 1118c2ecf20Sopenharmony_ci case LINEO1: return 4; 1128c2ecf20Sopenharmony_ci case LINEO2: return 7; 1138c2ecf20Sopenharmony_ci case LINEO3: return 5; 1148c2ecf20Sopenharmony_ci case LINEO4: return 6; 1158c2ecf20Sopenharmony_ci case LINEIM: return 7; 1168c2ecf20Sopenharmony_ci default: return -EINVAL; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci case ATC20K2: 1198c2ecf20Sopenharmony_ci switch (type) { 1208c2ecf20Sopenharmony_ci case SPDIFOO: return 0; 1218c2ecf20Sopenharmony_ci case SPDIFIO: return 0; 1228c2ecf20Sopenharmony_ci case LINEO1: return 4; 1238c2ecf20Sopenharmony_ci case LINEO2: return 7; 1248c2ecf20Sopenharmony_ci case LINEO3: return 5; 1258c2ecf20Sopenharmony_ci case LINEO4: return 6; 1268c2ecf20Sopenharmony_ci case LINEIM: return 4; 1278c2ecf20Sopenharmony_ci case MIC: return 5; 1288c2ecf20Sopenharmony_ci default: return -EINVAL; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci default: 1318c2ecf20Sopenharmony_ci return -EINVAL; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci dao->hw->dao_get_spos(dao->ctrl_blk, spos); 1408c2ecf20Sopenharmony_ci return 0; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic int dao_spdif_set_spos(struct dao *dao, unsigned int spos) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci dao->hw->dao_set_spos(dao->ctrl_blk, spos); 1468c2ecf20Sopenharmony_ci return 0; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int dao_commit_write(struct dao *dao) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci dao->hw->dao_commit_write(dao->hw, 1528c2ecf20Sopenharmony_ci daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); 1538c2ecf20Sopenharmony_ci return 0; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int dao_set_left_input(struct dao *dao, struct rsc *input) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct imapper *entry; 1598c2ecf20Sopenharmony_ci struct daio *daio = &dao->daio; 1608c2ecf20Sopenharmony_ci int i; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL); 1638c2ecf20Sopenharmony_ci if (!entry) 1648c2ecf20Sopenharmony_ci return -ENOMEM; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci dao->ops->clear_left_input(dao); 1678c2ecf20Sopenharmony_ci /* Program master and conjugate resources */ 1688c2ecf20Sopenharmony_ci input->ops->master(input); 1698c2ecf20Sopenharmony_ci daio->rscl.ops->master(&daio->rscl); 1708c2ecf20Sopenharmony_ci for (i = 0; i < daio->rscl.msr; i++, entry++) { 1718c2ecf20Sopenharmony_ci entry->slot = input->ops->output_slot(input); 1728c2ecf20Sopenharmony_ci entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl); 1738c2ecf20Sopenharmony_ci dao->mgr->imap_add(dao->mgr, entry); 1748c2ecf20Sopenharmony_ci dao->imappers[i] = entry; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci input->ops->next_conj(input); 1778c2ecf20Sopenharmony_ci daio->rscl.ops->next_conj(&daio->rscl); 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci input->ops->master(input); 1808c2ecf20Sopenharmony_ci daio->rscl.ops->master(&daio->rscl); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic int dao_set_right_input(struct dao *dao, struct rsc *input) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct imapper *entry; 1888c2ecf20Sopenharmony_ci struct daio *daio = &dao->daio; 1898c2ecf20Sopenharmony_ci int i; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL); 1928c2ecf20Sopenharmony_ci if (!entry) 1938c2ecf20Sopenharmony_ci return -ENOMEM; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci dao->ops->clear_right_input(dao); 1968c2ecf20Sopenharmony_ci /* Program master and conjugate resources */ 1978c2ecf20Sopenharmony_ci input->ops->master(input); 1988c2ecf20Sopenharmony_ci daio->rscr.ops->master(&daio->rscr); 1998c2ecf20Sopenharmony_ci for (i = 0; i < daio->rscr.msr; i++, entry++) { 2008c2ecf20Sopenharmony_ci entry->slot = input->ops->output_slot(input); 2018c2ecf20Sopenharmony_ci entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr); 2028c2ecf20Sopenharmony_ci dao->mgr->imap_add(dao->mgr, entry); 2038c2ecf20Sopenharmony_ci dao->imappers[daio->rscl.msr + i] = entry; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci input->ops->next_conj(input); 2068c2ecf20Sopenharmony_ci daio->rscr.ops->next_conj(&daio->rscr); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci input->ops->master(input); 2098c2ecf20Sopenharmony_ci daio->rscr.ops->master(&daio->rscr); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return 0; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic int dao_clear_left_input(struct dao *dao) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct imapper *entry; 2178c2ecf20Sopenharmony_ci struct daio *daio = &dao->daio; 2188c2ecf20Sopenharmony_ci int i; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (!dao->imappers[0]) 2218c2ecf20Sopenharmony_ci return 0; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci entry = dao->imappers[0]; 2248c2ecf20Sopenharmony_ci dao->mgr->imap_delete(dao->mgr, entry); 2258c2ecf20Sopenharmony_ci /* Program conjugate resources */ 2268c2ecf20Sopenharmony_ci for (i = 1; i < daio->rscl.msr; i++) { 2278c2ecf20Sopenharmony_ci entry = dao->imappers[i]; 2288c2ecf20Sopenharmony_ci dao->mgr->imap_delete(dao->mgr, entry); 2298c2ecf20Sopenharmony_ci dao->imappers[i] = NULL; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci kfree(dao->imappers[0]); 2338c2ecf20Sopenharmony_ci dao->imappers[0] = NULL; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic int dao_clear_right_input(struct dao *dao) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci struct imapper *entry; 2418c2ecf20Sopenharmony_ci struct daio *daio = &dao->daio; 2428c2ecf20Sopenharmony_ci int i; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (!dao->imappers[daio->rscl.msr]) 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci entry = dao->imappers[daio->rscl.msr]; 2488c2ecf20Sopenharmony_ci dao->mgr->imap_delete(dao->mgr, entry); 2498c2ecf20Sopenharmony_ci /* Program conjugate resources */ 2508c2ecf20Sopenharmony_ci for (i = 1; i < daio->rscr.msr; i++) { 2518c2ecf20Sopenharmony_ci entry = dao->imappers[daio->rscl.msr + i]; 2528c2ecf20Sopenharmony_ci dao->mgr->imap_delete(dao->mgr, entry); 2538c2ecf20Sopenharmony_ci dao->imappers[daio->rscl.msr + i] = NULL; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci kfree(dao->imappers[daio->rscl.msr]); 2578c2ecf20Sopenharmony_ci dao->imappers[daio->rscl.msr] = NULL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci return 0; 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic const struct dao_rsc_ops dao_ops = { 2638c2ecf20Sopenharmony_ci .set_spos = dao_spdif_set_spos, 2648c2ecf20Sopenharmony_ci .commit_write = dao_commit_write, 2658c2ecf20Sopenharmony_ci .get_spos = dao_spdif_get_spos, 2668c2ecf20Sopenharmony_ci .reinit = dao_rsc_reinit, 2678c2ecf20Sopenharmony_ci .set_left_input = dao_set_left_input, 2688c2ecf20Sopenharmony_ci .set_right_input = dao_set_right_input, 2698c2ecf20Sopenharmony_ci .clear_left_input = dao_clear_left_input, 2708c2ecf20Sopenharmony_ci .clear_right_input = dao_clear_right_input, 2718c2ecf20Sopenharmony_ci}; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic int dai_set_srt_srcl(struct dai *dai, struct rsc *src) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci src->ops->master(src); 2768c2ecf20Sopenharmony_ci dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src)); 2778c2ecf20Sopenharmony_ci return 0; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic int dai_set_srt_srcr(struct dai *dai, struct rsc *src) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci src->ops->master(src); 2838c2ecf20Sopenharmony_ci dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src)); 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int dai_set_srt_msr(struct dai *dai, unsigned int msr) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci unsigned int rsr; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci for (rsr = 0; msr > 1; msr >>= 1) 2928c2ecf20Sopenharmony_ci rsr++; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int dai_set_enb_src(struct dai *dai, unsigned int enb) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb); 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int dai_set_enb_srt(struct dai *dai, unsigned int enb) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci dai->hw->dai_srt_set_et(dai->ctrl_blk, enb); 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic int dai_commit_write(struct dai *dai) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci dai->hw->dai_commit_write(dai->hw, 3138c2ecf20Sopenharmony_ci daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); 3148c2ecf20Sopenharmony_ci return 0; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct dai_rsc_ops dai_ops = { 3188c2ecf20Sopenharmony_ci .set_srt_srcl = dai_set_srt_srcl, 3198c2ecf20Sopenharmony_ci .set_srt_srcr = dai_set_srt_srcr, 3208c2ecf20Sopenharmony_ci .set_srt_msr = dai_set_srt_msr, 3218c2ecf20Sopenharmony_ci .set_enb_src = dai_set_enb_src, 3228c2ecf20Sopenharmony_ci .set_enb_srt = dai_set_enb_srt, 3238c2ecf20Sopenharmony_ci .commit_write = dai_commit_write, 3248c2ecf20Sopenharmony_ci}; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic int daio_rsc_init(struct daio *daio, 3278c2ecf20Sopenharmony_ci const struct daio_desc *desc, 3288c2ecf20Sopenharmony_ci struct hw *hw) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci int err; 3318c2ecf20Sopenharmony_ci unsigned int idx_l, idx_r; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci switch (hw->chip_type) { 3348c2ecf20Sopenharmony_ci case ATC20K1: 3358c2ecf20Sopenharmony_ci idx_l = idx_20k1[desc->type].left; 3368c2ecf20Sopenharmony_ci idx_r = idx_20k1[desc->type].right; 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci case ATC20K2: 3398c2ecf20Sopenharmony_ci idx_l = idx_20k2[desc->type].left; 3408c2ecf20Sopenharmony_ci idx_r = idx_20k2[desc->type].right; 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci default: 3438c2ecf20Sopenharmony_ci return -EINVAL; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw); 3468c2ecf20Sopenharmony_ci if (err) 3478c2ecf20Sopenharmony_ci return err; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw); 3508c2ecf20Sopenharmony_ci if (err) 3518c2ecf20Sopenharmony_ci goto error1; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* Set daio->rscl/r->ops to daio specific ones */ 3548c2ecf20Sopenharmony_ci if (desc->type <= DAIO_OUT_MAX) { 3558c2ecf20Sopenharmony_ci daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; 3568c2ecf20Sopenharmony_ci } else { 3578c2ecf20Sopenharmony_ci switch (hw->chip_type) { 3588c2ecf20Sopenharmony_ci case ATC20K1: 3598c2ecf20Sopenharmony_ci daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; 3608c2ecf20Sopenharmony_ci break; 3618c2ecf20Sopenharmony_ci case ATC20K2: 3628c2ecf20Sopenharmony_ci daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2; 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci default: 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci daio->type = desc->type; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci return 0; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cierror1: 3738c2ecf20Sopenharmony_ci rsc_uninit(&daio->rscl); 3748c2ecf20Sopenharmony_ci return err; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic int daio_rsc_uninit(struct daio *daio) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci rsc_uninit(&daio->rscl); 3808c2ecf20Sopenharmony_ci rsc_uninit(&daio->rscr); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic int dao_rsc_init(struct dao *dao, 3868c2ecf20Sopenharmony_ci const struct daio_desc *desc, 3878c2ecf20Sopenharmony_ci struct daio_mgr *mgr) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct hw *hw = mgr->mgr.hw; 3908c2ecf20Sopenharmony_ci unsigned int conf; 3918c2ecf20Sopenharmony_ci int err; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw); 3948c2ecf20Sopenharmony_ci if (err) 3958c2ecf20Sopenharmony_ci return err; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2), 3988c2ecf20Sopenharmony_ci GFP_KERNEL); 3998c2ecf20Sopenharmony_ci if (!dao->imappers) { 4008c2ecf20Sopenharmony_ci err = -ENOMEM; 4018c2ecf20Sopenharmony_ci goto error1; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci dao->ops = &dao_ops; 4048c2ecf20Sopenharmony_ci dao->mgr = mgr; 4058c2ecf20Sopenharmony_ci dao->hw = hw; 4068c2ecf20Sopenharmony_ci err = hw->dao_get_ctrl_blk(&dao->ctrl_blk); 4078c2ecf20Sopenharmony_ci if (err) 4088c2ecf20Sopenharmony_ci goto error2; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, 4118c2ecf20Sopenharmony_ci daio_device_index(dao->daio.type, hw)); 4128c2ecf20Sopenharmony_ci hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci conf = (desc->msr & 0x7) | (desc->passthru << 3); 4158c2ecf20Sopenharmony_ci hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk, 4168c2ecf20Sopenharmony_ci daio_device_index(dao->daio.type, hw), conf); 4178c2ecf20Sopenharmony_ci hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, 4188c2ecf20Sopenharmony_ci daio_device_index(dao->daio.type, hw)); 4198c2ecf20Sopenharmony_ci hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci return 0; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cierror2: 4248c2ecf20Sopenharmony_ci kfree(dao->imappers); 4258c2ecf20Sopenharmony_ci dao->imappers = NULL; 4268c2ecf20Sopenharmony_cierror1: 4278c2ecf20Sopenharmony_ci daio_rsc_uninit(&dao->daio); 4288c2ecf20Sopenharmony_ci return err; 4298c2ecf20Sopenharmony_ci} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistatic int dao_rsc_uninit(struct dao *dao) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci if (dao->imappers) { 4348c2ecf20Sopenharmony_ci if (dao->imappers[0]) 4358c2ecf20Sopenharmony_ci dao_clear_left_input(dao); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (dao->imappers[dao->daio.rscl.msr]) 4388c2ecf20Sopenharmony_ci dao_clear_right_input(dao); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci kfree(dao->imappers); 4418c2ecf20Sopenharmony_ci dao->imappers = NULL; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci dao->hw->dao_put_ctrl_blk(dao->ctrl_blk); 4448c2ecf20Sopenharmony_ci dao->hw = dao->ctrl_blk = NULL; 4458c2ecf20Sopenharmony_ci daio_rsc_uninit(&dao->daio); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci return 0; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct daio_mgr *mgr = dao->mgr; 4538c2ecf20Sopenharmony_ci struct daio_desc dsc = {0}; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci dsc.type = dao->daio.type; 4568c2ecf20Sopenharmony_ci dsc.msr = desc->msr; 4578c2ecf20Sopenharmony_ci dsc.passthru = desc->passthru; 4588c2ecf20Sopenharmony_ci dao_rsc_uninit(dao); 4598c2ecf20Sopenharmony_ci return dao_rsc_init(dao, &dsc, mgr); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic int dai_rsc_init(struct dai *dai, 4638c2ecf20Sopenharmony_ci const struct daio_desc *desc, 4648c2ecf20Sopenharmony_ci struct daio_mgr *mgr) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci int err; 4678c2ecf20Sopenharmony_ci struct hw *hw = mgr->mgr.hw; 4688c2ecf20Sopenharmony_ci unsigned int rsr, msr; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw); 4718c2ecf20Sopenharmony_ci if (err) 4728c2ecf20Sopenharmony_ci return err; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci dai->ops = &dai_ops; 4758c2ecf20Sopenharmony_ci dai->hw = mgr->mgr.hw; 4768c2ecf20Sopenharmony_ci err = hw->dai_get_ctrl_blk(&dai->ctrl_blk); 4778c2ecf20Sopenharmony_ci if (err) 4788c2ecf20Sopenharmony_ci goto error1; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1) 4818c2ecf20Sopenharmony_ci rsr++; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 4848c2ecf20Sopenharmony_ci hw->dai_srt_set_drat(dai->ctrl_blk, 0); 4858c2ecf20Sopenharmony_ci /* default to disabling control of a SRC */ 4868c2ecf20Sopenharmony_ci hw->dai_srt_set_ec(dai->ctrl_blk, 0); 4878c2ecf20Sopenharmony_ci hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */ 4888c2ecf20Sopenharmony_ci hw->dai_commit_write(hw, 4898c2ecf20Sopenharmony_ci daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci return 0; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cierror1: 4948c2ecf20Sopenharmony_ci daio_rsc_uninit(&dai->daio); 4958c2ecf20Sopenharmony_ci return err; 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic int dai_rsc_uninit(struct dai *dai) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci dai->hw->dai_put_ctrl_blk(dai->ctrl_blk); 5018c2ecf20Sopenharmony_ci dai->hw = dai->ctrl_blk = NULL; 5028c2ecf20Sopenharmony_ci daio_rsc_uninit(&dai->daio); 5038c2ecf20Sopenharmony_ci return 0; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) 5098c2ecf20Sopenharmony_ci return -ENOENT; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return 0; 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci return 0; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic int get_daio_rsc(struct daio_mgr *mgr, 5248c2ecf20Sopenharmony_ci const struct daio_desc *desc, 5258c2ecf20Sopenharmony_ci struct daio **rdaio) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci int err; 5288c2ecf20Sopenharmony_ci unsigned long flags; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci *rdaio = NULL; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* Check whether there are sufficient daio resources to meet request. */ 5338c2ecf20Sopenharmony_ci spin_lock_irqsave(&mgr->mgr_lock, flags); 5348c2ecf20Sopenharmony_ci err = daio_mgr_get_rsc(&mgr->mgr, desc->type); 5358c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mgr->mgr_lock, flags); 5368c2ecf20Sopenharmony_ci if (err) { 5378c2ecf20Sopenharmony_ci dev_err(mgr->card->dev, 5388c2ecf20Sopenharmony_ci "Can't meet DAIO resource request!\n"); 5398c2ecf20Sopenharmony_ci return err; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci err = -ENOMEM; 5438c2ecf20Sopenharmony_ci /* Allocate mem for daio resource */ 5448c2ecf20Sopenharmony_ci if (desc->type <= DAIO_OUT_MAX) { 5458c2ecf20Sopenharmony_ci struct dao *dao = kzalloc(sizeof(*dao), GFP_KERNEL); 5468c2ecf20Sopenharmony_ci if (!dao) 5478c2ecf20Sopenharmony_ci goto error; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci err = dao_rsc_init(dao, desc, mgr); 5508c2ecf20Sopenharmony_ci if (err) { 5518c2ecf20Sopenharmony_ci kfree(dao); 5528c2ecf20Sopenharmony_ci goto error; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci *rdaio = &dao->daio; 5568c2ecf20Sopenharmony_ci } else { 5578c2ecf20Sopenharmony_ci struct dai *dai = kzalloc(sizeof(*dai), GFP_KERNEL); 5588c2ecf20Sopenharmony_ci if (!dai) 5598c2ecf20Sopenharmony_ci goto error; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci err = dai_rsc_init(dai, desc, mgr); 5628c2ecf20Sopenharmony_ci if (err) { 5638c2ecf20Sopenharmony_ci kfree(dai); 5648c2ecf20Sopenharmony_ci goto error; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci *rdaio = &dai->daio; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci mgr->daio_enable(mgr, *rdaio); 5718c2ecf20Sopenharmony_ci mgr->commit_write(mgr); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci return 0; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cierror: 5768c2ecf20Sopenharmony_ci spin_lock_irqsave(&mgr->mgr_lock, flags); 5778c2ecf20Sopenharmony_ci daio_mgr_put_rsc(&mgr->mgr, desc->type); 5788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mgr->mgr_lock, flags); 5798c2ecf20Sopenharmony_ci return err; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci unsigned long flags; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci mgr->daio_disable(mgr, daio); 5878c2ecf20Sopenharmony_ci mgr->commit_write(mgr); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci spin_lock_irqsave(&mgr->mgr_lock, flags); 5908c2ecf20Sopenharmony_ci daio_mgr_put_rsc(&mgr->mgr, daio->type); 5918c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mgr->mgr_lock, flags); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (daio->type <= DAIO_OUT_MAX) { 5948c2ecf20Sopenharmony_ci dao_rsc_uninit(container_of(daio, struct dao, daio)); 5958c2ecf20Sopenharmony_ci kfree(container_of(daio, struct dao, daio)); 5968c2ecf20Sopenharmony_ci } else { 5978c2ecf20Sopenharmony_ci dai_rsc_uninit(container_of(daio, struct dai, daio)); 5988c2ecf20Sopenharmony_ci kfree(container_of(daio, struct dai, daio)); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci return 0; 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci struct hw *hw = mgr->mgr.hw; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (DAIO_OUT_MAX >= daio->type) { 6098c2ecf20Sopenharmony_ci hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, 6108c2ecf20Sopenharmony_ci daio_device_index(daio->type, hw)); 6118c2ecf20Sopenharmony_ci } else { 6128c2ecf20Sopenharmony_ci hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk, 6138c2ecf20Sopenharmony_ci daio_device_index(daio->type, hw)); 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci return 0; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci struct hw *hw = mgr->mgr.hw; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (DAIO_OUT_MAX >= daio->type) { 6238c2ecf20Sopenharmony_ci hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, 6248c2ecf20Sopenharmony_ci daio_device_index(daio->type, hw)); 6258c2ecf20Sopenharmony_ci } else { 6268c2ecf20Sopenharmony_ci hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk, 6278c2ecf20Sopenharmony_ci daio_device_index(daio->type, hw)); 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci return 0; 6308c2ecf20Sopenharmony_ci} 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_cistatic int daio_map_op(void *data, struct imapper *entry) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr; 6358c2ecf20Sopenharmony_ci struct hw *hw = mgr->hw; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot); 6388c2ecf20Sopenharmony_ci hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next); 6398c2ecf20Sopenharmony_ci hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr); 6408c2ecf20Sopenharmony_ci hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci return 0; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci unsigned long flags; 6488c2ecf20Sopenharmony_ci int err; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci spin_lock_irqsave(&mgr->imap_lock, flags); 6518c2ecf20Sopenharmony_ci if (!entry->addr && mgr->init_imap_added) { 6528c2ecf20Sopenharmony_ci input_mapper_delete(&mgr->imappers, mgr->init_imap, 6538c2ecf20Sopenharmony_ci daio_map_op, mgr); 6548c2ecf20Sopenharmony_ci mgr->init_imap_added = 0; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); 6578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mgr->imap_lock, flags); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci return err; 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cistatic int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci unsigned long flags; 6658c2ecf20Sopenharmony_ci int err; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci spin_lock_irqsave(&mgr->imap_lock, flags); 6688c2ecf20Sopenharmony_ci err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); 6698c2ecf20Sopenharmony_ci if (list_empty(&mgr->imappers)) { 6708c2ecf20Sopenharmony_ci input_mapper_add(&mgr->imappers, mgr->init_imap, 6718c2ecf20Sopenharmony_ci daio_map_op, mgr); 6728c2ecf20Sopenharmony_ci mgr->init_imap_added = 1; 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mgr->imap_lock, flags); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return err; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic int daio_mgr_commit_write(struct daio_mgr *mgr) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci struct hw *hw = mgr->mgr.hw; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 6848c2ecf20Sopenharmony_ci return 0; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ciint daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci int err, i; 6908c2ecf20Sopenharmony_ci struct daio_mgr *daio_mgr; 6918c2ecf20Sopenharmony_ci struct imapper *entry; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci *rdaio_mgr = NULL; 6948c2ecf20Sopenharmony_ci daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL); 6958c2ecf20Sopenharmony_ci if (!daio_mgr) 6968c2ecf20Sopenharmony_ci return -ENOMEM; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); 6998c2ecf20Sopenharmony_ci if (err) 7008c2ecf20Sopenharmony_ci goto error1; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci spin_lock_init(&daio_mgr->mgr_lock); 7038c2ecf20Sopenharmony_ci spin_lock_init(&daio_mgr->imap_lock); 7048c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&daio_mgr->imappers); 7058c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_KERNEL); 7068c2ecf20Sopenharmony_ci if (!entry) { 7078c2ecf20Sopenharmony_ci err = -ENOMEM; 7088c2ecf20Sopenharmony_ci goto error2; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci entry->slot = entry->addr = entry->next = entry->user = 0; 7118c2ecf20Sopenharmony_ci list_add(&entry->list, &daio_mgr->imappers); 7128c2ecf20Sopenharmony_ci daio_mgr->init_imap = entry; 7138c2ecf20Sopenharmony_ci daio_mgr->init_imap_added = 1; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci daio_mgr->get_daio = get_daio_rsc; 7168c2ecf20Sopenharmony_ci daio_mgr->put_daio = put_daio_rsc; 7178c2ecf20Sopenharmony_ci daio_mgr->daio_enable = daio_mgr_enb_daio; 7188c2ecf20Sopenharmony_ci daio_mgr->daio_disable = daio_mgr_dsb_daio; 7198c2ecf20Sopenharmony_ci daio_mgr->imap_add = daio_imap_add; 7208c2ecf20Sopenharmony_ci daio_mgr->imap_delete = daio_imap_delete; 7218c2ecf20Sopenharmony_ci daio_mgr->commit_write = daio_mgr_commit_write; 7228c2ecf20Sopenharmony_ci daio_mgr->card = hw->card; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 7258c2ecf20Sopenharmony_ci hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); 7268c2ecf20Sopenharmony_ci hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci *rdaio_mgr = daio_mgr; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci return 0; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_cierror2: 7358c2ecf20Sopenharmony_ci rsc_mgr_uninit(&daio_mgr->mgr); 7368c2ecf20Sopenharmony_cierror1: 7378c2ecf20Sopenharmony_ci kfree(daio_mgr); 7388c2ecf20Sopenharmony_ci return err; 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ciint daio_mgr_destroy(struct daio_mgr *daio_mgr) 7428c2ecf20Sopenharmony_ci{ 7438c2ecf20Sopenharmony_ci unsigned long flags; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* free daio input mapper list */ 7468c2ecf20Sopenharmony_ci spin_lock_irqsave(&daio_mgr->imap_lock, flags); 7478c2ecf20Sopenharmony_ci free_input_mapper_list(&daio_mgr->imappers); 7488c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&daio_mgr->imap_lock, flags); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci rsc_mgr_uninit(&daio_mgr->mgr); 7518c2ecf20Sopenharmony_ci kfree(daio_mgr); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci return 0; 7548c2ecf20Sopenharmony_ci} 7558c2ecf20Sopenharmony_ci 756