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