mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
ALSA: hda: Direct MMIO accesses
HD-audio drivers access to the mmio registers indirectly via the corresponding bus->io_ops callbacks. This is because some platform (notably Tegra SoC) requires the word-aligned access. But it's rather a rare case, and other platforms suffer from the penalties by indirect calls unnecessarily. This patch is an attempt to optimize and cleanup for this situation. Now the special aligned access is used only when a new kconfig CONFIG_SND_HDA_ALIGNED_MMIO is set. And the HD-audio core itself provides the aligned MMIO access helpers instead of the driver side. If Kconfig isn't set (as default), the standard helpers like readl() or writel() are used directly. A couple of places in ASoC Intel drivers have the access via io_ops reg_writel(), and they are replaced with the direct writel() calls. And now with this patch, the whole bus->io_ops becomes empty, so it's dropped completely. The bus initialization functions are changed accordingly as well to drop the whole bus->io_ops. Reviewed-by: Pierre-Louis Bossart <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
This commit is contained in:
parent
619a1f195f
commit
19abfefd4c
13 changed files with 75 additions and 248 deletions
|
|
@ -6,6 +6,9 @@ config SND_HDA_CORE
|
|||
config SND_HDA_DSP_LOADER
|
||||
bool
|
||||
|
||||
config SND_HDA_ALIGNED_MMIO
|
||||
bool
|
||||
|
||||
config SND_HDA_COMPONENT
|
||||
bool
|
||||
|
||||
|
|
|
|||
|
|
@ -17,67 +17,22 @@
|
|||
MODULE_DESCRIPTION("HDA extended core");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
static void hdac_ext_writel(u32 value, u32 __iomem *addr)
|
||||
{
|
||||
writel(value, addr);
|
||||
}
|
||||
|
||||
static u32 hdac_ext_readl(u32 __iomem *addr)
|
||||
{
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
static void hdac_ext_writew(u16 value, u16 __iomem *addr)
|
||||
{
|
||||
writew(value, addr);
|
||||
}
|
||||
|
||||
static u16 hdac_ext_readw(u16 __iomem *addr)
|
||||
{
|
||||
return readw(addr);
|
||||
}
|
||||
|
||||
static void hdac_ext_writeb(u8 value, u8 __iomem *addr)
|
||||
{
|
||||
writeb(value, addr);
|
||||
}
|
||||
|
||||
static u8 hdac_ext_readb(u8 __iomem *addr)
|
||||
{
|
||||
return readb(addr);
|
||||
}
|
||||
|
||||
static const struct hdac_io_ops hdac_ext_default_io = {
|
||||
.reg_writel = hdac_ext_writel,
|
||||
.reg_readl = hdac_ext_readl,
|
||||
.reg_writew = hdac_ext_writew,
|
||||
.reg_readw = hdac_ext_readw,
|
||||
.reg_writeb = hdac_ext_writeb,
|
||||
.reg_readb = hdac_ext_readb,
|
||||
};
|
||||
|
||||
/**
|
||||
* snd_hdac_ext_bus_init - initialize a HD-audio extended bus
|
||||
* @ebus: the pointer to extended bus object
|
||||
* @dev: device pointer
|
||||
* @ops: bus verb operators
|
||||
* @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use
|
||||
* default ops
|
||||
*
|
||||
* Returns 0 if successful, or a negative error code.
|
||||
*/
|
||||
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
|
||||
const struct hdac_bus_ops *ops,
|
||||
const struct hdac_io_ops *io_ops,
|
||||
const struct hdac_ext_bus_ops *ext_ops)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* check if io ops are provided, if not load the defaults */
|
||||
if (io_ops == NULL)
|
||||
io_ops = &hdac_ext_default_io;
|
||||
|
||||
ret = snd_hdac_bus_init(bus, dev, ops, io_ops);
|
||||
ret = snd_hdac_bus_init(bus, dev, ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,11 @@ static const struct hdac_bus_ops default_ops = {
|
|||
* snd_hdac_bus_init - initialize a HD-audio bas bus
|
||||
* @bus: the pointer to bus object
|
||||
* @ops: bus verb operators
|
||||
* @io_ops: lowlevel I/O operators
|
||||
*
|
||||
* Returns 0 if successful, or a negative error code.
|
||||
*/
|
||||
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
|
||||
const struct hdac_bus_ops *ops,
|
||||
const struct hdac_io_ops *io_ops)
|
||||
const struct hdac_bus_ops *ops)
|
||||
{
|
||||
memset(bus, 0, sizeof(*bus));
|
||||
bus->dev = dev;
|
||||
|
|
@ -33,7 +31,6 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
|
|||
bus->ops = ops;
|
||||
else
|
||||
bus->ops = &default_ops;
|
||||
bus->io_ops = io_ops;
|
||||
bus->dma_type = SNDRV_DMA_TYPE_DEV;
|
||||
INIT_LIST_HEAD(&bus->stream_list);
|
||||
INIT_LIST_HEAD(&bus->codec_list);
|
||||
|
|
@ -218,3 +215,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus,
|
|||
flush_work(&bus->unsol_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
|
||||
/* Helpers for aligned read/write of mmio space, for Tegra */
|
||||
unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask)
|
||||
{
|
||||
void __iomem *aligned_addr =
|
||||
(void __iomem *)((unsigned long)(addr) & ~0x3);
|
||||
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
|
||||
unsigned int v;
|
||||
|
||||
v = readl(aligned_addr);
|
||||
return (v >> shift) & mask;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_aligned_read);
|
||||
|
||||
void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
|
||||
unsigned int mask)
|
||||
{
|
||||
void __iomem *aligned_addr =
|
||||
(void __iomem *)((unsigned long)(addr) & ~0x3);
|
||||
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
|
||||
unsigned int v;
|
||||
|
||||
v = readl(aligned_addr);
|
||||
v &= ~(mask << shift);
|
||||
v |= val << shift;
|
||||
writel(v, aligned_addr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_aligned_write);
|
||||
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
|
||||
|
|
|
|||
Loading…
Reference in a new issue