From: Joakim Zhang Date: Fri, 5 Dec 2025 15:46:20 +0000 (+0800) Subject: ALSA: hda/core: add addr_offset field for bus address translation X-Git-Tag: v6.19-rc1~20^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a4f2fa516e83f11c3792405599613c12efe6135e;p=thirdparty%2Fkernel%2Flinux.git 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 Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20251205154621.3019640-3-joakim.zhang@cixtech.com --- diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 4e0c1d8af09f7..f11bfc6b9f428 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -380,6 +380,9 @@ struct hdac_bus { /* factor used to derive STRIPE control value */ 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, diff --git a/sound/hda/core/bus.c b/sound/hda/core/bus.c index 9b196c915f378..81498f1e413e2 100644 --- a/sound/hda/core/bus.c +++ b/sound/hda/core/bus.c @@ -47,6 +47,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, INIT_LIST_HEAD(&bus->hlink_list); init_waitqueue_head(&bus->rirb_wq); bus->irq = -1; + bus->addr_offset = 0; /* * Default value of '8' is as per the HD audio specification (Rev 1.0a). diff --git a/sound/hda/core/controller.c b/sound/hda/core/controller.c index a7c00ad801170..69e11d62bbfa7 100644 --- a/sound/hda/core/controller.c +++ b/sound/hda/core/controller.c @@ -48,8 +48,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) /* CORB set up */ bus->corb.addr = bus->rb.addr; bus->corb.buf = (__le32 *)bus->rb.area; - snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr); - snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(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 + bus->addr_offset)); /* set the corb size to 256 entries (ULI requires explicitly) */ 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.wp = bus->rirb.rp = 0; memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds)); - snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr); - snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(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 + bus->addr_offset)); /* set the rirb size to 256 entries (ULI requires explicitly) */ 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 */ if (bus->use_posbuf && bus->posbuf.addr) { - snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); - snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(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 + bus->addr_offset)); } bus->chip_init = true; diff --git a/sound/hda/core/stream.c b/sound/hda/core/stream.c index 579ec544ef4a4..b471a038b3140 100644 --- a/sound/hda/core/stream.c +++ b/sound/hda/core/stream.c @@ -288,16 +288,16 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading) /* program the 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 */ 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 */ if (bus->use_posbuf && bus->posbuf.addr) { if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE)) 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 */ @@ -464,8 +464,8 @@ static int setup_bdle(struct hdac_bus *bus, addr = snd_sgbuf_get_addr(dmab, ofs); /* program the address field of the BDL entry */ - bdl[0] = cpu_to_le32((u32)addr); - bdl[1] = cpu_to_le32(upper_32_bits(addr)); + bdl[0] = cpu_to_le32((u32)(addr + bus->addr_offset)); + bdl[1] = cpu_to_le32(upper_32_bits(addr + bus->addr_offset)); /* program the size field of the BDL entry */ chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); /* one BDLE cannot cross 4K boundary on CTHDA chips */