Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_hda.c
Show First 20 Lines • Show All 326 Lines • ▼ Show 20 Lines | hda_parse_config(const char *opts, const char *key, char *val) | ||||
size_t len; | size_t len; | ||||
int i; | int i; | ||||
if (!opts) | if (!opts) | ||||
return (0); | return (0); | ||||
len = strlen(opts); | len = strlen(opts); | ||||
if (len >= sizeof(buf)) { | if (len >= sizeof(buf)) { | ||||
DPRINTF("Opts too big\n"); | DPRINTF("Opts too big\n\r"); | ||||
return (0); | return (0); | ||||
} | } | ||||
DPRINTF("opts: %s\n", opts); | DPRINTF("opts: %s\n\r", opts); | ||||
strcpy(buf, opts); | strcpy(buf, opts); | ||||
for (i = 0; i < len; i++) | for (i = 0; i < len; i++) | ||||
if (buf[i] == ',') { | if (buf[i] == ',') { | ||||
buf[i] = 0; | buf[i] = 0; | ||||
tmp = buf + i + 1; | tmp = buf + i + 1; | ||||
break; | break; | ||||
Show All 24 Lines | hda_init(const char *opts) | ||||
char play[64]; | char play[64]; | ||||
char rec[64]; | char rec[64]; | ||||
int err, p, r; | int err, p, r; | ||||
#if DEBUG_HDA == 1 | #if DEBUG_HDA == 1 | ||||
dbg = fopen("/tmp/bhyve_hda.log", "w+"); | dbg = fopen("/tmp/bhyve_hda.log", "w+"); | ||||
#endif | #endif | ||||
DPRINTF("opts: %s\n", opts); | DPRINTF("opts: %s\n\r", opts); | ||||
sc = calloc(1, sizeof(*sc)); | sc = calloc(1, sizeof(*sc)); | ||||
if (!sc) | if (!sc) | ||||
return (NULL); | return (NULL); | ||||
hda_reset_regs(sc); | hda_reset_regs(sc); | ||||
/* | /* | ||||
* TODO search all the codecs declared in opts | * TODO search all the codecs declared in opts | ||||
* For now we play with one single codec | * For now we play with one single codec | ||||
*/ | */ | ||||
codec = hda_find_codec_class("hda_codec"); | codec = hda_find_codec_class("hda_codec"); | ||||
if (codec) { | if (codec) { | ||||
p = hda_parse_config(opts, "play=", play); | p = hda_parse_config(opts, "play=", play); | ||||
r = hda_parse_config(opts, "rec=", rec); | r = hda_parse_config(opts, "rec=", rec); | ||||
DPRINTF("play: %s rec: %s\n", play, rec); | DPRINTF("play: %s rec: %s\n\r", play, rec); | ||||
if (p | r) { | if (p | r) { | ||||
err = hda_codec_constructor(sc, codec, p ? \ | err = hda_codec_constructor(sc, codec, p ? \ | ||||
play : NULL, r ? rec : NULL, NULL); | play : NULL, r ? rec : NULL, NULL); | ||||
assert(!err); | assert(!err); | ||||
} | } | ||||
} | } | ||||
return (sc); | return (sc); | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec, | ||||
hci->hda = sc; | hci->hda = sc; | ||||
hci->hops = &hops; | hci->hops = &hops; | ||||
hci->cad = sc->codecs_no; | hci->cad = sc->codecs_no; | ||||
hci->codec = codec; | hci->codec = codec; | ||||
sc->codecs[sc->codecs_no++] = hci; | sc->codecs[sc->codecs_no++] = hci; | ||||
if (!codec->init) { | if (!codec->init) { | ||||
DPRINTF("This codec does not implement the init function\n"); | DPRINTF("This codec does not implement the init function\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (codec->init(hci, play, rec, opts)); | return (codec->init(hci, play, rec, opts)); | ||||
} | } | ||||
static struct hda_codec_class * | static struct hda_codec_class * | ||||
hda_find_codec_class(const char *name) | hda_find_codec_class(const char *name) | ||||
Show All 16 Lines | hda_send_command(struct hda_softc *sc, uint32_t verb) | ||||
struct hda_codec_inst *hci = NULL; | struct hda_codec_inst *hci = NULL; | ||||
struct hda_codec_class *codec = NULL; | struct hda_codec_class *codec = NULL; | ||||
uint8_t cad = (verb >> HDA_CMD_CAD_SHIFT) & 0x0f; | uint8_t cad = (verb >> HDA_CMD_CAD_SHIFT) & 0x0f; | ||||
hci = sc->codecs[cad]; | hci = sc->codecs[cad]; | ||||
if (!hci) | if (!hci) | ||||
return (-1); | return (-1); | ||||
DPRINTF("cad: 0x%x verb: 0x%x\n", cad, verb); | DPRINTF("cad: 0x%x verb: 0x%x\n\r", cad, verb); | ||||
codec = hci->codec; | codec = hci->codec; | ||||
assert(codec); | assert(codec); | ||||
if (!codec->command) { | if (!codec->command) { | ||||
DPRINTF("This codec does not implement the command function\n"); | DPRINTF("This codec does not implement the command function\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (codec->command(hci, verb)); | return (codec->command(hci, verb)); | ||||
} | } | ||||
static int | static int | ||||
hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream, | hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream, | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
hda_reset_regs(struct hda_softc *sc) | hda_reset_regs(struct hda_softc *sc) | ||||
{ | { | ||||
uint32_t off = 0; | uint32_t off = 0; | ||||
uint8_t i; | uint8_t i; | ||||
DPRINTF("Reset the HDA controller registers ...\n"); | DPRINTF("Reset the HDA controller registers ...\n\r"); | ||||
memset(sc->regs, 0, sizeof(sc->regs)); | memset(sc->regs, 0, sizeof(sc->regs)); | ||||
hda_set_reg_by_offset(sc, HDAC_GCAP, | hda_set_reg_by_offset(sc, HDAC_GCAP, | ||||
HDAC_GCAP_64OK | | HDAC_GCAP_64OK | | ||||
(HDA_ISS_NO << HDAC_GCAP_ISS_SHIFT) | | (HDA_ISS_NO << HDAC_GCAP_ISS_SHIFT) | | ||||
(HDA_OSS_NO << HDAC_GCAP_OSS_SHIFT)); | (HDA_OSS_NO << HDAC_GCAP_OSS_SHIFT)); | ||||
hda_set_reg_by_offset(sc, HDAC_VMAJ, 0x01); | hda_set_reg_by_offset(sc, HDAC_VMAJ, 0x01); | ||||
Show All 11 Lines | |||||
} | } | ||||
static void | static void | ||||
hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind) | hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind) | ||||
{ | { | ||||
struct hda_stream_desc *st = &sc->streams[stream_ind]; | struct hda_stream_desc *st = &sc->streams[stream_ind]; | ||||
uint32_t off = hda_get_offset_stream(stream_ind); | uint32_t off = hda_get_offset_stream(stream_ind); | ||||
DPRINTF("Reset the HDA stream: 0x%x\n", stream_ind); | DPRINTF("Reset the HDA stream: 0x%x\n\r", stream_ind); | ||||
/* Reset the Stream Descriptor registers */ | /* Reset the Stream Descriptor registers */ | ||||
memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN); | memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN); | ||||
/* Reset the Stream Descriptor */ | /* Reset the Stream Descriptor */ | ||||
memset(st, 0, sizeof(*st)); | memset(st, 0, sizeof(*st)); | ||||
hda_set_field_by_offset(sc, off + HDAC_SDSTS, | hda_set_field_by_offset(sc, off + HDAC_SDSTS, | ||||
Show All 33 Lines | hda_stream_start(struct hda_softc *sc, uint8_t stream_ind) | ||||
bdl_cnt = lvi + 1; | bdl_cnt = lvi + 1; | ||||
assert(bdl_cnt <= HDA_BDL_MAX_LEN); | assert(bdl_cnt <= HDA_BDL_MAX_LEN); | ||||
bdl_paddr = bdpl | (bdpu << 32); | bdl_paddr = bdpl | (bdpu << 32); | ||||
bdl_vaddr = hda_dma_get_vaddr(sc, bdl_paddr, | bdl_vaddr = hda_dma_get_vaddr(sc, bdl_paddr, | ||||
HDA_BDL_ENTRY_LEN * bdl_cnt); | HDA_BDL_ENTRY_LEN * bdl_cnt); | ||||
if (!bdl_vaddr) { | if (!bdl_vaddr) { | ||||
DPRINTF("Fail to get the guest virtual address\n"); | DPRINTF("Fail to get the guest virtual address\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
DPRINTF("stream: 0x%x bdl_cnt: 0x%x bdl_paddr: 0x%lx\n", | DPRINTF("stream: 0x%x bdl_cnt: 0x%x bdl_paddr: 0x%lx\n\r", | ||||
stream_ind, bdl_cnt, bdl_paddr); | stream_ind, bdl_cnt, bdl_paddr); | ||||
st->bdl_cnt = bdl_cnt; | st->bdl_cnt = bdl_cnt; | ||||
bdle = (struct hda_bdle *)bdl_vaddr; | bdle = (struct hda_bdle *)bdl_vaddr; | ||||
for (i = 0; i < bdl_cnt; i++, bdle++) { | for (i = 0; i < bdl_cnt; i++, bdle++) { | ||||
bdle_sz = bdle->len; | bdle_sz = bdle->len; | ||||
assert(!(bdle_sz % HDA_DMA_ACCESS_LEN)); | assert(!(bdle_sz % HDA_DMA_ACCESS_LEN)); | ||||
bdle_addrl = bdle->addrl; | bdle_addrl = bdle->addrl; | ||||
bdle_addrh = bdle->addrh; | bdle_addrh = bdle->addrh; | ||||
bdle_paddr = bdle_addrl | (bdle_addrh << 32); | bdle_paddr = bdle_addrl | (bdle_addrh << 32); | ||||
bdle_vaddr = hda_dma_get_vaddr(sc, bdle_paddr, bdle_sz); | bdle_vaddr = hda_dma_get_vaddr(sc, bdle_paddr, bdle_sz); | ||||
if (!bdle_vaddr) { | if (!bdle_vaddr) { | ||||
DPRINTF("Fail to get the guest virtual address\n"); | DPRINTF("Fail to get the guest virtual address\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
bdle_desc = &st->bdl[i]; | bdle_desc = &st->bdl[i]; | ||||
bdle_desc->addr = bdle_vaddr; | bdle_desc->addr = bdle_vaddr; | ||||
bdle_desc->len = bdle_sz; | bdle_desc->len = bdle_sz; | ||||
bdle_desc->ioc = bdle->ioc; | bdle_desc->ioc = bdle->ioc; | ||||
DPRINTF("bdle: 0x%x bdle_sz: 0x%x\n", i, bdle_sz); | DPRINTF("bdle: 0x%x bdle_sz: 0x%x\n\r", i, bdle_sz); | ||||
} | } | ||||
sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0); | sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0); | ||||
strm = (sdctl >> 20) & 0x0f; | strm = (sdctl >> 20) & 0x0f; | ||||
dir = stream_ind >= HDA_ISS_NO; | dir = stream_ind >= HDA_ISS_NO; | ||||
DPRINTF("strm: 0x%x, dir: 0x%x\n", strm, dir); | DPRINTF("strm: 0x%x, dir: 0x%x\n\r", strm, dir); | ||||
sc->stream_map[dir][strm] = stream_ind; | sc->stream_map[dir][strm] = stream_ind; | ||||
st->stream = strm; | st->stream = strm; | ||||
st->dir = dir; | st->dir = dir; | ||||
st->bp = 0; | st->bp = 0; | ||||
st->be = 0; | st->be = 0; | ||||
hda_set_pib(sc, stream_ind, 0); | hda_set_pib(sc, stream_ind, 0); | ||||
st->run = 1; | st->run = 1; | ||||
hda_notify_codecs(sc, 1, strm, dir); | hda_notify_codecs(sc, 1, strm, dir); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind) | hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind) | ||||
{ | { | ||||
struct hda_stream_desc *st = &sc->streams[stream_ind]; | struct hda_stream_desc *st = &sc->streams[stream_ind]; | ||||
uint8_t strm = st->stream; | uint8_t strm = st->stream; | ||||
uint8_t dir = st->dir; | uint8_t dir = st->dir; | ||||
DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x\n", stream_ind, strm, dir); | DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x\n\r", stream_ind, strm, dir); | ||||
st->run = 0; | st->run = 0; | ||||
hda_notify_codecs(sc, 0, strm, dir); | hda_notify_codecs(sc, 0, strm, dir); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 24 Lines | |||||
} | } | ||||
static inline void | static inline void | ||||
hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p) | hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p) | ||||
{ | { | ||||
#if DEBUG_HDA == 1 | #if DEBUG_HDA == 1 | ||||
char *name = p->name; | char *name = p->name; | ||||
#endif | #endif | ||||
DPRINTF("%s size: %d\n", name, p->size); | DPRINTF("%s size: %d\n\r", name, p->size); | ||||
DPRINTF("%s dma_vaddr: %p\n", name, p->dma_vaddr); | DPRINTF("%s dma_vaddr: %p\n\r", name, p->dma_vaddr); | ||||
DPRINTF("%s wp: 0x%x\n", name, p->wp); | DPRINTF("%s wp: 0x%x\n\r", name, p->wp); | ||||
DPRINTF("%s rp: 0x%x\n", name, p->rp); | DPRINTF("%s rp: 0x%x\n\r", name, p->rp); | ||||
} | } | ||||
static int | static int | ||||
hda_corb_start(struct hda_softc *sc) | hda_corb_start(struct hda_softc *sc) | ||||
{ | { | ||||
struct hda_codec_cmd_ctl *corb = &sc->corb; | struct hda_codec_cmd_ctl *corb = &sc->corb; | ||||
uint8_t corbsize = 0; | uint8_t corbsize = 0; | ||||
uint64_t corblbase = 0; | uint64_t corblbase = 0; | ||||
uint64_t corbubase = 0; | uint64_t corbubase = 0; | ||||
uint64_t corbpaddr = 0; | uint64_t corbpaddr = 0; | ||||
corb->name = "CORB"; | corb->name = "CORB"; | ||||
corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) & \ | corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) & \ | ||||
HDAC_CORBSIZE_CORBSIZE_MASK; | HDAC_CORBSIZE_CORBSIZE_MASK; | ||||
corb->size = hda_corb_sizes[corbsize]; | corb->size = hda_corb_sizes[corbsize]; | ||||
if (!corb->size) { | if (!corb->size) { | ||||
DPRINTF("Invalid corb size\n"); | DPRINTF("Invalid corb size\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE); | corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE); | ||||
corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE); | corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE); | ||||
corbpaddr = corblbase | (corbubase << 32); | corbpaddr = corblbase | (corbubase << 32); | ||||
DPRINTF("CORB dma_paddr: %p\n", (void *)corbpaddr); | DPRINTF("CORB dma_paddr: %p\n\r", (void *)corbpaddr); | ||||
corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr, | corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr, | ||||
HDA_CORB_ENTRY_LEN * corb->size); | HDA_CORB_ENTRY_LEN * corb->size); | ||||
if (!corb->dma_vaddr) { | if (!corb->dma_vaddr) { | ||||
DPRINTF("Fail to get the guest virtual address\n"); | DPRINTF("Fail to get the guest virtual address\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP); | corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP); | ||||
corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP); | corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP); | ||||
corb->run = 1; | corb->run = 1; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | hda_rirb_start(struct hda_softc *sc) | ||||
rirb->name = "RIRB"; | rirb->name = "RIRB"; | ||||
rirbsize = hda_get_reg_by_offset(sc, HDAC_RIRBSIZE) & \ | rirbsize = hda_get_reg_by_offset(sc, HDAC_RIRBSIZE) & \ | ||||
HDAC_RIRBSIZE_RIRBSIZE_MASK; | HDAC_RIRBSIZE_RIRBSIZE_MASK; | ||||
rirb->size = hda_rirb_sizes[rirbsize]; | rirb->size = hda_rirb_sizes[rirbsize]; | ||||
if (!rirb->size) { | if (!rirb->size) { | ||||
DPRINTF("Invalid rirb size\n"); | DPRINTF("Invalid rirb size\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
rirblbase = hda_get_reg_by_offset(sc, HDAC_RIRBLBASE); | rirblbase = hda_get_reg_by_offset(sc, HDAC_RIRBLBASE); | ||||
rirbubase = hda_get_reg_by_offset(sc, HDAC_RIRBUBASE); | rirbubase = hda_get_reg_by_offset(sc, HDAC_RIRBUBASE); | ||||
rirbpaddr = rirblbase | (rirbubase << 32); | rirbpaddr = rirblbase | (rirbubase << 32); | ||||
DPRINTF("RIRB dma_paddr: %p\n", (void *)rirbpaddr); | DPRINTF("RIRB dma_paddr: %p\n\r", (void *)rirbpaddr); | ||||
rirb->dma_vaddr = hda_dma_get_vaddr(sc, rirbpaddr, | rirb->dma_vaddr = hda_dma_get_vaddr(sc, rirbpaddr, | ||||
HDA_RIRB_ENTRY_LEN * rirb->size); | HDA_RIRB_ENTRY_LEN * rirb->size); | ||||
if (!rirb->dma_vaddr) { | if (!rirb->dma_vaddr) { | ||||
DPRINTF("Fail to get the guest virtual address\n"); | DPRINTF("Fail to get the guest virtual address\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
rirb->wp = hda_get_reg_by_offset(sc, HDAC_RIRBWP); | rirb->wp = hda_get_reg_by_offset(sc, HDAC_RIRBWP); | ||||
rirb->rp = 0x0000; | rirb->rp = 0x0000; | ||||
rirb->run = 1; | rirb->run = 1; | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old) | ||||
if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old & \ | if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old & \ | ||||
HDAC_DPLBASE_DPLBASE_DMAPBE)) { | HDAC_DPLBASE_DPLBASE_DMAPBE)) { | ||||
if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) { | if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) { | ||||
dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK; | dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK; | ||||
dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE); | dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE); | ||||
dpibpaddr = dpiblbase | (dpibubase << 32); | dpibpaddr = dpiblbase | (dpibubase << 32); | ||||
DPRINTF("DMA Position In Buffer dma_paddr: %p\n", | DPRINTF("DMA Position In Buffer dma_paddr: %p\n\r", | ||||
(void *)dpibpaddr); | (void *)dpibpaddr); | ||||
sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr, | sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr, | ||||
HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO); | HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO); | ||||
if (!sc->dma_pib_vaddr) { | if (!sc->dma_pib_vaddr) { | ||||
DPRINTF("Fail to get the guest \ | DPRINTF("Fail to get the guest \ | ||||
virtual address\n"); | virtual address\n\r"); | ||||
assert(0); | assert(0); | ||||
} | } | ||||
} else { | } else { | ||||
DPRINTF("DMA Position In Buffer Reset\n"); | DPRINTF("DMA Position In Buffer Reset\n\r"); | ||||
sc->dma_pib_vaddr = NULL; | sc->dma_pib_vaddr = NULL; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old) | hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old) | ||||
{ | { | ||||
uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0); | uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0); | ||||
uint32_t value = hda_get_reg_by_offset(sc, offset); | uint32_t value = hda_get_reg_by_offset(sc, offset); | ||||
int err; | int err; | ||||
DPRINTF("stream_ind: 0x%x old: 0x%x value: 0x%x\n", | DPRINTF("stream_ind: 0x%x old: 0x%x value: 0x%x\n\r", | ||||
stream_ind, old, value); | stream_ind, old, value); | ||||
if (value & HDAC_SDCTL_SRST) { | if (value & HDAC_SDCTL_SRST) { | ||||
hda_stream_reset(sc, stream_ind); | hda_stream_reset(sc, stream_ind); | ||||
} | } | ||||
if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) { | if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) { | ||||
if (value & HDAC_SDCTL_RUN) { | if (value & HDAC_SDCTL_RUN) { | ||||
Show All 31 Lines | |||||
hda_signal_state_change(struct hda_codec_inst *hci) | hda_signal_state_change(struct hda_codec_inst *hci) | ||||
{ | { | ||||
struct hda_softc *sc = NULL; | struct hda_softc *sc = NULL; | ||||
uint32_t sdiwake = 0; | uint32_t sdiwake = 0; | ||||
assert(hci); | assert(hci); | ||||
assert(hci->hda); | assert(hci->hda); | ||||
DPRINTF("cad: 0x%x\n", hci->cad); | DPRINTF("cad: 0x%x\n\r", hci->cad); | ||||
sc = hci->hda; | sc = hci->hda; | ||||
sdiwake = 1 << hci->cad; | sdiwake = 1 << hci->cad; | ||||
hda_set_field_by_offset(sc, HDAC_STATESTS, sdiwake, sdiwake); | hda_set_field_by_offset(sc, HDAC_STATESTS, sdiwake, sdiwake); | ||||
hda_update_intr(sc); | hda_update_intr(sc); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, | ||||
uint8_t irq = 0; | uint8_t irq = 0; | ||||
assert(hci); | assert(hci); | ||||
assert(hci->hda); | assert(hci->hda); | ||||
assert(buf); | assert(buf); | ||||
assert(!(count % HDA_DMA_ACCESS_LEN)); | assert(!(count % HDA_DMA_ACCESS_LEN)); | ||||
if (!stream) { | if (!stream) { | ||||
DPRINTF("Invalid stream\n"); | DPRINTF("Invalid stream\n\r"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
sc = hci->hda; | sc = hci->hda; | ||||
assert(stream < HDA_STREAM_TAGS_CNT); | assert(stream < HDA_STREAM_TAGS_CNT); | ||||
stream_ind = sc->stream_map[dir][stream]; | stream_ind = sc->stream_map[dir][stream]; | ||||
if (!dir) | if (!dir) | ||||
assert(stream_ind < HDA_ISS_NO); | assert(stream_ind < HDA_ISS_NO); | ||||
else | else | ||||
assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO); | assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO); | ||||
st = &sc->streams[stream_ind]; | st = &sc->streams[stream_ind]; | ||||
if (!st->run) { | if (!st->run) { | ||||
DPRINTF("Stream 0x%x stopped\n", stream); | DPRINTF("Stream 0x%x stopped\n\r", stream); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
assert(st->stream == stream); | assert(st->stream == stream); | ||||
off = hda_get_offset_stream(stream_ind); | off = hda_get_offset_stream(stream_ind); | ||||
lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB); | lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB); | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct hda_softc *sc = pi->pi_arg; | struct hda_softc *sc = pi->pi_arg; | ||||
int err; | int err; | ||||
assert(sc); | assert(sc); | ||||
assert(baridx == 0); | assert(baridx == 0); | ||||
assert(size <= 4); | assert(size <= 4); | ||||
DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value); | DPRINTF("offset: 0x%lx value: 0x%lx\n\r", offset, value); | ||||
err = hda_write(sc, offset, size, value); | err = hda_write(sc, offset, size, value); | ||||
assert(!err); | assert(!err); | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | ||||
int baridx, uint64_t offset, int size) | int baridx, uint64_t offset, int size) | ||||
{ | { | ||||
struct hda_softc *sc = pi->pi_arg; | struct hda_softc *sc = pi->pi_arg; | ||||
uint64_t value = 0; | uint64_t value = 0; | ||||
assert(sc); | assert(sc); | ||||
assert(baridx == 0); | assert(baridx == 0); | ||||
assert(size <= 4); | assert(size <= 4); | ||||
value = hda_read(sc, offset); | value = hda_read(sc, offset); | ||||
DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value); | DPRINTF("offset: 0x%lx value: 0x%lx\n\r", offset, value); | ||||
return (value); | return (value); | ||||
} | } |