Changeset 1412a184 in mainline


Ignore:
Timestamp:
2014-08-16T15:34:44Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a333b7f
Parents:
65b09c1
Message:

Stream management. Attempt some playback.

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

Legend:

Unmodified
Added
Removed
  • uspace/drv/audio/hdaudio/Makefile

    r65b09c1 r1412a184  
    3636        regif.c \
    3737        hdactl.c \
    38         hdaudio.c
     38        hdaudio.c \
     39        stream.c
    3940
    4041include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/audio/hdaudio/codec.c

    r65b09c1 r1412a184  
    4242#include "hdactl.h"
    4343#include "spec/codec.h"
     44#include "spec/fmt.h"
     45#include "stream.h"
     46
     47static int hda_ccmd(hda_codec_t *codec, int node, uint32_t vid, uint32_t payload,
     48    uint32_t *resp)
     49{
     50        uint32_t verb;
     51
     52        verb = (codec->address << 28) | (node << 20) | (vid << 8) | payload;
     53        return hda_cmd(codec->hda, verb, resp);
     54}
    4455
    4556static int hda_get_parameter(hda_codec_t *codec, int node, hda_param_id_t param,
    4657    uint32_t *resp)
    4758{
    48         uint32_t verb;
    49 
    50         verb = (codec->address << 28) | (node << 20) | ((hda_param_get) << 8) | param;
    51         return hda_cmd(codec->hda, verb, resp);
     59        return hda_ccmd(codec, node, hda_param_get, param, resp);
    5260}
    5361
     
    8795}
    8896
     97/** Get Suppported PCM Size, Rates */
     98static int hda_get_supp_rates(hda_codec_t *codec, int node, uint32_t *rates)
     99{
     100        return hda_get_parameter(codec, node, hda_supp_rates, rates);
     101}
     102
     103/** Get Suppported Stream Formats */
     104static int hda_get_supp_formats(hda_codec_t *codec, int node, uint32_t *fmts)
     105{
     106        return hda_get_parameter(codec, node, hda_supp_formats, fmts);
     107}
     108
     109static int hda_set_converter_fmt(hda_codec_t *codec, int node, uint16_t fmt)
     110{
     111        return hda_ccmd(codec, node, hda_converter_fmt_set, fmt, NULL);
     112}
     113
     114static int hda_set_converter_ctl(hda_codec_t *codec, int node, uint8_t stream,
     115    uint8_t channel)
     116{
     117        uint32_t ctl;
     118
     119        ctl = (stream << cctl_stream_l) | (channel << cctl_channel_l);
     120        return hda_ccmd(codec, node, hda_converter_ctl_set, ctl, NULL);
     121}
     122
    89123/** Get Audio Widget Capabilities */
    90124static int hda_get_aw_caps(hda_codec_t *codec, int node,
     
    107141static int hda_get_cfg_def(hda_codec_t *codec, int node, uint32_t *cfgdef)
    108142{
    109         uint32_t verb;
    110 
    111         verb = (codec->address << 28) | (node << 20) | ((hda_cfg_def_get) << 8) | 0;
    112         return hda_cmd(codec->hda, verb, cfgdef);
     143        return hda_ccmd(codec, node, hda_cfg_def_get, 0, cfgdef);
     144}
     145
     146/** Get Amplifier Gain / Mute  */
     147static int hda_get_amp_gain_mute(hda_codec_t *codec, int node, uint16_t payload,
     148    uint32_t *resp)
     149{
     150        return hda_ccmd(codec, node, hda_amp_gain_mute_get, payload, resp);
     151}
     152
     153static int hda_set_amp_gain_mute(hda_codec_t *codec, int node, uint16_t payload)
     154{
     155        return hda_ccmd(codec, node, hda_amp_gain_mute_set, payload, NULL);
    113156}
    114157
     
    125168        uint32_t awcaps;
    126169        uint32_t cfgdef;
     170        uint32_t rates;
     171        uint32_t formats;
    127172
    128173        codec = calloc(1, sizeof(hda_codec_t));
     
    171216                                    aw, cfgdef);
    172217
     218                        } else if (awtype == awt_audio_output) {
     219                                codec->out_aw = aw;
     220                        }
     221
     222                        if ((awcaps & BIT_V(uint32_t, awc_out_amp_present)) != 0) {
     223                                uint32_t ampcaps;
     224                                uint32_t gmleft, gmright;
     225
     226                                rc = hda_get_parameter(codec, aw,
     227                                    hda_out_amp_caps, &ampcaps);
     228                                if (rc != EOK)
     229                                        goto error;
     230
     231                                rc = hda_get_amp_gain_mute(codec, aw, 0x8000, &gmleft);
     232                                if (rc != EOK)
     233                                        goto error;
     234
     235                                rc = hda_get_amp_gain_mute(codec, aw, 0xc000, &gmright);
     236                                if (rc != EOK)
     237                                        goto error;
     238
     239                                ddf_msg(LVL_NOTE, "out amp caps 0x%x "
     240                                    "gain/mute: L:0x%x R:0x%x",
     241                                    ampcaps, gmleft, gmright);
     242
     243                                rc = hda_set_amp_gain_mute(codec, aw, 0xb04a);
     244                                if (rc != EOK)
     245                                        goto error;
    173246                        }
    174247                }
    175248        }
    176249
     250        rc = hda_get_supp_rates(codec, codec->out_aw, &rates);
     251        if (rc != EOK)
     252                goto error;
     253
     254        rc = hda_get_supp_formats(codec, codec->out_aw, &formats);
     255        if (rc != EOK)
     256                goto error;
     257
     258        ddf_msg(LVL_NOTE, "Output widget %d: rates=0x%x formats=0x%x",
     259            codec->out_aw, rates, formats);
     260
     261        /* XXX Choose appropriate parameters */
     262        uint32_t fmt;
     263        /* 48 kHz, 16-bits, 1 channel */
     264        fmt = fmt_bits_16 << fmt_bits_l;
     265
     266        /* Create stream */
     267        ddf_msg(LVL_NOTE, "Create stream");
     268        hda_stream_t *stream;
     269        stream = hda_stream_create(hda, sdir_output, fmt);
     270        if (stream == NULL)
     271                goto error;
     272
     273        /* Configure converter */
     274
     275        ddf_msg(LVL_NOTE, "Configure converter format");
     276        rc = hda_set_converter_fmt(codec, codec->out_aw, fmt);
     277        if (rc != EOK)
     278                goto error;
     279
     280        ddf_msg(LVL_NOTE, "Configure converter stream, channel");
     281        rc = hda_set_converter_ctl(codec, codec->out_aw, stream->sid, 0);
     282        if (rc != EOK)
     283                goto error;
     284
     285        ddf_msg(LVL_NOTE, "Start stream");
     286        hda_stream_start(stream);
     287
     288        ddf_msg(LVL_NOTE, "Codec OK");
    177289        return codec;
    178290error:
  • uspace/drv/audio/hdaudio/codec.h

    r65b09c1 r1412a184  
    4141        hda_t *hda;
    4242        uint8_t address;
     43        uint8_t out_aw;
    4344} hda_codec_t;
    4445
  • uspace/drv/audio/hdaudio/hdactl.c

    r65b09c1 r1412a184  
    102102        uint8_t sizecap;
    103103        uint8_t selsz;
    104         bool ok64bit;
    105104        int rc;
    106105
     
    131130        hda->ctl->corb_entries = hda_rb_entries(selsz);
    132131
    133         ddf_msg(LVL_NOTE, "Read GCAP");
    134         uint16_t gcap = hda_reg16_read(&hda->regs->gcap);
    135         ok64bit = (gcap & BIT_V(uint8_t, gcap_64ok)) != 0;
    136         ddf_msg(LVL_NOTE, "GCAP: 0x%x (64OK=%d)", gcap, ok64bit);
    137132
    138133        /*
     
    142137        hda->ctl->corb_virt = AS_AREA_ANY;
    143138        rc = dmamem_map_anonymous(hda->ctl->corb_entries * sizeof(uint32_t),
    144             ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
     139            hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
    145140            &hda->ctl->corb_phys, &hda->ctl->corb_virt);
    146141
     
    178173        uint8_t sizecap;
    179174        uint8_t selsz;
    180         bool ok64bit;
    181175        int rc;
    182176
     
    207201        hda->ctl->rirb_entries = hda_rb_entries(selsz);
    208202
    209         ddf_msg(LVL_NOTE, "Read GCAP");
    210         uint16_t gcap = hda_reg16_read(&hda->regs->gcap);
    211         ok64bit = (gcap & BIT_V(uint8_t, gcap_64ok)) != 0;
    212         ddf_msg(LVL_NOTE, "GCAP: 0x%x (64OK=%d)", gcap, ok64bit);
    213 
    214203        /*
    215204         * RIRB must be aligned to 128 bytes. If 64OK is not set,
     
    218207        hda->ctl->rirb_virt = AS_AREA_ANY;
    219208        rc = dmamem_map_anonymous(hda->ctl->rirb_entries * sizeof(uint64_t),
    220             ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
     209            hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
    221210            &hda->ctl->rirb_phys, &hda->ctl->rirb_virt);
    222211
     
    434423        ddf_msg(LVL_NOTE, "Controller is out of reset.");
    435424
     425        ddf_msg(LVL_NOTE, "Read GCAP");
     426        uint16_t gcap = hda_reg16_read(&hda->regs->gcap);
     427        ctl->ok64bit = (gcap & BIT_V(uint16_t, gcap_64ok)) != 0;
     428        ctl->oss = BIT_RANGE_EXTRACT(uint16_t, gcap_oss_h, gcap_oss_l, gcap);
     429        ctl->iss = BIT_RANGE_EXTRACT(uint16_t, gcap_iss_h, gcap_iss_l, gcap);
     430        ctl->bss = BIT_RANGE_EXTRACT(uint16_t, gcap_bss_h, gcap_bss_l, gcap);
     431        ddf_msg(LVL_NOTE, "GCAP: 0x%x (64OK=%d)", gcap, ctl->ok64bit);
     432
    436433        /* Give codecs enough time to enumerate themselves */
    437434        async_usleep(codec_enum_wait_us);
  • uspace/drv/audio/hdaudio/hdactl.h

    r65b09c1 r1412a184  
    3636#define HDACTL_H
    3737
     38#include <stdbool.h>
    3839#include "hdaudio.h"
    3940
    4041typedef struct hda_ctl {
     42        bool ok64bit;
     43        int iss;
     44        int oss;
     45        int bss;
     46
    4147        uintptr_t corb_phys;
    4248        void *corb_virt;
  • uspace/drv/audio/hdaudio/spec/codec.h

    r65b09c1 r1412a184  
    336336} hda_awidget_type_t;
    337337
     338/** Converter Control bits */
     339typedef enum {
     340        /** Stream (H) */
     341        cctl_stream_h = 7,
     342        /** Stream (L) */
     343        cctl_stream_l = 4,
     344        /** Channel (H) */
     345        cctl_channel_h = 3,
     346        /** Channel (L) */
     347        cctl_channel_l = 0
     348} hda_converter_ctl_bits_t;
     349
    338350#endif
    339351
  • uspace/drv/audio/hdaudio/spec/regs.h

    r65b09c1 r1412a184  
    4040/** Stream Descriptor registers */
    4141typedef struct {
    42         /** Control */
    43         uint16_t ctl;
     42        /** Control 1 */
     43        uint8_t ctl1;
     44        /** Control 2 */
     45        uint8_t ctl2;
     46        /** Control 3 */
     47        uint8_t ctl3;
    4448        /** Status */
    4549        uint8_t sts;
     
    142146        uint32_t icii;
    143147        /** Immediate Command Status */
    144         uint32_t icis;
     148        uint16_t icis;
    145149        /** Reserved */
    146150        uint8_t reserved8[6];
    147151        /** DMA Position Buffer Lower Base */
    148         uint32_t dpiblbase;
     152        uint32_t dplbase;
    149153        /** DMA Position Buffer Upper Base */
    150         uint32_t dpibubase;
     154        uint32_t dpubase;
    151155        /** Reserved */
    152156        uint8_t reserved9[8];
Note: See TracChangeset for help on using the changeset viewer.