Commit c2f16a94 authored by Mark Brown's avatar Mark Brown

Merge branch 'topic/hda-bus-ops-cleanup' of...

Merge branch 'topic/hda-bus-ops-cleanup' of https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound into asoc-5.4
parents f6326fa4 d4ff1b39
...@@ -253,24 +253,6 @@ struct hdac_ext_bus_ops { ...@@ -253,24 +253,6 @@ struct hdac_ext_bus_ops {
int (*hdev_detach)(struct hdac_device *hdev); int (*hdev_detach)(struct hdac_device *hdev);
}; };
/*
* Lowlevel I/O operators
*/
struct hdac_io_ops {
/* mapped register accesses */
void (*reg_writel)(u32 value, u32 __iomem *addr);
u32 (*reg_readl)(u32 __iomem *addr);
void (*reg_writew)(u16 value, u16 __iomem *addr);
u16 (*reg_readw)(u16 __iomem *addr);
void (*reg_writeb)(u8 value, u8 __iomem *addr);
u8 (*reg_readb)(u8 __iomem *addr);
/* Allocation ops */
int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size,
struct snd_dma_buffer *buf);
void (*dma_free_pages)(struct hdac_bus *bus,
struct snd_dma_buffer *buf);
};
#define HDA_UNSOL_QUEUE_SIZE 64 #define HDA_UNSOL_QUEUE_SIZE 64
#define HDA_MAX_CODECS 8 /* limit by controller side */ #define HDA_MAX_CODECS 8 /* limit by controller side */
...@@ -304,7 +286,6 @@ struct hdac_rb { ...@@ -304,7 +286,6 @@ struct hdac_rb {
struct hdac_bus { struct hdac_bus {
struct device *dev; struct device *dev;
const struct hdac_bus_ops *ops; const struct hdac_bus_ops *ops;
const struct hdac_io_ops *io_ops;
const struct hdac_ext_bus_ops *ext_ops; const struct hdac_ext_bus_ops *ext_ops;
/* h/w resources */ /* h/w resources */
...@@ -344,6 +325,7 @@ struct hdac_bus { ...@@ -344,6 +325,7 @@ struct hdac_bus {
/* CORB/RIRB and position buffers */ /* CORB/RIRB and position buffers */
struct snd_dma_buffer rb; struct snd_dma_buffer rb;
struct snd_dma_buffer posbuf; struct snd_dma_buffer posbuf;
int dma_type; /* SNDRV_DMA_TYPE_XXX for CORB/RIRB */
/* hdac_stream linked list */ /* hdac_stream linked list */
struct list_head stream_list; struct list_head stream_list;
...@@ -384,8 +366,7 @@ struct hdac_bus { ...@@ -384,8 +366,7 @@ struct hdac_bus {
}; };
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops);
const struct hdac_io_ops *io_ops);
void snd_hdac_bus_exit(struct hdac_bus *bus); void snd_hdac_bus_exit(struct hdac_bus *bus);
int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr,
unsigned int cmd, unsigned int *res); unsigned int cmd, unsigned int *res);
...@@ -429,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, ...@@ -429,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus);
void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
#ifdef CONFIG_SND_HDA_ALIGNED_MMIO
unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
unsigned int mask);
#define snd_hdac_reg_writeb(v, addr) snd_hdac_aligned_write(v, addr, 0xff)
#define snd_hdac_reg_writew(v, addr) snd_hdac_aligned_write(v, addr, 0xffff)
#define snd_hdac_reg_readb(addr) snd_hdac_aligned_read(addr, 0xff)
#define snd_hdac_reg_readw(addr) snd_hdac_aligned_read(addr, 0xffff)
#else /* CONFIG_SND_HDA_ALIGNED_MMIO */
#define snd_hdac_reg_writeb(val, addr) writeb(val, addr)
#define snd_hdac_reg_writew(val, addr) writew(val, addr)
#define snd_hdac_reg_readb(addr) readb(addr)
#define snd_hdac_reg_readw(addr) readw(addr)
#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
#define snd_hdac_reg_writel(val, addr) writel(val, addr)
#define snd_hdac_reg_readl(addr) readl(addr)
/* /*
* macros for easy use * macros for easy use
*/ */
#define _snd_hdac_chip_writeb(chip, reg, value) \ #define _snd_hdac_chip_writeb(chip, reg, value) \
((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readb(chip, reg) \ #define _snd_hdac_chip_readb(chip, reg) \
((chip)->io_ops->reg_readb((chip)->remap_addr + (reg))) snd_hdac_reg_readb((chip)->remap_addr + (reg))
#define _snd_hdac_chip_writew(chip, reg, value) \ #define _snd_hdac_chip_writew(chip, reg, value) \
((chip)->io_ops->reg_writew(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writew(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readw(chip, reg) \ #define _snd_hdac_chip_readw(chip, reg) \
((chip)->io_ops->reg_readw((chip)->remap_addr + (reg))) snd_hdac_reg_readw((chip)->remap_addr + (reg))
#define _snd_hdac_chip_writel(chip, reg, value) \ #define _snd_hdac_chip_writel(chip, reg, value) \
((chip)->io_ops->reg_writel(value, (chip)->remap_addr + (reg))) snd_hdac_reg_writel(value, (chip)->remap_addr + (reg))
#define _snd_hdac_chip_readl(chip, reg) \ #define _snd_hdac_chip_readl(chip, reg) \
((chip)->io_ops->reg_readl((chip)->remap_addr + (reg))) snd_hdac_reg_readl((chip)->remap_addr + (reg))
/* read/write a register, pass without AZX_REG_ prefix */ /* read/write a register, pass without AZX_REG_ prefix */
#define snd_hdac_chip_writel(chip, reg, value) \ #define snd_hdac_chip_writel(chip, reg, value) \
...@@ -548,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, ...@@ -548,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
/* /*
* macros for easy use * macros for easy use
*/ */
#define _snd_hdac_stream_write(type, dev, reg, value) \
((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg)))
#define _snd_hdac_stream_read(type, dev, reg) \
((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg)))
/* read/write a register, pass without AZX_REG_ prefix */ /* read/write a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_writel(dev, reg, value) \ #define snd_hdac_stream_writel(dev, reg, value) \
_snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_writew(dev, reg, value) \ #define snd_hdac_stream_writew(dev, reg, value) \
_snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_writeb(dev, reg, value) \ #define snd_hdac_stream_writeb(dev, reg, value) \
_snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readl(dev, reg) \ #define snd_hdac_stream_readl(dev, reg) \
_snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readw(dev, reg) \ #define snd_hdac_stream_readw(dev, reg) \
_snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readb(dev, reg) \ #define snd_hdac_stream_readb(dev, reg) \
_snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg)
/* update a register, pass without AZX_REG_ prefix */ /* update a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_updatel(dev, reg, mask, val) \ #define snd_hdac_stream_updatel(dev, reg, mask, val) \
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops); const struct hdac_ext_bus_ops *ext_ops);
void snd_hdac_ext_bus_exit(struct hdac_bus *bus); void snd_hdac_ext_bus_exit(struct hdac_bus *bus);
......
...@@ -6,6 +6,9 @@ config SND_HDA_CORE ...@@ -6,6 +6,9 @@ config SND_HDA_CORE
config SND_HDA_DSP_LOADER config SND_HDA_DSP_LOADER
bool bool
config SND_HDA_ALIGNED_MMIO
bool
config SND_HDA_COMPONENT config SND_HDA_COMPONENT
bool bool
......
...@@ -17,80 +17,22 @@ ...@@ -17,80 +17,22 @@
MODULE_DESCRIPTION("HDA extended core"); MODULE_DESCRIPTION("HDA extended core");
MODULE_LICENSE("GPL v2"); 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 int hdac_ext_dma_alloc_pages(struct hdac_bus *bus, int type,
size_t size, struct snd_dma_buffer *buf)
{
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void hdac_ext_dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
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,
.dma_alloc_pages = hdac_ext_dma_alloc_pages,
.dma_free_pages = hdac_ext_dma_free_pages,
};
/** /**
* snd_hdac_ext_bus_init - initialize a HD-audio extended bus * snd_hdac_ext_bus_init - initialize a HD-audio extended bus
* @ebus: the pointer to extended bus object * @ebus: the pointer to extended bus object
* @dev: device pointer * @dev: device pointer
* @ops: bus verb operators * @ops: bus verb operators
* @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use
* default ops * default ops
* *
* Returns 0 if successful, or a negative error code. * Returns 0 if successful, or a negative error code.
*/ */
int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops,
const struct hdac_io_ops *io_ops,
const struct hdac_ext_bus_ops *ext_ops) const struct hdac_ext_bus_ops *ext_ops)
{ {
int ret; int ret;
/* check if io ops are provided, if not load the defaults */ ret = snd_hdac_bus_init(bus, dev, ops);
if (io_ops == NULL)
io_ops = &hdac_ext_default_io;
ret = snd_hdac_bus_init(bus, dev, ops, io_ops);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -19,13 +19,11 @@ static const struct hdac_bus_ops default_ops = { ...@@ -19,13 +19,11 @@ static const struct hdac_bus_ops default_ops = {
* snd_hdac_bus_init - initialize a HD-audio bas bus * snd_hdac_bus_init - initialize a HD-audio bas bus
* @bus: the pointer to bus object * @bus: the pointer to bus object
* @ops: bus verb operators * @ops: bus verb operators
* @io_ops: lowlevel I/O operators
* *
* Returns 0 if successful, or a negative error code. * Returns 0 if successful, or a negative error code.
*/ */
int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_bus_ops *ops, const struct hdac_bus_ops *ops)
const struct hdac_io_ops *io_ops)
{ {
memset(bus, 0, sizeof(*bus)); memset(bus, 0, sizeof(*bus));
bus->dev = dev; bus->dev = dev;
...@@ -33,7 +31,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, ...@@ -33,7 +31,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
bus->ops = ops; bus->ops = ops;
else else
bus->ops = &default_ops; 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->stream_list);
INIT_LIST_HEAD(&bus->codec_list); INIT_LIST_HEAD(&bus->codec_list);
INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events);
...@@ -217,3 +215,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, ...@@ -217,3 +215,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus,
flush_work(&bus->unsol_work); flush_work(&bus->unsol_work);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); 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 */
...@@ -575,11 +575,12 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) ...@@ -575,11 +575,12 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
{ {
struct hdac_stream *s; struct hdac_stream *s;
int num_streams = 0; int num_streams = 0;
int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV;
int err; int err;
list_for_each_entry(s, &bus->stream_list, list) { list_for_each_entry(s, &bus->stream_list, list) {
/* allocate memory for the BDL for each stream */ /* allocate memory for the BDL for each stream */
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, err = snd_dma_alloc_pages(dma_type, bus->dev,
BDL_SIZE, &s->bdl); BDL_SIZE, &s->bdl);
num_streams++; num_streams++;
if (err < 0) if (err < 0)
...@@ -589,7 +590,7 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) ...@@ -589,7 +590,7 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
if (WARN_ON(!num_streams)) if (WARN_ON(!num_streams))
return -EINVAL; return -EINVAL;
/* allocate memory for the position buffer */ /* allocate memory for the position buffer */
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, err = snd_dma_alloc_pages(dma_type, bus->dev,
num_streams * 8, &bus->posbuf); num_streams * 8, &bus->posbuf);
if (err < 0) if (err < 0)
return -ENOMEM; return -ENOMEM;
...@@ -597,8 +598,7 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) ...@@ -597,8 +598,7 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8);
/* single page (at least 4096 bytes) must suffice for both ringbuffes */ /* single page (at least 4096 bytes) must suffice for both ringbuffes */
return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
PAGE_SIZE, &bus->rb);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
...@@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) ...@@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
list_for_each_entry(s, &bus->stream_list, list) { list_for_each_entry(s, &bus->stream_list, list) {
if (s->bdl.area) if (s->bdl.area)
bus->io_ops->dma_free_pages(bus, &s->bdl); snd_dma_free_pages(&s->bdl);
} }
if (bus->rb.area) if (bus->rb.area)
bus->io_ops->dma_free_pages(bus, &bus->rb); snd_dma_free_pages(&bus->rb);
if (bus->posbuf.area) if (bus->posbuf.area)
bus->io_ops->dma_free_pages(bus, &bus->posbuf); snd_dma_free_pages(&bus->posbuf);
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);
...@@ -680,7 +680,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, ...@@ -680,7 +680,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
azx_dev->locked = true; azx_dev->locked = true;
spin_unlock_irq(&bus->reg_lock); spin_unlock_irq(&bus->reg_lock);
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev,
byte_size, bufp); byte_size, bufp);
if (err < 0) if (err < 0)
goto err_alloc; goto err_alloc;
...@@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, ...@@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
return azx_dev->stream_tag; return azx_dev->stream_tag;
error: error:
bus->io_ops->dma_free_pages(bus, bufp); snd_dma_free_pages(bufp);
err_alloc: err_alloc:
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
azx_dev->locked = false; azx_dev->locked = false;
...@@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, ...@@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
azx_dev->period_bytes = 0; azx_dev->period_bytes = 0;
azx_dev->format_val = 0; azx_dev->format_val = 0;
bus->io_ops->dma_free_pages(bus, dmab); snd_dma_free_pages(dmab);
dmab->area = NULL; dmab->area = NULL;
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
......
...@@ -36,6 +36,7 @@ config SND_HDA_TEGRA ...@@ -36,6 +36,7 @@ config SND_HDA_TEGRA
tristate "NVIDIA Tegra HD Audio" tristate "NVIDIA Tegra HD Audio"
depends on ARCH_TEGRA depends on ARCH_TEGRA
select SND_HDA select SND_HDA
select SND_HDA_ALIGNED_MMIO
help help
Say Y here to support the HDA controller present in NVIDIA Say Y here to support the HDA controller present in NVIDIA
Tegra SoCs Tegra SoCs
......
...@@ -1202,14 +1202,12 @@ void snd_hda_bus_reset(struct hda_bus *bus) ...@@ -1202,14 +1202,12 @@ void snd_hda_bus_reset(struct hda_bus *bus)
} }
/* HD-audio bus initialization */ /* HD-audio bus initialization */
int azx_bus_init(struct azx *chip, const char *model, int azx_bus_init(struct azx *chip, const char *model)
const struct hdac_io_ops *io_ops)
{ {
struct hda_bus *bus = &chip->bus; struct hda_bus *bus = &chip->bus;
int err; int err;
err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops);
io_ops);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip); ...@@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip);
irqreturn_t azx_interrupt(int irq, void *dev_id); irqreturn_t azx_interrupt(int irq, void *dev_id);
/* Codec interface */ /* Codec interface */
int azx_bus_init(struct azx *chip, const char *model, int azx_bus_init(struct azx *chip, const char *model);
const struct hdac_io_ops *io_ops);
int azx_probe_codecs(struct azx *chip, unsigned int max_slots); int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
int azx_codec_configure(struct azx *chip); int azx_codec_configure(struct azx *chip);
int azx_init_streams(struct azx *chip); int azx_init_streams(struct azx *chip);
......
...@@ -1631,7 +1631,6 @@ static int default_bdl_pos_adj(struct azx *chip) ...@@ -1631,7 +1631,6 @@ static int default_bdl_pos_adj(struct azx *chip)
/* /*
* constructor * constructor
*/ */
static const struct hdac_io_ops pci_hda_io_ops;
static const struct hda_controller_ops pci_hda_ops; static const struct hda_controller_ops pci_hda_ops;
static int azx_create(struct snd_card *card, struct pci_dev *pci, static int azx_create(struct snd_card *card, struct pci_dev *pci,
...@@ -1691,13 +1690,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1691,13 +1690,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
else else
chip->bdl_pos_adj = bdl_pos_adj[dev]; chip->bdl_pos_adj = bdl_pos_adj[dev];
err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); err = azx_bus_init(chip, model[dev]);
if (err < 0) { if (err < 0) {
kfree(hda); kfree(hda);
pci_disable_device(pci); pci_disable_device(pci);
return err; return err;
} }
/* use the non-cached pages in non-snoop mode */
if (!azx_snoop(chip))
azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
/* Workaround for a communication error on CFL (bko#199007) and CNL */ /* Workaround for a communication error on CFL (bko#199007) and CNL */
if (IS_CFL(pci) || IS_CNL(pci)) if (IS_CFL(pci) || IS_CNL(pci))
azx_bus(chip)->polling_mode = 1; azx_bus(chip)->polling_mode = 1;
...@@ -1932,41 +1935,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) ...@@ -1932,41 +1935,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
} }
#endif #endif
/*
* HDA controller ops.
*/
/* PCI register access. */
static void pci_azx_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 pci_azx_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void pci_azx_writew(u16 value, u16 __iomem *addr)
{
writew(value, addr);
}
static u16 pci_azx_readw(u16 __iomem *addr)
{
return readw(addr);
}
static void pci_azx_writeb(u8 value, u8 __iomem *addr)
{
writeb(value, addr);
}
static u8 pci_azx_readb(u8 __iomem *addr)
{
return readb(addr);
}
static int disable_msi_reset_irq(struct azx *chip) static int disable_msi_reset_irq(struct azx *chip)
{ {
struct hdac_bus *bus = azx_bus(chip); struct hdac_bus *bus = azx_bus(chip);
...@@ -1983,24 +1951,6 @@ static int disable_msi_reset_irq(struct azx *chip) ...@@ -1983,24 +1951,6 @@ static int disable_msi_reset_irq(struct azx *chip)
return 0; return 0;
} }
/* DMA page allocation helpers. */
static int dma_alloc_pages(struct hdac_bus *bus,
int type,
size_t size,
struct snd_dma_buffer *buf)
{
struct azx *chip = bus_to_azx(bus);
if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV)
type = SNDRV_DMA_TYPE_DEV_UC;
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
static void pcm_mmap_prepare(struct snd_pcm_substream *substream, static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
...@@ -2012,17 +1962,6 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, ...@@ -2012,17 +1962,6 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
#endif #endif
} }
static const struct hdac_io_ops pci_hda_io_ops = {
.reg_writel = pci_azx_writel,
.reg_readl = pci_azx_readl,
.reg_writew = pci_azx_writew,
.reg_readw = pci_azx_readw,
.reg_writeb = pci_azx_writeb,
.reg_readb = pci_azx_readb,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
};
static const struct hda_controller_ops pci_hda_ops = { static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq, .disable_msi_reset_irq = disable_msi_reset_irq,
.pcm_mmap_prepare = pcm_mmap_prepare, .pcm_mmap_prepare = pcm_mmap_prepare,
......
...@@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save, ...@@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save,
#define power_save 0 #define power_save 0
#endif #endif
/*
* DMA page allocation ops.
*/
static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size,
struct snd_dma_buffer *buf)
{
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
/*
* Register access ops. Tegra HDA register access is DWORD only.
*/
static void hda_tegra_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 hda_tegra_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void hda_tegra_writew(u16 value, u16 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
v &= ~(0xffff << shift);
v |= value << shift;
writel(v, dword_addr);
}
static u16 hda_tegra_readw(u16 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
return (v >> shift) & 0xffff;
}
static void hda_tegra_writeb(u8 value, u8 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
v &= ~(0xff << shift);
v |= value << shift;
writel(v, dword_addr);
}
static u8 hda_tegra_readb(u8 __iomem *addr)
{
unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
u32 v;
v = readl(dword_addr);
return (v >> shift) & 0xff;
}
static const struct hdac_io_ops hda_tegra_io_ops = {
.reg_writel = hda_tegra_writel,
.reg_readl = hda_tegra_readl,
.reg_writew = hda_tegra_writew,
.reg_readw = hda_tegra_readw,
.reg_writeb = hda_tegra_writeb,
.reg_readb = hda_tegra_readb,
.dma_alloc_pages = dma_alloc_pages,
.dma_free_pages = dma_free_pages,
};
static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ static const struct hda_controller_ops hda_tegra_ops; /* nothing special */
static void hda_tegra_init(struct hda_tegra *hda) static void hda_tegra_init(struct hda_tegra *hda)
...@@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card, ...@@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card,
INIT_WORK(&hda->probe_work, hda_tegra_probe_work); INIT_WORK(&hda->probe_work, hda_tegra_probe_work);
err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); err = azx_bus_init(chip, NULL);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -25,23 +25,12 @@ ...@@ -25,23 +25,12 @@
static int skl_alloc_dma_buf(struct device *dev, static int skl_alloc_dma_buf(struct device *dev,
struct snd_dma_buffer *dmab, size_t size) struct snd_dma_buffer *dmab, size_t size)
{ {
struct hdac_bus *bus = dev_get_drvdata(dev); return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, dmab);
if (!bus)
return -ENODEV;
return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab);
} }
static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
{ {
struct hdac_bus *bus = dev_get_drvdata(dev); snd_dma_free_pages(dmab);
if (!bus)
return -ENODEV;
bus->io_ops->dma_free_pages(bus, dmab);
return 0; return 0;
} }
......
...@@ -134,7 +134,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) ...@@ -134,7 +134,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
/* Reset stream-to-link mapping */ /* Reset stream-to-link mapping */
list_for_each_entry(hlink, &bus->hlink_list, list) list_for_each_entry(hlink, &bus->hlink_list, list)
bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
skl_enable_miscbdcge(bus->dev, true); skl_enable_miscbdcge(bus->dev, true);
...@@ -858,7 +858,6 @@ static void skl_probe_work(struct work_struct *work) ...@@ -858,7 +858,6 @@ static void skl_probe_work(struct work_struct *work)
* constructor * constructor
*/ */
static int skl_create(struct pci_dev *pci, static int skl_create(struct pci_dev *pci,
const struct hdac_io_ops *io_ops,
struct skl_dev **rskl) struct skl_dev **rskl)
{ {
struct hdac_ext_bus_ops *ext_ops = NULL; struct hdac_ext_bus_ops *ext_ops = NULL;
...@@ -888,7 +887,7 @@ static int skl_create(struct pci_dev *pci, ...@@ -888,7 +887,7 @@ static int skl_create(struct pci_dev *pci,
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
ext_ops = snd_soc_hdac_hda_get_ops(); ext_ops = snd_soc_hdac_hda_get_ops();
#endif #endif
snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops); snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, ext_ops);
bus->use_posbuf = 1; bus->use_posbuf = 1;
skl->pci = pci; skl->pci = pci;
INIT_WORK(&skl->probe_work, skl_probe_work); INIT_WORK(&skl->probe_work, skl_probe_work);
...@@ -1017,7 +1016,7 @@ static int skl_probe(struct pci_dev *pci, ...@@ -1017,7 +1016,7 @@ static int skl_probe(struct pci_dev *pci,
} }
/* we use ext core ops, so provide NULL for ops here */ /* we use ext core ops, so provide NULL for ops here */
err = skl_create(pci, NULL, &skl); err = skl_create(pci, &skl);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -12,82 +12,26 @@ ...@@ -12,82 +12,26 @@
#include "../sof-priv.h" #include "../sof-priv.h"
#include "hda.h" #include "hda.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
#define sof_hda_ext_ops snd_soc_hdac_hda_get_ops()
static const struct hdac_bus_ops bus_ops = { #else
.command = snd_hdac_bus_send_cmd, #define sof_hda_ext_ops NULL
.get_response = snd_hdac_bus_get_response,
};
#endif #endif
static void sof_hda_writel(u32 value, u32 __iomem *addr)
{
writel(value, addr);
}
static u32 sof_hda_readl(u32 __iomem *addr)
{
return readl(addr);
}
static void sof_hda_writew(u16 value, u16 __iomem *addr)
{
writew(value, addr);
}
static u16 sof_hda_readw(u16 __iomem *addr)
{
return readw(addr);
}
static void sof_hda_writeb(u8 value, u8 __iomem *addr)
{
writeb(value, addr);
}
static u8 sof_hda_readb(u8 __iomem *addr)
{
return readb(addr);
}
static int sof_hda_dma_alloc_pages(struct hdac_bus *bus, int type,
size_t size, struct snd_dma_buffer *buf)
{
return snd_dma_alloc_pages(type, bus->dev, size, buf);
}
static void sof_hda_dma_free_pages(struct hdac_bus *bus,
struct snd_dma_buffer *buf)
{
snd_dma_free_pages(buf);
}
static const struct hdac_io_ops io_ops = {
.reg_writel = sof_hda_writel,
.reg_readl = sof_hda_readl,
.reg_writew = sof_hda_writew,
.reg_readw = sof_hda_readw,
.reg_writeb = sof_hda_writeb,
.reg_readb = sof_hda_readb,
.dma_alloc_pages = sof_hda_dma_alloc_pages,
.dma_free_pages = sof_hda_dma_free_pages,
};
/* /*
* This can be used for both with/without hda link support. * This can be used for both with/without hda link support.
*/ */
void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev)
const struct hdac_ext_bus_ops *ext_ops)
{ {
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops);
#else /* CONFIG_SND_SOC_SOF_HDA */
memset(bus, 0, sizeof(*bus)); memset(bus, 0, sizeof(*bus));
bus->dev = dev; bus->dev = dev;
bus->io_ops = &io_ops;
INIT_LIST_HEAD(&bus->stream_list); INIT_LIST_HEAD(&bus->stream_list);
bus->irq = -1; bus->irq = -1;
bus->ext_ops = ext_ops;
/* /*
* There is only one HDA bus atm. keep the index as 0. * There is only one HDA bus atm. keep the index as 0.
...@@ -96,16 +40,5 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, ...@@ -96,16 +40,5 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev,
bus->idx = 0; bus->idx = 0;
spin_lock_init(&bus->reg_lock); spin_lock_init(&bus->reg_lock);
#endif /* CONFIG_SND_SOC_SOF_HDA */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
INIT_LIST_HEAD(&bus->codec_list);
INIT_LIST_HEAD(&bus->hlink_list);
mutex_init(&bus->cmd_mutex);
mutex_init(&bus->lock);
bus->ops = &bus_ops;
INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events);
bus->cmd_dma_state = true;
#endif
} }
...@@ -354,6 +354,45 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) ...@@ -354,6 +354,45 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
return ret; return ret;
} }
hda_dsp_ctrl_misc_clock_gating(sdev, false);
/* Reset stream-to-link mapping */
list_for_each_entry(hlink, &bus->hlink_list, list)
writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
hda_dsp_ctrl_misc_clock_gating(sdev, true);
#else
hda_dsp_ctrl_misc_clock_gating(sdev, false);
/* reset controller */
ret = hda_dsp_ctrl_link_reset(sdev, true);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to reset controller during resume\n");
return ret;
}
/* take controller out of reset */
ret = hda_dsp_ctrl_link_reset(sdev, false);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to ready controller during resume\n");
return ret;
}
/* enable hda bus irq */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
hda_dsp_ctrl_misc_clock_gating(sdev, true);
#endif
/* enable ppcap interrupt */
hda_dsp_ctrl_ppcap_enable(sdev, true);
hda_dsp_ctrl_ppcap_int_enable(sdev, true);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* check jack status */ /* check jack status */
if (runtime_resume) if (runtime_resume)
......
...@@ -242,7 +242,6 @@ static int hda_init(struct snd_sof_dev *sdev) ...@@ -242,7 +242,6 @@ static int hda_init(struct snd_sof_dev *sdev)
{ {
struct hda_bus *hbus; struct hda_bus *hbus;
struct hdac_bus *bus; struct hdac_bus *bus;
struct hdac_ext_bus_ops *ext_ops = NULL;
struct pci_dev *pci = to_pci_dev(sdev->dev); struct pci_dev *pci = to_pci_dev(sdev->dev);
int ret; int ret;
...@@ -250,10 +249,7 @@ static int hda_init(struct snd_sof_dev *sdev) ...@@ -250,10 +249,7 @@ static int hda_init(struct snd_sof_dev *sdev)
bus = sof_to_bus(sdev); bus = sof_to_bus(sdev);
/* HDA bus init */ /* HDA bus init */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) sof_hda_bus_init(bus, &pci->dev);
ext_ops = snd_soc_hdac_hda_get_ops();
#endif
sof_hda_bus_init(bus, &pci->dev, ext_ops);
/* Workaround for a communication error on CFL (bko#199007) and CNL */ /* Workaround for a communication error on CFL (bko#199007) and CNL */
if (IS_CFL(pci) || IS_CNL(pci)) if (IS_CFL(pci) || IS_CNL(pci))
......
...@@ -548,8 +548,7 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); ...@@ -548,8 +548,7 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev);
/* /*
* HDA bus operations. * HDA bus operations.
*/ */
void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev);
const struct hdac_ext_bus_ops *ext_ops);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment