Changeset a333b7f in mainline for uspace/drv/audio/hdaudio/hdactl.c


Ignore:
Timestamp:
2014-08-25T09:28:39Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
932e2f5
Parents:
1412a184
Message:

Interrupt handling - RIRB interrupts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/audio/hdaudio/hdactl.c

    r1412a184 ra333b7f  
    3939#include <ddi.h>
    4040#include <errno.h>
     41#include <fibril_synch.h>
    4142#include <macros.h>
    4243#include <stdint.h>
     
    222223
    223224        /* Set RINTCNT - Qemu won't read from CORB if this is zero */
    224         hda_reg16_write(&hda->regs->rintcnt, 128);
     225        hda_reg16_write(&hda->regs->rintcnt, hda->ctl->rirb_entries / 2);
    225226
    226227        hda->ctl->rirb_rp = 0;
    227228
    228         /* Start RIRB */
     229        /* Start RIRB and enable RIRB interrupt */
    229230        ctl = hda_reg8_read(&hda->regs->rirbctl);
    230231        ddf_msg(LVL_NOTE, "RIRBctl (0x%x) = 0x%x",
    231232            (unsigned)((void *)&hda->regs->rirbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, rirbctl_run));
    232         hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run));
     233        hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run) |
     234            BIT_V(uint8_t, rirbctl_int));
    233235
    234236        ddf_msg(LVL_NOTE, "RIRB initialized");
     
    327329}
    328330
    329 static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data, size_t count)
     331static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data)
    330332{
    331333        size_t wp;
    332334        hda_rirb_entry_t resp;
    333335        hda_rirb_entry_t *rirb;
     336
     337        rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt;
     338
     339        wp = hda_get_rirbwp(hda);
     340        ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%d", wp);
     341        if (hda->ctl->rirb_rp == wp)
     342                return ENOENT;
     343
     344        ++hda->ctl->rirb_rp;
     345        resp = rirb[hda->ctl->rirb_rp];
     346
     347        ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x",
     348            resp.resp, resp.respex);
     349        *data = resp;
     350        return EOK;
     351}
     352
     353static int hda_solrb_read(hda_t *hda, hda_rirb_entry_t *data, size_t count)
     354{
     355        hda_rirb_entry_t resp;
    334356        int wcnt;
    335357
    336         rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt;
     358        wcnt = 10;
     359
     360        fibril_mutex_lock(&hda->ctl->solrb_lock);
    337361
    338362        while (count > 0) {
    339                 wp = hda_get_rirbwp(hda);
    340                 ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%d", wp);
    341                 while (count > 0 && hda->ctl->rirb_rp != wp) {
    342                         ++hda->ctl->rirb_rp;
    343                         resp = rirb[hda->ctl->rirb_rp];
    344 
    345                         ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x",
     363                while (count > 0 && hda->ctl->solrb_rp != hda->ctl->solrb_wp) {
     364                        ++hda->ctl->solrb_rp;
     365                        resp = hda->ctl->solrb[hda->ctl->solrb_rp];
     366
     367                        ddf_msg(LVL_DEBUG2, "solrb RESPONSE resp=0x%x respex=0x%x",
    346368                            resp.resp, resp.respex);
    347369                        if ((resp.respex & BIT_V(uint32_t, respex_unsol)) == 0) {
     
    353375
    354376                if (count > 0) {
    355                         wcnt = rirb_wait_max;
    356                         while (wcnt > 0 && hda_get_rirbwp(hda) == hda->ctl->rirb_rp) {
     377                        while (wcnt > 0 && hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
     378                                fibril_mutex_unlock(&hda->ctl->solrb_lock);
    357379                                async_usleep(100);
     380                                fibril_mutex_lock(&hda->ctl->solrb_lock);
    358381                                --wcnt;
    359382                        }
    360383
    361                         if (hda_get_rirbwp(hda) == hda->ctl->rirb_rp)
     384                        if (hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
     385                                ddf_msg(LVL_NOTE, "hda_solrb_read() time out");
     386                                fibril_mutex_unlock(&hda->ctl->solrb_lock);
    362387                                return ETIMEOUT;
    363                 }
    364         }
    365 
     388                        }
     389                }
     390        }
     391
     392        fibril_mutex_unlock(&hda->ctl->solrb_lock);
    366393        return EOK;
    367394}
     
    371398        hda_ctl_t *ctl;
    372399        uint32_t gctl;
     400        uint32_t intctl;
    373401        int cnt;
    374402        int rc;
     
    378406                return NULL;
    379407
     408        fibril_mutex_initialize(&ctl->solrb_lock);
     409        fibril_condvar_initialize(&ctl->solrb_cv);
     410
    380411        hda->ctl = ctl;
     412        ctl->hda = hda;
    381413
    382414        uint8_t vmaj = hda_reg8_read(&hda->regs->vmaj);
     
    391423
    392424        ddf_msg(LVL_NOTE, "reg 0x%zx STATESTS = 0x%x",
    393             (void *)&hda->regs->statests - (void *)hda->regs, hda_reg16_read(&hda->regs->statests));
     425            (void *)&hda->regs->statests - (void *)hda->regs,
     426                hda_reg16_read(&hda->regs->statests));
     427        /**
     428          * Clear STATESTS bits so they don't generate an interrupt later
     429          * when we enable interrupts.
     430          */
     431        hda_reg16_write(&hda->regs->statests, 0x7f);
     432
     433        ddf_msg(LVL_NOTE, "after clearing reg 0x%zx STATESTS = 0x%x",
     434            (void *)&hda->regs->statests - (void *)hda->regs,
     435                hda_reg16_read(&hda->regs->statests));
    394436
    395437        gctl = hda_reg32_read(&hda->regs->gctl);
     
    437479            hda_reg16_read(&hda->regs->statests));
    438480
     481        async_usleep(1000*1000);
     482
     483        /* Enable interrupts */
     484        intctl = hda_reg32_read(&hda->regs->intctl);
     485        ddf_msg(LVL_NOTE, "intctl (0x%x) := 0x%x",
     486            (unsigned)((void *)&hda->regs->intctl - (void *)hda->regs),
     487            intctl | BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie));
     488        hda_reg32_write(&hda->regs->intctl, intctl |
     489            BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie));
     490
     491        async_usleep(1000*1000);
     492
    439493        rc = hda_corb_init(hda);
    440494        if (rc != EOK)
    441495                goto error;
    442496
     497
     498        async_usleep(1000*1000);
     499
    443500        rc = hda_rirb_init(hda);
    444501        if (rc != EOK)
    445502                goto error;
    446503
     504        async_usleep(1000*1000);
     505
     506        ddf_msg(LVL_NOTE, "call hda_codec_init()");
    447507        hda->ctl->codec = hda_codec_init(hda, 0);
    448         if (hda->ctl->codec == NULL)
    449                 goto error;
     508        if (hda->ctl->codec == NULL) {
     509                ddf_msg(LVL_NOTE, "hda_codec_init() failed");
     510                goto error;
     511        }
    450512
    451513        return ctl;
     
    466528
    467529        if (resp != NULL) {
    468                 rc = hda_rirb_read(hda, &rentry, 1);
     530                rc = hda_solrb_read(hda, &rentry, 1);
    469531                if (rc != EOK)
    470532                        return rc;
     
    483545}
    484546
     547void hda_ctl_interrupt(hda_ctl_t *ctl)
     548{
     549        hda_rirb_entry_t resp;
     550        int rc;
     551
     552        while (true) {
     553                rc = hda_rirb_read(ctl->hda, &resp);
     554                if (rc != EOK) {
     555//                      ddf_msg(LVL_NOTE, "nothing in rirb");
     556                        break;
     557                }
     558
     559                ddf_msg(LVL_NOTE, "writing to solrb");
     560                fibril_mutex_lock(&ctl->solrb_lock);
     561                ctl->solrb_wp = (ctl->solrb_wp + 1) % softrb_entries;
     562                ctl->solrb[ctl->solrb_wp] = resp;
     563                fibril_mutex_unlock(&ctl->solrb_lock);
     564                fibril_condvar_broadcast(&ctl->solrb_cv);
     565        }
     566}
     567
    485568/** @}
    486569 */
Note: See TracChangeset for help on using the changeset viewer.