Changeset 8d070710 in mainline


Ignore:
Timestamp:
2014-08-14T11:12:19Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d2d5329
Parents:
7978d1e7
Message:

Say hello to root node.

Location:
uspace/drv/audio/hdaudio
Files:
4 edited

Legend:

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

    r7978d1e7 r8d070710  
    4848enum {
    4949        ctrl_init_wait_max = 10,
    50         codec_enum_wait_us = 512
     50        codec_enum_wait_us = 512,
     51        corb_wait_max = 10
    5152};
    5253
     
    104105        ddf_msg(LVL_NOTE, "hda_corb_init()");
    105106
    106         /* Stop CORB if not stopped. */
     107        /* Stop CORB if not stopped */
    107108        ctl = hda_reg8_read(&hda->regs->corbctl);
    108109        if ((ctl & BIT_V(uint8_t, corbctl_run)) != 0) {
     
    148149        hda_reg32_write(&hda->regs->corbubase, UPPER32(hda->ctl->corb_phys));
    149150
    150         ddf_msg(LVL_NOTE, "Rset CORB Read/Write pointers");
     151        ddf_msg(LVL_NOTE, "Reset CORB Read/Write pointers");
    151152
    152153        /* Reset CORB Read Pointer */
     
    155156        /* Reset CORB Write Poitner */
    156157        hda_reg16_write(&hda->regs->corbwp, 0);
     158
     159        /* Start CORB */
     160        ctl = hda_reg8_read(&hda->regs->corbctl);
     161        ddf_msg(LVL_NOTE, "CORBctl (0x%x) = 0x%x",
     162            (unsigned)((void *)&hda->regs->corbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, corbctl_run));
     163        hda_reg8_write(&hda->regs->corbctl, ctl | BIT_V(uint8_t, corbctl_run));
    157164
    158165        ddf_msg(LVL_NOTE, "CORB initialized");
     
    174181        ddf_msg(LVL_NOTE, "hda_rirb_init()");
    175182
    176         /* Stop RIRB if not stopped. */
     183        /* Stop RIRB if not stopped */
    177184        ctl = hda_reg8_read(&hda->regs->rirbctl);
    178185        if ((ctl & BIT_V(uint8_t, rirbctl_run)) != 0) {
     
    218225        hda_reg32_write(&hda->regs->rirbubase, UPPER32(hda->ctl->rirb_phys));
    219226
    220         ddf_msg(LVL_NOTE, "Rset RIRB Write pointer");
     227        ddf_msg(LVL_NOTE, "Reset RIRB Write pointer");
    221228
    222229        /* Reset RIRB Write Pointer */
    223230        hda_reg16_write(&hda->regs->rirbwp, BIT_V(uint16_t, rirbwp_rst));
     231
     232        /* Set RINTCNT - Qemu won't read from CORB if this is zero */
     233        hda_reg16_write(&hda->regs->rintcnt, 2);
     234
     235        hda->ctl->rirb_rp = 0;
     236
     237        /* Start RIRB */
     238        ctl = hda_reg8_read(&hda->regs->rirbctl);
     239        ddf_msg(LVL_NOTE, "RIRBctl (0x%x) = 0x%x",
     240            (unsigned)((void *)&hda->regs->rirbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, rirbctl_run));
     241        hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run));
    224242
    225243        ddf_msg(LVL_NOTE, "RIRB initialized");
     
    229247}
    230248
     249static size_t hda_get_corbrp(hda_t *hda)
     250{
     251        uint16_t corbrp;
     252
     253        corbrp = hda_reg16_read(&hda->regs->corbrp);
     254        return BIT_RANGE_EXTRACT(uint16_t, corbrp_rp_h, corbrp_rp_l, corbrp);
     255}
     256
     257static size_t hda_get_corbwp(hda_t *hda)
     258{
     259        uint16_t corbwp;
     260
     261        corbwp = hda_reg16_read(&hda->regs->corbwp);
     262        return BIT_RANGE_EXTRACT(uint16_t, corbwp_wp_h, corbwp_wp_l, corbwp);
     263}
     264
     265static void hda_set_corbwp(hda_t *hda, size_t wp)
     266{
     267        ddf_msg(LVL_NOTE, "Set CORBWP = %d", wp);
     268        hda_reg16_write(&hda->regs->corbwp, wp);
     269}
     270
     271static size_t hda_get_rirbwp(hda_t *hda)
     272{
     273        uint16_t rirbwp;
     274
     275        rirbwp = hda_reg16_read(&hda->regs->rirbwp);
     276        return BIT_RANGE_EXTRACT(uint16_t, rirbwp_wp_h, rirbwp_wp_l, rirbwp);
     277}
     278
     279/** Determine number of free entries in CORB */
     280static size_t hda_corb_avail(hda_t *hda)
     281{
     282        int rp, wp;
     283        int avail;
     284
     285        rp = hda_get_corbrp(hda);
     286        wp = hda_get_corbwp(hda);
     287
     288        avail = rp - wp - 1;
     289        while (avail < 0)
     290                avail += hda->ctl->corb_entries;
     291
     292        return avail;
     293}
     294
     295/** Write to CORB */
     296static int hda_corb_write(hda_t *hda, uint32_t *data, size_t count)
     297{
     298        size_t avail;
     299        size_t wp;
     300        size_t idx;
     301        size_t now;
     302        size_t i;
     303        uint32_t *corb;
     304        int wcnt;
     305
     306        avail = hda_corb_avail(hda);
     307        wp = hda_get_corbwp(hda);
     308        corb = (uint32_t *)hda->ctl->corb_virt;
     309
     310        idx = 0;
     311        while (idx < count) {
     312                now = min(avail, count - idx);
     313
     314                for (i = 0; i < now; i++) {
     315                        wp = (wp + 1) % hda->ctl->corb_entries;
     316                        corb[wp] = data[idx++];
     317                }
     318
     319                hda_set_corbwp(hda, wp);
     320
     321                if (idx < count) {
     322                        /* We filled up CORB but still data remaining */
     323                        wcnt = corb_wait_max;
     324                        while (hda_corb_avail(hda) < 1 && wcnt > 0) {
     325                                async_usleep(100);
     326                                --wcnt;
     327                        }
     328
     329                        /* If CORB is still full return timeout error */
     330                        if (hda_corb_avail(hda) < 1)
     331                                return ETIMEOUT;
     332                }
     333        }
     334
     335        return EOK;
     336}
     337
     338static void hda_rirb_read(hda_t *hda)
     339{
     340        size_t wp;
     341        hda_rirb_entry_t resp;
     342        hda_rirb_entry_t *rirb;
     343
     344        rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt;
     345
     346        wp = hda_get_rirbwp(hda);
     347        ddf_msg(LVL_NOTE, "hda_rirb_read: wp=%d", wp);
     348        while (hda->ctl->rirb_rp != wp) {
     349                ++hda->ctl->rirb_rp;
     350                resp = rirb[hda->ctl->rirb_rp];
     351
     352                ddf_msg(LVL_NOTE, "RESPONSE resp=0x%x respex=0x%x",
     353                    resp.resp, resp.respex);
     354        }
     355}
     356
     357#include "spec/codec.h"
    231358hda_ctl_t *hda_ctl_init(hda_t *hda)
    232359{
     
    299426                goto error;
    300427
     428        uint32_t verb;
     429        verb = (0 << 28) | (0 << 20) | ((hda_get_param) << 8) | (hda_sub_nc);
     430        rc = hda_corb_write(hda, &verb, 1);
     431        ddf_msg(LVL_NOTE, "hda_corb_write -> %d", rc);
     432        rc = hda_corb_write(hda, &verb, 1);
     433        ddf_msg(LVL_NOTE, "hda_corb_write -> %d", rc);
     434        rc = hda_corb_write(hda, &verb, 1);
     435        ddf_msg(LVL_NOTE, "hda_corb_write -> %d", rc);
     436        rc = hda_corb_write(hda, &verb, 1);
     437        ddf_msg(LVL_NOTE, "hda_corb_write -> %d", rc);
     438
     439        async_usleep(100*1000);
     440        hda_rirb_read(hda);
     441
    301442        return ctl;
    302443error:
  • uspace/drv/audio/hdaudio/hdactl.h

    r7978d1e7 r8d070710  
    4646        void *rirb_virt;
    4747        size_t rirb_entries;
     48        size_t rirb_rp;
    4849} hda_ctl_t;
    4950
  • uspace/drv/audio/hdaudio/spec/codec.h

    r7978d1e7 r8d070710  
    7070        hda_spdif_ctl_set1 = 0x70d,
    7171        /** S/PDIF Converter Control / Set 2 */
    72         hda_spdif_ctl_set1 = 0x70e,
     72        hda_spdif_ctl_set2 = 0x70e,
    7373        /** S/PDIF Converter Control / Set 3 */
    74         hda_spdif_ctl_set1 = 0x73e,
     74        hda_spdif_ctl_set3 = 0x73e,
    7575        /** S/PDIF Converter Control / Set 4 */
    76         hda_spdif_ctl_set1 = 0x73f,
     76        hda_spdif_ctl_set4 = 0x73f,
    7777        /** Power State / Get */
    7878        hda_power_state_get = 0xf05,
     
    9191        /** Enable VRef / Set */
    9292        hda_enable_vref_set = 0x707,
    93         /** Connection Select Control / Get */
    94         hda_conn_sel_get = 0xf08,
    95         /** Connection Select Control / Set */
    96         hda_conn_sel_set = 0x708
     93        /** Unsolicited Response Control / Get */
     94        hda_unsol_resp_get = 0xf08,
     95        /** Unsolicied Response Control / Set */
     96        hda_unsol_resp_set = 0x708
    9797} hda_verb_t;
    9898
  • uspace/drv/audio/hdaudio/spec/regs.h

    r7978d1e7 r8d070710  
    201201
    202202typedef enum {
     203        /** CORB Write Pointer (H) */
     204        corbwp_wp_h = 7,
     205        /** CORB Write Pointer (L) */
     206        corbwp_wp_l = 0
     207} hda_corbwp_bits_t;
     208
     209typedef enum {
    203210        /** Enable CORB DMA Engine */
    204211        corbctl_run = 1,
     
    224231        rirbwp_wp_h = 7,
    225232        /** RIRB Write Pointer (L) */
    226         rirbrp_wp_l = 0
     233        rirbwp_wp_l = 0
    227234} hda_rirbwp_bits_t;
    228235
     
    247254} hda_rirbsize_bits_t;
    248255
     256typedef struct {
     257        /** Response - data received from codec */
     258        uint32_t resp;
     259        /** Response Extended - added by controller */
     260        uint32_t respex;
     261} hda_rirb_entry_t;
     262
     263typedef enum {
     264        /** Unsolicited response */
     265        respex_unsol = 4,
     266        /** Codec Address (H) */
     267        respex_addr_h = 3,
     268        /** Codec Address (L) */
     269        respex_addr_l = 0
     270} hda_respex_bits_t;
     271
    249272#endif
    250273
Note: See TracChangeset for help on using the changeset viewer.