ALSA: hda/core: add addr_offset field for bus address translation
Add bus addr_offset field for dma address translation, for some SoCs such as CIX SKY1 which is ARM64 Arch, HOST and HDAC has different memory view, so need to do dma address translation between HOST and HDAC. Signed-off-by: Joakim Zhang <joakim.zhang@cixtech.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20251205154621.3019640-3-joakim.zhang@cixtech.compull/1354/merge
parent
85a6544777
commit
a4f2fa516e
|
|
@ -380,6 +380,9 @@ struct hdac_bus {
|
||||||
|
|
||||||
/* factor used to derive STRIPE control value */
|
/* factor used to derive STRIPE control value */
|
||||||
unsigned int sdo_limit;
|
unsigned int sdo_limit;
|
||||||
|
|
||||||
|
/* address offset between host and hadc */
|
||||||
|
dma_addr_t addr_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
|
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
|
||||||
INIT_LIST_HEAD(&bus->hlink_list);
|
INIT_LIST_HEAD(&bus->hlink_list);
|
||||||
init_waitqueue_head(&bus->rirb_wq);
|
init_waitqueue_head(&bus->rirb_wq);
|
||||||
bus->irq = -1;
|
bus->irq = -1;
|
||||||
|
bus->addr_offset = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default value of '8' is as per the HD audio specification (Rev 1.0a).
|
* Default value of '8' is as per the HD audio specification (Rev 1.0a).
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
|
||||||
/* CORB set up */
|
/* CORB set up */
|
||||||
bus->corb.addr = bus->rb.addr;
|
bus->corb.addr = bus->rb.addr;
|
||||||
bus->corb.buf = (__le32 *)bus->rb.area;
|
bus->corb.buf = (__le32 *)bus->rb.area;
|
||||||
snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr);
|
snd_hdac_chip_writel(bus, CORBLBASE, (u32)(bus->corb.addr + bus->addr_offset));
|
||||||
snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr));
|
snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr + bus->addr_offset));
|
||||||
|
|
||||||
/* set the corb size to 256 entries (ULI requires explicitly) */
|
/* set the corb size to 256 entries (ULI requires explicitly) */
|
||||||
snd_hdac_chip_writeb(bus, CORBSIZE, 0x02);
|
snd_hdac_chip_writeb(bus, CORBSIZE, 0x02);
|
||||||
|
|
@ -70,8 +70,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
|
||||||
bus->rirb.buf = (__le32 *)(bus->rb.area + 2048);
|
bus->rirb.buf = (__le32 *)(bus->rb.area + 2048);
|
||||||
bus->rirb.wp = bus->rirb.rp = 0;
|
bus->rirb.wp = bus->rirb.rp = 0;
|
||||||
memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds));
|
memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds));
|
||||||
snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr);
|
snd_hdac_chip_writel(bus, RIRBLBASE, (u32)(bus->rirb.addr + bus->addr_offset));
|
||||||
snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr));
|
snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr + bus->addr_offset));
|
||||||
|
|
||||||
/* set the rirb size to 256 entries (ULI requires explicitly) */
|
/* set the rirb size to 256 entries (ULI requires explicitly) */
|
||||||
snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02);
|
snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02);
|
||||||
|
|
@ -625,8 +625,8 @@ bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
|
||||||
|
|
||||||
/* program the position buffer */
|
/* program the position buffer */
|
||||||
if (bus->use_posbuf && bus->posbuf.addr) {
|
if (bus->use_posbuf && bus->posbuf.addr) {
|
||||||
snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr);
|
snd_hdac_chip_writel(bus, DPLBASE, (u32)(bus->posbuf.addr + bus->addr_offset));
|
||||||
snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr));
|
snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr + bus->addr_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->chip_init = true;
|
bus->chip_init = true;
|
||||||
|
|
|
||||||
|
|
@ -288,16 +288,16 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading)
|
||||||
|
|
||||||
/* program the BDL address */
|
/* program the BDL address */
|
||||||
/* lower BDL address */
|
/* lower BDL address */
|
||||||
snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
|
snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)(azx_dev->bdl.addr + bus->addr_offset));
|
||||||
/* upper BDL address */
|
/* upper BDL address */
|
||||||
snd_hdac_stream_writel(azx_dev, SD_BDLPU,
|
snd_hdac_stream_writel(azx_dev, SD_BDLPU,
|
||||||
upper_32_bits(azx_dev->bdl.addr));
|
upper_32_bits(azx_dev->bdl.addr + bus->addr_offset));
|
||||||
|
|
||||||
/* enable the position buffer */
|
/* enable the position buffer */
|
||||||
if (bus->use_posbuf && bus->posbuf.addr) {
|
if (bus->use_posbuf && bus->posbuf.addr) {
|
||||||
if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE))
|
if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE))
|
||||||
snd_hdac_chip_writel(bus, DPLBASE,
|
snd_hdac_chip_writel(bus, DPLBASE,
|
||||||
(u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE);
|
(u32)(bus->posbuf.addr + bus->addr_offset) | AZX_DPLBASE_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the interrupt enable bits in the descriptor control register */
|
/* set the interrupt enable bits in the descriptor control register */
|
||||||
|
|
@ -464,8 +464,8 @@ static int setup_bdle(struct hdac_bus *bus,
|
||||||
|
|
||||||
addr = snd_sgbuf_get_addr(dmab, ofs);
|
addr = snd_sgbuf_get_addr(dmab, ofs);
|
||||||
/* program the address field of the BDL entry */
|
/* program the address field of the BDL entry */
|
||||||
bdl[0] = cpu_to_le32((u32)addr);
|
bdl[0] = cpu_to_le32((u32)(addr + bus->addr_offset));
|
||||||
bdl[1] = cpu_to_le32(upper_32_bits(addr));
|
bdl[1] = cpu_to_le32(upper_32_bits(addr + bus->addr_offset));
|
||||||
/* program the size field of the BDL entry */
|
/* program the size field of the BDL entry */
|
||||||
chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size);
|
chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size);
|
||||||
/* one BDLE cannot cross 4K boundary on CTHDA chips */
|
/* one BDLE cannot cross 4K boundary on CTHDA chips */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue