1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 4 * 5 * @File ctdaio.c 6 * 7 * @Brief 8 * This file contains the implementation of Digital Audio Input Output 9 * resource management object. 10 * 11 * @Author Liu Chun 12 * @Date May 23 2008 13 */ 14 15 #include "ctdaio.h" 16 #include "cthardware.h" 17 #include "ctimap.h" 18 #include <linux/slab.h> 19 #include <linux/kernel.h> 20 21 #define DAIO_OUT_MAX SPDIFOO 22 23 struct daio_usage { 24 unsigned short data; 25 }; 26 27 struct daio_rsc_idx { 28 unsigned short left; 29 unsigned short right; 30 }; 31 32 static const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { 33 [LINEO1] = {.left = 0x00, .right = 0x01}, 34 [LINEO2] = {.left = 0x18, .right = 0x19}, 35 [LINEO3] = {.left = 0x08, .right = 0x09}, 36 [LINEO4] = {.left = 0x10, .right = 0x11}, 37 [LINEIM] = {.left = 0x1b5, .right = 0x1bd}, 38 [SPDIFOO] = {.left = 0x20, .right = 0x21}, 39 [SPDIFIO] = {.left = 0x15, .right = 0x1d}, 40 [SPDIFI1] = {.left = 0x95, .right = 0x9d}, 41 }; 42 43 static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { 44 [LINEO1] = {.left = 0x40, .right = 0x41}, 45 [LINEO2] = {.left = 0x60, .right = 0x61}, 46 [LINEO3] = {.left = 0x50, .right = 0x51}, 47 [LINEO4] = {.left = 0x70, .right = 0x71}, 48 [LINEIM] = {.left = 0x45, .right = 0xc5}, 49 [MIC] = {.left = 0x55, .right = 0xd5}, 50 [SPDIFOO] = {.left = 0x00, .right = 0x01}, 51 [SPDIFIO] = {.left = 0x05, .right = 0x85}, 52 }; 53 54 static void daio_master(struct rsc *rsc) 55 { 56 /* Actually, this is not the resource index of DAIO. 57 * For DAO, it is the input mapper index. And, for DAI, 58 * it is the output time-slot index. */ 59 rsc->conj = rsc->idx; 60 } 61 62 static int daio_index(const struct rsc *rsc) 63 { 64 return rsc->conj; 65 } 66 67 static void daio_out_next_conj(struct rsc *rsc) 68 { 69 rsc->conj += 2; 70 } 71 72 static void daio_in_next_conj_20k1(struct rsc *rsc) 73 { 74 rsc->conj += 0x200; 75 } 76 77 static void daio_in_next_conj_20k2(struct rsc *rsc) 78 { 79 rsc->conj += 0x100; 80 } 81 82 static const struct rsc_ops daio_out_rsc_ops = { 83 .master = daio_master, 84 .next_conj = daio_out_next_conj, 85 .index = daio_index, 86 .output_slot = NULL, 87 }; 88 89 static const struct rsc_ops daio_in_rsc_ops_20k1 = { 90 .master = daio_master, 91 .next_conj = daio_in_next_conj_20k1, 92 .index = NULL, 93 .output_slot = daio_index, 94 }; 95 96 static const struct rsc_ops daio_in_rsc_ops_20k2 = { 97 .master = daio_master, 98 .next_conj = daio_in_next_conj_20k2, 99 .index = NULL, 100 .output_slot = daio_index, 101 }; 102 103 static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) 104 { 105 switch (hw->chip_type) { 106 case ATC20K1: 107 switch (type) { 108 case SPDIFOO: return 0; 109 case SPDIFIO: return 0; 110 case SPDIFI1: return 1; 111 case LINEO1: return 4; 112 case LINEO2: return 7; 113 case LINEO3: return 5; 114 case LINEO4: return 6; 115 case LINEIM: return 7; 116 default: return -EINVAL; 117 } 118 case ATC20K2: 119 switch (type) { 120 case SPDIFOO: return 0; 121 case SPDIFIO: return 0; 122 case LINEO1: return 4; 123 case LINEO2: return 7; 124 case LINEO3: return 5; 125 case LINEO4: return 6; 126 case LINEIM: return 4; 127 case MIC: return 5; 128 default: return -EINVAL; 129 } 130 default: 131 return -EINVAL; 132 } 133 } 134 135 static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); 136 137 static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) 138 { 139 dao->hw->dao_get_spos(dao->ctrl_blk, spos); 140 return 0; 141 } 142 143 static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) 144 { 145 dao->hw->dao_set_spos(dao->ctrl_blk, spos); 146 return 0; 147 } 148 149 static int dao_commit_write(struct dao *dao) 150 { 151 dao->hw->dao_commit_write(dao->hw, 152 daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); 153 return 0; 154 } 155 156 static int dao_set_left_input(struct dao *dao, struct rsc *input) 157 { 158 struct imapper *entry; 159 struct daio *daio = &dao->daio; 160 int i; 161 162 entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL); 163 if (!entry) 164 return -ENOMEM; 165 166 dao->ops->clear_left_input(dao); 167 /* Program master and conjugate resources */ 168 input->ops->master(input); 169 daio->rscl.ops->master(&daio->rscl); 170 for (i = 0; i < daio->rscl.msr; i++, entry++) { 171 entry->slot = input->ops->output_slot(input); 172 entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl); 173 dao->mgr->imap_add(dao->mgr, entry); 174 dao->imappers[i] = entry; 175 176 input->ops->next_conj(input); 177 daio->rscl.ops->next_conj(&daio->rscl); 178 } 179 input->ops->master(input); 180 daio->rscl.ops->master(&daio->rscl); 181 182 return 0; 183 } 184 185 static int dao_set_right_input(struct dao *dao, struct rsc *input) 186 { 187 struct imapper *entry; 188 struct daio *daio = &dao->daio; 189 int i; 190 191 entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL); 192 if (!entry) 193 return -ENOMEM; 194 195 dao->ops->clear_right_input(dao); 196 /* Program master and conjugate resources */ 197 input->ops->master(input); 198 daio->rscr.ops->master(&daio->rscr); 199 for (i = 0; i < daio->rscr.msr; i++, entry++) { 200 entry->slot = input->ops->output_slot(input); 201 entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr); 202 dao->mgr->imap_add(dao->mgr, entry); 203 dao->imappers[daio->rscl.msr + i] = entry; 204 205 input->ops->next_conj(input); 206 daio->rscr.ops->next_conj(&daio->rscr); 207 } 208 input->ops->master(input); 209 daio->rscr.ops->master(&daio->rscr); 210 211 return 0; 212 } 213 214 static int dao_clear_left_input(struct dao *dao) 215 { 216 struct imapper *entry; 217 struct daio *daio = &dao->daio; 218 int i; 219 220 if (!dao->imappers[0]) 221 return 0; 222 223 entry = dao->imappers[0]; 224 dao->mgr->imap_delete(dao->mgr, entry); 225 /* Program conjugate resources */ 226 for (i = 1; i < daio->rscl.msr; i++) { 227 entry = dao->imappers[i]; 228 dao->mgr->imap_delete(dao->mgr, entry); 229 dao->imappers[i] = NULL; 230 } 231 232 kfree(dao->imappers[0]); 233 dao->imappers[0] = NULL; 234 235 return 0; 236 } 237 238 static int dao_clear_right_input(struct dao *dao) 239 { 240 struct imapper *entry; 241 struct daio *daio = &dao->daio; 242 int i; 243 244 if (!dao->imappers[daio->rscl.msr]) 245 return 0; 246 247 entry = dao->imappers[daio->rscl.msr]; 248 dao->mgr->imap_delete(dao->mgr, entry); 249 /* Program conjugate resources */ 250 for (i = 1; i < daio->rscr.msr; i++) { 251 entry = dao->imappers[daio->rscl.msr + i]; 252 dao->mgr->imap_delete(dao->mgr, entry); 253 dao->imappers[daio->rscl.msr + i] = NULL; 254 } 255 256 kfree(dao->imappers[daio->rscl.msr]); 257 dao->imappers[daio->rscl.msr] = NULL; 258 259 return 0; 260 } 261 262 static const struct dao_rsc_ops dao_ops = { 263 .set_spos = dao_spdif_set_spos, 264 .commit_write = dao_commit_write, 265 .get_spos = dao_spdif_get_spos, 266 .reinit = dao_rsc_reinit, 267 .set_left_input = dao_set_left_input, 268 .set_right_input = dao_set_right_input, 269 .clear_left_input = dao_clear_left_input, 270 .clear_right_input = dao_clear_right_input, 271 }; 272 273 static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) 274 { 275 src->ops->master(src); 276 dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src)); 277 return 0; 278 } 279 280 static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) 281 { 282 src->ops->master(src); 283 dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src)); 284 return 0; 285 } 286 287 static int dai_set_srt_msr(struct dai *dai, unsigned int msr) 288 { 289 unsigned int rsr; 290 291 for (rsr = 0; msr > 1; msr >>= 1) 292 rsr++; 293 294 dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 295 return 0; 296 } 297 298 static int dai_set_enb_src(struct dai *dai, unsigned int enb) 299 { 300 dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb); 301 return 0; 302 } 303 304 static int dai_set_enb_srt(struct dai *dai, unsigned int enb) 305 { 306 dai->hw->dai_srt_set_et(dai->ctrl_blk, enb); 307 return 0; 308 } 309 310 static int dai_commit_write(struct dai *dai) 311 { 312 dai->hw->dai_commit_write(dai->hw, 313 daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); 314 return 0; 315 } 316 317 static const struct dai_rsc_ops dai_ops = { 318 .set_srt_srcl = dai_set_srt_srcl, 319 .set_srt_srcr = dai_set_srt_srcr, 320 .set_srt_msr = dai_set_srt_msr, 321 .set_enb_src = dai_set_enb_src, 322 .set_enb_srt = dai_set_enb_srt, 323 .commit_write = dai_commit_write, 324 }; 325 326 static int daio_rsc_init(struct daio *daio, 327 const struct daio_desc *desc, 328 struct hw *hw) 329 { 330 int err; 331 unsigned int idx_l, idx_r; 332 333 switch (hw->chip_type) { 334 case ATC20K1: 335 idx_l = idx_20k1[desc->type].left; 336 idx_r = idx_20k1[desc->type].right; 337 break; 338 case ATC20K2: 339 idx_l = idx_20k2[desc->type].left; 340 idx_r = idx_20k2[desc->type].right; 341 break; 342 default: 343 return -EINVAL; 344 } 345 err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw); 346 if (err) 347 return err; 348 349 err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw); 350 if (err) 351 goto error1; 352 353 /* Set daio->rscl/r->ops to daio specific ones */ 354 if (desc->type <= DAIO_OUT_MAX) { 355 daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; 356 } else { 357 switch (hw->chip_type) { 358 case ATC20K1: 359 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; 360 break; 361 case ATC20K2: 362 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2; 363 break; 364 default: 365 break; 366 } 367 } 368 daio->type = desc->type; 369 370 return 0; 371 372 error1: 373 rsc_uninit(&daio->rscl); 374 return err; 375 } 376 377 static int daio_rsc_uninit(struct daio *daio) 378 { 379 rsc_uninit(&daio->rscl); 380 rsc_uninit(&daio->rscr); 381 382 return 0; 383 } 384 385 static int dao_rsc_init(struct dao *dao, 386 const struct daio_desc *desc, 387 struct daio_mgr *mgr) 388 { 389 struct hw *hw = mgr->mgr.hw; 390 unsigned int conf; 391 int err; 392 393 err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw); 394 if (err) 395 return err; 396 397 dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2), 398 GFP_KERNEL); 399 if (!dao->imappers) { 400 err = -ENOMEM; 401 goto error1; 402 } 403 dao->ops = &dao_ops; 404 dao->mgr = mgr; 405 dao->hw = hw; 406 err = hw->dao_get_ctrl_blk(&dao->ctrl_blk); 407 if (err) 408 goto error2; 409 410 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, 411 daio_device_index(dao->daio.type, hw)); 412 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 413 414 conf = (desc->msr & 0x7) | (desc->passthru << 3); 415 hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk, 416 daio_device_index(dao->daio.type, hw), conf); 417 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, 418 daio_device_index(dao->daio.type, hw)); 419 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 420 421 return 0; 422 423 error2: 424 kfree(dao->imappers); 425 dao->imappers = NULL; 426 error1: 427 daio_rsc_uninit(&dao->daio); 428 return err; 429 } 430 431 static int dao_rsc_uninit(struct dao *dao) 432 { 433 if (dao->imappers) { 434 if (dao->imappers[0]) 435 dao_clear_left_input(dao); 436 437 if (dao->imappers[dao->daio.rscl.msr]) 438 dao_clear_right_input(dao); 439 440 kfree(dao->imappers); 441 dao->imappers = NULL; 442 } 443 dao->hw->dao_put_ctrl_blk(dao->ctrl_blk); 444 dao->hw = dao->ctrl_blk = NULL; 445 daio_rsc_uninit(&dao->daio); 446 447 return 0; 448 } 449 450 static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc) 451 { 452 struct daio_mgr *mgr = dao->mgr; 453 struct daio_desc dsc = {0}; 454 455 dsc.type = dao->daio.type; 456 dsc.msr = desc->msr; 457 dsc.passthru = desc->passthru; 458 dao_rsc_uninit(dao); 459 return dao_rsc_init(dao, &dsc, mgr); 460 } 461 462 static int dai_rsc_init(struct dai *dai, 463 const struct daio_desc *desc, 464 struct daio_mgr *mgr) 465 { 466 int err; 467 struct hw *hw = mgr->mgr.hw; 468 unsigned int rsr, msr; 469 470 err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw); 471 if (err) 472 return err; 473 474 dai->ops = &dai_ops; 475 dai->hw = mgr->mgr.hw; 476 err = hw->dai_get_ctrl_blk(&dai->ctrl_blk); 477 if (err) 478 goto error1; 479 480 for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1) 481 rsr++; 482 483 hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 484 hw->dai_srt_set_drat(dai->ctrl_blk, 0); 485 /* default to disabling control of a SRC */ 486 hw->dai_srt_set_ec(dai->ctrl_blk, 0); 487 hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */ 488 hw->dai_commit_write(hw, 489 daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); 490 491 return 0; 492 493 error1: 494 daio_rsc_uninit(&dai->daio); 495 return err; 496 } 497 498 static int dai_rsc_uninit(struct dai *dai) 499 { 500 dai->hw->dai_put_ctrl_blk(dai->ctrl_blk); 501 dai->hw = dai->ctrl_blk = NULL; 502 daio_rsc_uninit(&dai->daio); 503 return 0; 504 } 505 506 static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 507 { 508 if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) 509 return -ENOENT; 510 511 ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); 512 513 return 0; 514 } 515 516 static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 517 { 518 ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); 519 520 return 0; 521 } 522 523 static int get_daio_rsc(struct daio_mgr *mgr, 524 const struct daio_desc *desc, 525 struct daio **rdaio) 526 { 527 int err; 528 unsigned long flags; 529 530 *rdaio = NULL; 531 532 /* Check whether there are sufficient daio resources to meet request. */ 533 spin_lock_irqsave(&mgr->mgr_lock, flags); 534 err = daio_mgr_get_rsc(&mgr->mgr, desc->type); 535 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 536 if (err) { 537 dev_err(mgr->card->dev, 538 "Can't meet DAIO resource request!\n"); 539 return err; 540 } 541 542 err = -ENOMEM; 543 /* Allocate mem for daio resource */ 544 if (desc->type <= DAIO_OUT_MAX) { 545 struct dao *dao = kzalloc(sizeof(*dao), GFP_KERNEL); 546 if (!dao) 547 goto error; 548 549 err = dao_rsc_init(dao, desc, mgr); 550 if (err) { 551 kfree(dao); 552 goto error; 553 } 554 555 *rdaio = &dao->daio; 556 } else { 557 struct dai *dai = kzalloc(sizeof(*dai), GFP_KERNEL); 558 if (!dai) 559 goto error; 560 561 err = dai_rsc_init(dai, desc, mgr); 562 if (err) { 563 kfree(dai); 564 goto error; 565 } 566 567 *rdaio = &dai->daio; 568 } 569 570 mgr->daio_enable(mgr, *rdaio); 571 mgr->commit_write(mgr); 572 573 return 0; 574 575 error: 576 spin_lock_irqsave(&mgr->mgr_lock, flags); 577 daio_mgr_put_rsc(&mgr->mgr, desc->type); 578 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 579 return err; 580 } 581 582 static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) 583 { 584 unsigned long flags; 585 586 mgr->daio_disable(mgr, daio); 587 mgr->commit_write(mgr); 588 589 spin_lock_irqsave(&mgr->mgr_lock, flags); 590 daio_mgr_put_rsc(&mgr->mgr, daio->type); 591 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 592 593 if (daio->type <= DAIO_OUT_MAX) { 594 dao_rsc_uninit(container_of(daio, struct dao, daio)); 595 kfree(container_of(daio, struct dao, daio)); 596 } else { 597 dai_rsc_uninit(container_of(daio, struct dai, daio)); 598 kfree(container_of(daio, struct dai, daio)); 599 } 600 601 return 0; 602 } 603 604 static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio) 605 { 606 struct hw *hw = mgr->mgr.hw; 607 608 if (DAIO_OUT_MAX >= daio->type) { 609 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, 610 daio_device_index(daio->type, hw)); 611 } else { 612 hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk, 613 daio_device_index(daio->type, hw)); 614 } 615 return 0; 616 } 617 618 static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio) 619 { 620 struct hw *hw = mgr->mgr.hw; 621 622 if (DAIO_OUT_MAX >= daio->type) { 623 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, 624 daio_device_index(daio->type, hw)); 625 } else { 626 hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk, 627 daio_device_index(daio->type, hw)); 628 } 629 return 0; 630 } 631 632 static int daio_map_op(void *data, struct imapper *entry) 633 { 634 struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr; 635 struct hw *hw = mgr->hw; 636 637 hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot); 638 hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next); 639 hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr); 640 hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk); 641 642 return 0; 643 } 644 645 static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) 646 { 647 unsigned long flags; 648 int err; 649 650 spin_lock_irqsave(&mgr->imap_lock, flags); 651 if (!entry->addr && mgr->init_imap_added) { 652 input_mapper_delete(&mgr->imappers, mgr->init_imap, 653 daio_map_op, mgr); 654 mgr->init_imap_added = 0; 655 } 656 err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); 657 spin_unlock_irqrestore(&mgr->imap_lock, flags); 658 659 return err; 660 } 661 662 static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) 663 { 664 unsigned long flags; 665 int err; 666 667 spin_lock_irqsave(&mgr->imap_lock, flags); 668 err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); 669 if (list_empty(&mgr->imappers)) { 670 input_mapper_add(&mgr->imappers, mgr->init_imap, 671 daio_map_op, mgr); 672 mgr->init_imap_added = 1; 673 } 674 spin_unlock_irqrestore(&mgr->imap_lock, flags); 675 676 return err; 677 } 678 679 static int daio_mgr_commit_write(struct daio_mgr *mgr) 680 { 681 struct hw *hw = mgr->mgr.hw; 682 683 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 684 return 0; 685 } 686 687 int daio_mgr_create(struct hw *hw, void **rdaio_mgr) 688 { 689 int err, i; 690 struct daio_mgr *daio_mgr; 691 struct imapper *entry; 692 693 *rdaio_mgr = NULL; 694 daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL); 695 if (!daio_mgr) 696 return -ENOMEM; 697 698 err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); 699 if (err) 700 goto error1; 701 702 spin_lock_init(&daio_mgr->mgr_lock); 703 spin_lock_init(&daio_mgr->imap_lock); 704 INIT_LIST_HEAD(&daio_mgr->imappers); 705 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 706 if (!entry) { 707 err = -ENOMEM; 708 goto error2; 709 } 710 entry->slot = entry->addr = entry->next = entry->user = 0; 711 list_add(&entry->list, &daio_mgr->imappers); 712 daio_mgr->init_imap = entry; 713 daio_mgr->init_imap_added = 1; 714 715 daio_mgr->get_daio = get_daio_rsc; 716 daio_mgr->put_daio = put_daio_rsc; 717 daio_mgr->daio_enable = daio_mgr_enb_daio; 718 daio_mgr->daio_disable = daio_mgr_dsb_daio; 719 daio_mgr->imap_add = daio_imap_add; 720 daio_mgr->imap_delete = daio_imap_delete; 721 daio_mgr->commit_write = daio_mgr_commit_write; 722 daio_mgr->card = hw->card; 723 724 for (i = 0; i < 8; i++) { 725 hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); 726 hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); 727 } 728 hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); 729 730 *rdaio_mgr = daio_mgr; 731 732 return 0; 733 734 error2: 735 rsc_mgr_uninit(&daio_mgr->mgr); 736 error1: 737 kfree(daio_mgr); 738 return err; 739 } 740 741 int daio_mgr_destroy(void *ptr) 742 { 743 struct daio_mgr *daio_mgr = ptr; 744 unsigned long flags; 745 746 /* free daio input mapper list */ 747 spin_lock_irqsave(&daio_mgr->imap_lock, flags); 748 free_input_mapper_list(&daio_mgr->imappers); 749 spin_unlock_irqrestore(&daio_mgr->imap_lock, flags); 750 751 rsc_mgr_uninit(&daio_mgr->mgr); 752 kfree(daio_mgr); 753 754 return 0; 755 } 756 757
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.