linux/sound/pci/ctxfi/ctsrc.c
<<
>>
Prefs
   1/**
   2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   3 *
   4 * This source file is released under GPL v2 license (no other versions).
   5 * See the COPYING file included in the main directory of this source
   6 * distribution for the license terms and conditions.
   7 *
   8 * @File        ctsrc.c
   9 *
  10 * @Brief
  11 * This file contains the implementation of the Sample Rate Convertor
  12 * resource management object.
  13 *
  14 * @Author      Liu Chun
  15 * @Date        May 13 2008
  16 *
  17 */
  18
  19#include "ctsrc.h"
  20#include "cthardware.h"
  21#include <linux/slab.h>
  22
  23#define SRC_RESOURCE_NUM        256
  24#define SRCIMP_RESOURCE_NUM     256
  25
  26static unsigned int conj_mask;
  27
  28static int src_default_config_memrd(struct src *src);
  29static int src_default_config_memwr(struct src *src);
  30static int src_default_config_arcrw(struct src *src);
  31
  32static int (*src_default_config[3])(struct src *) = {
  33        [MEMRD] = src_default_config_memrd,
  34        [MEMWR] = src_default_config_memwr,
  35        [ARCRW] = src_default_config_arcrw
  36};
  37
  38static int src_set_state(struct src *src, unsigned int state)
  39{
  40        struct hw *hw;
  41
  42        hw = src->rsc.hw;
  43        hw->src_set_state(src->rsc.ctrl_blk, state);
  44
  45        return 0;
  46}
  47
  48static int src_set_bm(struct src *src, unsigned int bm)
  49{
  50        struct hw *hw;
  51
  52        hw = src->rsc.hw;
  53        hw->src_set_bm(src->rsc.ctrl_blk, bm);
  54
  55        return 0;
  56}
  57
  58static int src_set_sf(struct src *src, unsigned int sf)
  59{
  60        struct hw *hw;
  61
  62        hw = src->rsc.hw;
  63        hw->src_set_sf(src->rsc.ctrl_blk, sf);
  64
  65        return 0;
  66}
  67
  68static int src_set_pm(struct src *src, unsigned int pm)
  69{
  70        struct hw *hw;
  71
  72        hw = src->rsc.hw;
  73        hw->src_set_pm(src->rsc.ctrl_blk, pm);
  74
  75        return 0;
  76}
  77
  78static int src_set_rom(struct src *src, unsigned int rom)
  79{
  80        struct hw *hw;
  81
  82        hw = src->rsc.hw;
  83        hw->src_set_rom(src->rsc.ctrl_blk, rom);
  84
  85        return 0;
  86}
  87
  88static int src_set_vo(struct src *src, unsigned int vo)
  89{
  90        struct hw *hw;
  91
  92        hw = src->rsc.hw;
  93        hw->src_set_vo(src->rsc.ctrl_blk, vo);
  94
  95        return 0;
  96}
  97
  98static int src_set_st(struct src *src, unsigned int st)
  99{
 100        struct hw *hw;
 101
 102        hw = src->rsc.hw;
 103        hw->src_set_st(src->rsc.ctrl_blk, st);
 104
 105        return 0;
 106}
 107
 108static int src_set_bp(struct src *src, unsigned int bp)
 109{
 110        struct hw *hw;
 111
 112        hw = src->rsc.hw;
 113        hw->src_set_bp(src->rsc.ctrl_blk, bp);
 114
 115        return 0;
 116}
 117
 118static int src_set_cisz(struct src *src, unsigned int cisz)
 119{
 120        struct hw *hw;
 121
 122        hw = src->rsc.hw;
 123        hw->src_set_cisz(src->rsc.ctrl_blk, cisz);
 124
 125        return 0;
 126}
 127
 128static int src_set_ca(struct src *src, unsigned int ca)
 129{
 130        struct hw *hw;
 131
 132        hw = src->rsc.hw;
 133        hw->src_set_ca(src->rsc.ctrl_blk, ca);
 134
 135        return 0;
 136}
 137
 138static int src_set_sa(struct src *src, unsigned int sa)
 139{
 140        struct hw *hw;
 141
 142        hw = src->rsc.hw;
 143        hw->src_set_sa(src->rsc.ctrl_blk, sa);
 144
 145        return 0;
 146}
 147
 148static int src_set_la(struct src *src, unsigned int la)
 149{
 150        struct hw *hw;
 151
 152        hw = src->rsc.hw;
 153        hw->src_set_la(src->rsc.ctrl_blk, la);
 154
 155        return 0;
 156}
 157
 158static int src_set_pitch(struct src *src, unsigned int pitch)
 159{
 160        struct hw *hw;
 161
 162        hw = src->rsc.hw;
 163        hw->src_set_pitch(src->rsc.ctrl_blk, pitch);
 164
 165        return 0;
 166}
 167
 168static int src_set_clear_zbufs(struct src *src)
 169{
 170        struct hw *hw;
 171
 172        hw = src->rsc.hw;
 173        hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
 174
 175        return 0;
 176}
 177
 178static int src_commit_write(struct src *src)
 179{
 180        struct hw *hw;
 181        int i;
 182        unsigned int dirty = 0;
 183
 184        hw = src->rsc.hw;
 185        src->rsc.ops->master(&src->rsc);
 186        if (src->rsc.msr > 1) {
 187                /* Save dirty flags for conjugate resource programming */
 188                dirty = hw->src_get_dirty(src->rsc.ctrl_blk) & conj_mask;
 189        }
 190        hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 191                                                src->rsc.ctrl_blk);
 192
 193        /* Program conjugate parameter mixer resources */
 194        if (MEMWR == src->mode)
 195                return 0;
 196
 197        for (i = 1; i < src->rsc.msr; i++) {
 198                src->rsc.ops->next_conj(&src->rsc);
 199                hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
 200                hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 201                                                        src->rsc.ctrl_blk);
 202        }
 203        src->rsc.ops->master(&src->rsc);
 204
 205        return 0;
 206}
 207
 208static int src_get_ca(struct src *src)
 209{
 210        struct hw *hw;
 211
 212        hw = src->rsc.hw;
 213        return hw->src_get_ca(hw, src->rsc.ops->index(&src->rsc),
 214                                                src->rsc.ctrl_blk);
 215}
 216
 217static int src_init(struct src *src)
 218{
 219        src_default_config[src->mode](src);
 220
 221        return 0;
 222}
 223
 224static struct src *src_next_interleave(struct src *src)
 225{
 226        return src->intlv;
 227}
 228
 229static int src_default_config_memrd(struct src *src)
 230{
 231        struct hw *hw = src->rsc.hw;
 232        unsigned int rsr, msr;
 233
 234        hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
 235        hw->src_set_bm(src->rsc.ctrl_blk, 1);
 236        for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
 237                rsr++;
 238
 239        hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
 240        hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
 241        hw->src_set_wr(src->rsc.ctrl_blk, 0);
 242        hw->src_set_pm(src->rsc.ctrl_blk, 0);
 243        hw->src_set_rom(src->rsc.ctrl_blk, 0);
 244        hw->src_set_vo(src->rsc.ctrl_blk, 0);
 245        hw->src_set_st(src->rsc.ctrl_blk, 0);
 246        hw->src_set_ilsz(src->rsc.ctrl_blk, src->multi - 1);
 247        hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
 248        hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
 249        hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
 250        hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
 251        hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
 252        hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
 253
 254        src->rsc.ops->master(&src->rsc);
 255        hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 256                                                src->rsc.ctrl_blk);
 257
 258        for (msr = 1; msr < src->rsc.msr; msr++) {
 259                src->rsc.ops->next_conj(&src->rsc);
 260                hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
 261                hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 262                                                        src->rsc.ctrl_blk);
 263        }
 264        src->rsc.ops->master(&src->rsc);
 265
 266        return 0;
 267}
 268
 269static int src_default_config_memwr(struct src *src)
 270{
 271        struct hw *hw = src->rsc.hw;
 272
 273        hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
 274        hw->src_set_bm(src->rsc.ctrl_blk, 1);
 275        hw->src_set_rsr(src->rsc.ctrl_blk, 0);
 276        hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
 277        hw->src_set_wr(src->rsc.ctrl_blk, 1);
 278        hw->src_set_pm(src->rsc.ctrl_blk, 0);
 279        hw->src_set_rom(src->rsc.ctrl_blk, 0);
 280        hw->src_set_vo(src->rsc.ctrl_blk, 0);
 281        hw->src_set_st(src->rsc.ctrl_blk, 0);
 282        hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
 283        hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
 284        hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
 285        hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
 286        hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
 287        hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
 288        hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
 289
 290        src->rsc.ops->master(&src->rsc);
 291        hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 292                                                src->rsc.ctrl_blk);
 293
 294        return 0;
 295}
 296
 297static int src_default_config_arcrw(struct src *src)
 298{
 299        struct hw *hw = src->rsc.hw;
 300        unsigned int rsr, msr;
 301        unsigned int dirty;
 302
 303        hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
 304        hw->src_set_bm(src->rsc.ctrl_blk, 0);
 305        for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
 306                rsr++;
 307
 308        hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
 309        hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_F32);
 310        hw->src_set_wr(src->rsc.ctrl_blk, 0);
 311        hw->src_set_pm(src->rsc.ctrl_blk, 0);
 312        hw->src_set_rom(src->rsc.ctrl_blk, 0);
 313        hw->src_set_vo(src->rsc.ctrl_blk, 0);
 314        hw->src_set_st(src->rsc.ctrl_blk, 0);
 315        hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
 316        hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
 317        hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
 318        /*hw->src_set_sa(src->rsc.ctrl_blk, 0x100);*/
 319        hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
 320        /*hw->src_set_la(src->rsc.ctrl_blk, 0x03ffffe0);*/
 321        hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
 322        hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
 323        hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
 324
 325        dirty = hw->src_get_dirty(src->rsc.ctrl_blk);
 326        src->rsc.ops->master(&src->rsc);
 327        for (msr = 0; msr < src->rsc.msr; msr++) {
 328                hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
 329                hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
 330                                                        src->rsc.ctrl_blk);
 331                src->rsc.ops->next_conj(&src->rsc);
 332        }
 333        src->rsc.ops->master(&src->rsc);
 334
 335        return 0;
 336}
 337
 338static const struct src_rsc_ops src_rsc_ops = {
 339        .set_state              = src_set_state,
 340        .set_bm                 = src_set_bm,
 341        .set_sf                 = src_set_sf,
 342        .set_pm                 = src_set_pm,
 343        .set_rom                = src_set_rom,
 344        .set_vo                 = src_set_vo,
 345        .set_st                 = src_set_st,
 346        .set_bp                 = src_set_bp,
 347        .set_cisz               = src_set_cisz,
 348        .set_ca                 = src_set_ca,
 349        .set_sa                 = src_set_sa,
 350        .set_la                 = src_set_la,
 351        .set_pitch              = src_set_pitch,
 352        .set_clr_zbufs          = src_set_clear_zbufs,
 353        .commit_write           = src_commit_write,
 354        .get_ca                 = src_get_ca,
 355        .init                   = src_init,
 356        .next_interleave        = src_next_interleave,
 357};
 358
 359static int
 360src_rsc_init(struct src *src, u32 idx,
 361             const struct src_desc *desc, struct src_mgr *mgr)
 362{
 363        int err;
 364        int i, n;
 365        struct src *p;
 366
 367        n = (MEMRD == desc->mode) ? desc->multi : 1;
 368        for (i = 0, p = src; i < n; i++, p++) {
 369                err = rsc_init(&p->rsc, idx + i, SRC, desc->msr, mgr->mgr.hw);
 370                if (err)
 371                        goto error1;
 372
 373                /* Initialize src specific rsc operations */
 374                p->ops = &src_rsc_ops;
 375                p->multi = (0 == i) ? desc->multi : 1;
 376                p->mode = desc->mode;
 377                src_default_config[desc->mode](p);
 378                mgr->src_enable(mgr, p);
 379                p->intlv = p + 1;
 380        }
 381        (--p)->intlv = NULL;    /* Set @intlv of the last SRC to NULL */
 382
 383        mgr->commit_write(mgr);
 384
 385        return 0;
 386
 387error1:
 388        for (i--, p--; i >= 0; i--, p--) {
 389                mgr->src_disable(mgr, p);
 390                rsc_uninit(&p->rsc);
 391        }
 392        mgr->commit_write(mgr);
 393        return err;
 394}
 395
 396static int src_rsc_uninit(struct src *src, struct src_mgr *mgr)
 397{
 398        int i, n;
 399        struct src *p;
 400
 401        n = (MEMRD == src->mode) ? src->multi : 1;
 402        for (i = 0, p = src; i < n; i++, p++) {
 403                mgr->src_disable(mgr, p);
 404                rsc_uninit(&p->rsc);
 405                p->multi = 0;
 406                p->ops = NULL;
 407                p->mode = NUM_SRCMODES;
 408                p->intlv = NULL;
 409        }
 410        mgr->commit_write(mgr);
 411
 412        return 0;
 413}
 414
 415static int
 416get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
 417{
 418        unsigned int idx = SRC_RESOURCE_NUM;
 419        int err;
 420        struct src *src;
 421        unsigned long flags;
 422
 423        *rsrc = NULL;
 424
 425        /* Check whether there are sufficient src resources to meet request. */
 426        spin_lock_irqsave(&mgr->mgr_lock, flags);
 427        if (MEMRD == desc->mode)
 428                err = mgr_get_resource(&mgr->mgr, desc->multi, &idx);
 429        else
 430                err = mgr_get_resource(&mgr->mgr, 1, &idx);
 431
 432        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 433        if (err) {
 434                dev_err(mgr->card->dev,
 435                        "Can't meet SRC resource request!\n");
 436                return err;
 437        }
 438
 439        /* Allocate mem for master src resource */
 440        if (MEMRD == desc->mode)
 441                src = kcalloc(desc->multi, sizeof(*src), GFP_KERNEL);
 442        else
 443                src = kzalloc(sizeof(*src), GFP_KERNEL);
 444
 445        if (!src) {
 446                err = -ENOMEM;
 447                goto error1;
 448        }
 449
 450        err = src_rsc_init(src, idx, desc, mgr);
 451        if (err)
 452                goto error2;
 453
 454        *rsrc = src;
 455
 456        return 0;
 457
 458error2:
 459        kfree(src);
 460error1:
 461        spin_lock_irqsave(&mgr->mgr_lock, flags);
 462        if (MEMRD == desc->mode)
 463                mgr_put_resource(&mgr->mgr, desc->multi, idx);
 464        else
 465                mgr_put_resource(&mgr->mgr, 1, idx);
 466
 467        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 468        return err;
 469}
 470
 471static int put_src_rsc(struct src_mgr *mgr, struct src *src)
 472{
 473        unsigned long flags;
 474
 475        spin_lock_irqsave(&mgr->mgr_lock, flags);
 476        src->rsc.ops->master(&src->rsc);
 477        if (MEMRD == src->mode)
 478                mgr_put_resource(&mgr->mgr, src->multi,
 479                                 src->rsc.ops->index(&src->rsc));
 480        else
 481                mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc));
 482
 483        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 484        src_rsc_uninit(src, mgr);
 485        kfree(src);
 486
 487        return 0;
 488}
 489
 490static int src_enable_s(struct src_mgr *mgr, struct src *src)
 491{
 492        struct hw *hw = mgr->mgr.hw;
 493        int i;
 494
 495        src->rsc.ops->master(&src->rsc);
 496        for (i = 0; i < src->rsc.msr; i++) {
 497                hw->src_mgr_enbs_src(mgr->mgr.ctrl_blk,
 498                                     src->rsc.ops->index(&src->rsc));
 499                src->rsc.ops->next_conj(&src->rsc);
 500        }
 501        src->rsc.ops->master(&src->rsc);
 502
 503        return 0;
 504}
 505
 506static int src_enable(struct src_mgr *mgr, struct src *src)
 507{
 508        struct hw *hw = mgr->mgr.hw;
 509        int i;
 510
 511        src->rsc.ops->master(&src->rsc);
 512        for (i = 0; i < src->rsc.msr; i++) {
 513                hw->src_mgr_enb_src(mgr->mgr.ctrl_blk,
 514                                    src->rsc.ops->index(&src->rsc));
 515                src->rsc.ops->next_conj(&src->rsc);
 516        }
 517        src->rsc.ops->master(&src->rsc);
 518
 519        return 0;
 520}
 521
 522static int src_disable(struct src_mgr *mgr, struct src *src)
 523{
 524        struct hw *hw = mgr->mgr.hw;
 525        int i;
 526
 527        src->rsc.ops->master(&src->rsc);
 528        for (i = 0; i < src->rsc.msr; i++) {
 529                hw->src_mgr_dsb_src(mgr->mgr.ctrl_blk,
 530                                    src->rsc.ops->index(&src->rsc));
 531                src->rsc.ops->next_conj(&src->rsc);
 532        }
 533        src->rsc.ops->master(&src->rsc);
 534
 535        return 0;
 536}
 537
 538static int src_mgr_commit_write(struct src_mgr *mgr)
 539{
 540        struct hw *hw = mgr->mgr.hw;
 541
 542        hw->src_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
 543
 544        return 0;
 545}
 546
 547int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
 548{
 549        int err, i;
 550        struct src_mgr *src_mgr;
 551
 552        *rsrc_mgr = NULL;
 553        src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL);
 554        if (!src_mgr)
 555                return -ENOMEM;
 556
 557        err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw);
 558        if (err)
 559                goto error1;
 560
 561        spin_lock_init(&src_mgr->mgr_lock);
 562        conj_mask = hw->src_dirty_conj_mask();
 563
 564        src_mgr->get_src = get_src_rsc;
 565        src_mgr->put_src = put_src_rsc;
 566        src_mgr->src_enable_s = src_enable_s;
 567        src_mgr->src_enable = src_enable;
 568        src_mgr->src_disable = src_disable;
 569        src_mgr->commit_write = src_mgr_commit_write;
 570        src_mgr->card = hw->card;
 571
 572        /* Disable all SRC resources. */
 573        for (i = 0; i < 256; i++)
 574                hw->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
 575
 576        hw->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
 577
 578        *rsrc_mgr = src_mgr;
 579
 580        return 0;
 581
 582error1:
 583        kfree(src_mgr);
 584        return err;
 585}
 586
 587int src_mgr_destroy(struct src_mgr *src_mgr)
 588{
 589        rsc_mgr_uninit(&src_mgr->mgr);
 590        kfree(src_mgr);
 591
 592        return 0;
 593}
 594
 595/* SRCIMP resource manager operations */
 596
 597static int srcimp_master(struct rsc *rsc)
 598{
 599        rsc->conj = 0;
 600        return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
 601}
 602
 603static int srcimp_next_conj(struct rsc *rsc)
 604{
 605        rsc->conj++;
 606        return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
 607}
 608
 609static int srcimp_index(const struct rsc *rsc)
 610{
 611        return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
 612}
 613
 614static const struct rsc_ops srcimp_basic_rsc_ops = {
 615        .master         = srcimp_master,
 616        .next_conj      = srcimp_next_conj,
 617        .index          = srcimp_index,
 618        .output_slot    = NULL,
 619};
 620
 621static int srcimp_map(struct srcimp *srcimp, struct src *src, struct rsc *input)
 622{
 623        struct imapper *entry;
 624        int i;
 625
 626        srcimp->rsc.ops->master(&srcimp->rsc);
 627        src->rsc.ops->master(&src->rsc);
 628        input->ops->master(input);
 629
 630        /* Program master and conjugate resources */
 631        for (i = 0; i < srcimp->rsc.msr; i++) {
 632                entry = &srcimp->imappers[i];
 633                entry->slot = input->ops->output_slot(input);
 634                entry->user = src->rsc.ops->index(&src->rsc);
 635                entry->addr = srcimp->rsc.ops->index(&srcimp->rsc);
 636                srcimp->mgr->imap_add(srcimp->mgr, entry);
 637                srcimp->mapped |= (0x1 << i);
 638
 639                srcimp->rsc.ops->next_conj(&srcimp->rsc);
 640                input->ops->next_conj(input);
 641        }
 642
 643        srcimp->rsc.ops->master(&srcimp->rsc);
 644        input->ops->master(input);
 645
 646        return 0;
 647}
 648
 649static int srcimp_unmap(struct srcimp *srcimp)
 650{
 651        int i;
 652
 653        /* Program master and conjugate resources */
 654        for (i = 0; i < srcimp->rsc.msr; i++) {
 655                if (srcimp->mapped & (0x1 << i)) {
 656                        srcimp->mgr->imap_delete(srcimp->mgr,
 657                                                 &srcimp->imappers[i]);
 658                        srcimp->mapped &= ~(0x1 << i);
 659                }
 660        }
 661
 662        return 0;
 663}
 664
 665static const struct srcimp_rsc_ops srcimp_ops = {
 666        .map = srcimp_map,
 667        .unmap = srcimp_unmap
 668};
 669
 670static int srcimp_rsc_init(struct srcimp *srcimp,
 671                           const struct srcimp_desc *desc,
 672                           struct srcimp_mgr *mgr)
 673{
 674        int err;
 675
 676        err = rsc_init(&srcimp->rsc, srcimp->idx[0],
 677                       SRCIMP, desc->msr, mgr->mgr.hw);
 678        if (err)
 679                return err;
 680
 681        /* Reserve memory for imapper nodes */
 682        srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr,
 683                                   GFP_KERNEL);
 684        if (!srcimp->imappers) {
 685                err = -ENOMEM;
 686                goto error1;
 687        }
 688
 689        /* Set srcimp specific operations */
 690        srcimp->rsc.ops = &srcimp_basic_rsc_ops;
 691        srcimp->ops = &srcimp_ops;
 692        srcimp->mgr = mgr;
 693
 694        srcimp->rsc.ops->master(&srcimp->rsc);
 695
 696        return 0;
 697
 698error1:
 699        rsc_uninit(&srcimp->rsc);
 700        return err;
 701}
 702
 703static int srcimp_rsc_uninit(struct srcimp *srcimp)
 704{
 705        if (NULL != srcimp->imappers) {
 706                kfree(srcimp->imappers);
 707                srcimp->imappers = NULL;
 708        }
 709        srcimp->ops = NULL;
 710        srcimp->mgr = NULL;
 711        rsc_uninit(&srcimp->rsc);
 712
 713        return 0;
 714}
 715
 716static int get_srcimp_rsc(struct srcimp_mgr *mgr,
 717                          const struct srcimp_desc *desc,
 718                          struct srcimp **rsrcimp)
 719{
 720        int err, i;
 721        unsigned int idx;
 722        struct srcimp *srcimp;
 723        unsigned long flags;
 724
 725        *rsrcimp = NULL;
 726
 727        /* Allocate mem for SRCIMP resource */
 728        srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
 729        if (!srcimp)
 730                return -ENOMEM;
 731
 732        /* Check whether there are sufficient SRCIMP resources. */
 733        err = 0;
 734        spin_lock_irqsave(&mgr->mgr_lock, flags);
 735        for (i = 0; i < desc->msr; i++) {
 736                err = mgr_get_resource(&mgr->mgr, 1, &idx);
 737                if (err)
 738                        break;
 739
 740                srcimp->idx[i] = idx;
 741        }
 742        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 743        if (err) {
 744                dev_err(mgr->card->dev,
 745                        "Can't meet SRCIMP resource request!\n");
 746                goto error1;
 747        }
 748
 749        err = srcimp_rsc_init(srcimp, desc, mgr);
 750        if (err)
 751                goto error1;
 752
 753        *rsrcimp = srcimp;
 754
 755        return 0;
 756
 757error1:
 758        spin_lock_irqsave(&mgr->mgr_lock, flags);
 759        for (i--; i >= 0; i--)
 760                mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
 761
 762        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 763        kfree(srcimp);
 764        return err;
 765}
 766
 767static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp)
 768{
 769        unsigned long flags;
 770        int i;
 771
 772        spin_lock_irqsave(&mgr->mgr_lock, flags);
 773        for (i = 0; i < srcimp->rsc.msr; i++)
 774                mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
 775
 776        spin_unlock_irqrestore(&mgr->mgr_lock, flags);
 777        srcimp_rsc_uninit(srcimp);
 778        kfree(srcimp);
 779
 780        return 0;
 781}
 782
 783static int srcimp_map_op(void *data, struct imapper *entry)
 784{
 785        struct rsc_mgr *mgr = &((struct srcimp_mgr *)data)->mgr;
 786        struct hw *hw = mgr->hw;
 787
 788        hw->srcimp_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
 789        hw->srcimp_mgr_set_imapuser(mgr->ctrl_blk, entry->user);
 790        hw->srcimp_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
 791        hw->srcimp_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
 792        hw->srcimp_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
 793
 794        return 0;
 795}
 796
 797static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry)
 798{
 799        unsigned long flags;
 800        int err;
 801
 802        spin_lock_irqsave(&mgr->imap_lock, flags);
 803        if ((0 == entry->addr) && (mgr->init_imap_added)) {
 804                input_mapper_delete(&mgr->imappers,
 805                                    mgr->init_imap, srcimp_map_op, mgr);
 806                mgr->init_imap_added = 0;
 807        }
 808        err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr);
 809        spin_unlock_irqrestore(&mgr->imap_lock, flags);
 810
 811        return err;
 812}
 813
 814static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
 815{
 816        unsigned long flags;
 817        int err;
 818
 819        spin_lock_irqsave(&mgr->imap_lock, flags);
 820        err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr);
 821        if (list_empty(&mgr->imappers)) {
 822                input_mapper_add(&mgr->imappers, mgr->init_imap,
 823                                 srcimp_map_op, mgr);
 824                mgr->init_imap_added = 1;
 825        }
 826        spin_unlock_irqrestore(&mgr->imap_lock, flags);
 827
 828        return err;
 829}
 830
 831int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
 832{
 833        int err;
 834        struct srcimp_mgr *srcimp_mgr;
 835        struct imapper *entry;
 836
 837        *rsrcimp_mgr = NULL;
 838        srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL);
 839        if (!srcimp_mgr)
 840                return -ENOMEM;
 841
 842        err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw);
 843        if (err)
 844                goto error1;
 845
 846        spin_lock_init(&srcimp_mgr->mgr_lock);
 847        spin_lock_init(&srcimp_mgr->imap_lock);
 848        INIT_LIST_HEAD(&srcimp_mgr->imappers);
 849        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 850        if (!entry) {
 851                err = -ENOMEM;
 852                goto error2;
 853        }
 854        entry->slot = entry->addr = entry->next = entry->user = 0;
 855        list_add(&entry->list, &srcimp_mgr->imappers);
 856        srcimp_mgr->init_imap = entry;
 857        srcimp_mgr->init_imap_added = 1;
 858
 859        srcimp_mgr->get_srcimp = get_srcimp_rsc;
 860        srcimp_mgr->put_srcimp = put_srcimp_rsc;
 861        srcimp_mgr->imap_add = srcimp_imap_add;
 862        srcimp_mgr->imap_delete = srcimp_imap_delete;
 863        srcimp_mgr->card = hw->card;
 864
 865        *rsrcimp_mgr = srcimp_mgr;
 866
 867        return 0;
 868
 869error2:
 870        rsc_mgr_uninit(&srcimp_mgr->mgr);
 871error1:
 872        kfree(srcimp_mgr);
 873        return err;
 874}
 875
 876int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
 877{
 878        unsigned long flags;
 879
 880        /* free src input mapper list */
 881        spin_lock_irqsave(&srcimp_mgr->imap_lock, flags);
 882        free_input_mapper_list(&srcimp_mgr->imappers);
 883        spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags);
 884
 885        rsc_mgr_uninit(&srcimp_mgr->mgr);
 886        kfree(srcimp_mgr);
 887
 888        return 0;
 889}
 890