ALSA: hda - Add DSP loader to core library code
Copied from the legacy driver code, no transition done yet. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -187,6 +187,11 @@ struct hdac_io_ops {
|
|||||||
u16 (*reg_readw)(u16 __iomem *addr);
|
u16 (*reg_readw)(u16 __iomem *addr);
|
||||||
void (*reg_writeb)(u8 value, u8 __iomem *addr);
|
void (*reg_writeb)(u8 value, u8 __iomem *addr);
|
||||||
u8 (*reg_readb)(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
|
||||||
@@ -374,6 +379,7 @@ struct hdac_stream {
|
|||||||
bool opened:1;
|
bool opened:1;
|
||||||
bool running:1;
|
bool running:1;
|
||||||
bool no_period_wakeup:1;
|
bool no_period_wakeup:1;
|
||||||
|
bool locked:1;
|
||||||
|
|
||||||
/* timestamp */
|
/* timestamp */
|
||||||
unsigned long start_wallclk; /* start + minimum wallclk */
|
unsigned long start_wallclk; /* start + minimum wallclk */
|
||||||
@@ -383,6 +389,10 @@ struct hdac_stream {
|
|||||||
int delay_negative_threshold;
|
int delay_negative_threshold;
|
||||||
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
|
/* DSP access mutex */
|
||||||
|
struct mutex dsp_mutex;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
|
void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
|
||||||
@@ -440,6 +450,42 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
|
|||||||
(snd_hdac_stream_readb(dev, reg) & \
|
(snd_hdac_stream_readb(dev, reg) & \
|
||||||
~(mask)) | (val))
|
~(mask)) | (val))
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
|
/* DSP lock helpers */
|
||||||
|
#define snd_hdac_dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex)
|
||||||
|
#define snd_hdac_dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex)
|
||||||
|
#define snd_hdac_dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex)
|
||||||
|
#define snd_hdac_stream_is_locked(dev) ((dev)->locked)
|
||||||
|
/* DSP loader helpers */
|
||||||
|
int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
|
||||||
|
unsigned int byte_size, struct snd_dma_buffer *bufp);
|
||||||
|
void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start);
|
||||||
|
void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
|
||||||
|
struct snd_dma_buffer *dmab);
|
||||||
|
#else /* CONFIG_SND_HDA_DSP_LOADER */
|
||||||
|
#define snd_hdac_dsp_lock_init(dev) do {} while (0)
|
||||||
|
#define snd_hdac_dsp_lock(dev) do {} while (0)
|
||||||
|
#define snd_hdac_dsp_unlock(dev) do {} while (0)
|
||||||
|
#define snd_hdac_stream_is_locked(dev) 0
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
|
||||||
|
unsigned int byte_size, struct snd_dma_buffer *bufp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
|
||||||
|
struct snd_dma_buffer *dmab)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SND_HDA_DSP_LOADER */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generic array helpers
|
* generic array helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
config SND_HDA_CORE
|
config SND_HDA_CORE
|
||||||
tristate
|
tristate
|
||||||
select REGMAP
|
select REGMAP
|
||||||
|
|
||||||
|
config SND_HDA_DSP_LOADER
|
||||||
|
bool
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
|
|||||||
azx_dev->index = idx;
|
azx_dev->index = idx;
|
||||||
azx_dev->direction = direction;
|
azx_dev->direction = direction;
|
||||||
azx_dev->stream_tag = tag;
|
azx_dev->stream_tag = tag;
|
||||||
|
snd_hdac_dsp_lock_init(azx_dev);
|
||||||
list_add_tail(&azx_dev->list, &bus->stream_list);
|
list_add_tail(&azx_dev->list, &bus->stream_list);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hdac_stream_init);
|
EXPORT_SYMBOL_GPL(snd_hdac_stream_init);
|
||||||
@@ -534,3 +535,115 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hdac_stream_sync);
|
EXPORT_SYMBOL_GPL(snd_hdac_stream_sync);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
|
/**
|
||||||
|
* snd_hdac_dsp_prepare - prepare for DSP loading
|
||||||
|
* @azx_dev: HD-audio core stream used for DSP loading
|
||||||
|
* @format: HD-audio stream format
|
||||||
|
* @byte_size: data chunk byte size
|
||||||
|
* @bufp: allocated buffer
|
||||||
|
*
|
||||||
|
* Allocate the buffer for the given size and set up the given stream for
|
||||||
|
* DSP loading. Returns the stream tag (>= 0), or a negative error code.
|
||||||
|
*/
|
||||||
|
int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
|
||||||
|
unsigned int byte_size, struct snd_dma_buffer *bufp)
|
||||||
|
{
|
||||||
|
struct hdac_bus *bus = azx_dev->bus;
|
||||||
|
u32 *bdl;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
snd_hdac_dsp_lock(azx_dev);
|
||||||
|
spin_lock_irq(&bus->reg_lock);
|
||||||
|
if (azx_dev->running || azx_dev->locked) {
|
||||||
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
|
err = -EBUSY;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
azx_dev->locked = true;
|
||||||
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
|
|
||||||
|
err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG,
|
||||||
|
byte_size, bufp);
|
||||||
|
if (err < 0)
|
||||||
|
goto err_alloc;
|
||||||
|
|
||||||
|
azx_dev->bufsize = byte_size;
|
||||||
|
azx_dev->period_bytes = byte_size;
|
||||||
|
azx_dev->format_val = format;
|
||||||
|
|
||||||
|
snd_hdac_stream_reset(azx_dev);
|
||||||
|
|
||||||
|
/* reset BDL address */
|
||||||
|
snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
|
||||||
|
snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
|
||||||
|
|
||||||
|
azx_dev->frags = 0;
|
||||||
|
bdl = (u32 *)azx_dev->bdl.area;
|
||||||
|
err = setup_bdle(bus, bufp, azx_dev, &bdl, 0, byte_size, 0);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
snd_hdac_stream_setup(azx_dev);
|
||||||
|
snd_hdac_dsp_unlock(azx_dev);
|
||||||
|
return azx_dev->stream_tag;
|
||||||
|
|
||||||
|
error:
|
||||||
|
bus->io_ops->dma_free_pages(bus, bufp);
|
||||||
|
err_alloc:
|
||||||
|
spin_lock_irq(&bus->reg_lock);
|
||||||
|
azx_dev->locked = false;
|
||||||
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
|
unlock:
|
||||||
|
snd_hdac_dsp_unlock(azx_dev);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_dsp_prepare);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hdac_dsp_trigger - start / stop DSP loading
|
||||||
|
* @azx_dev: HD-audio core stream used for DSP loading
|
||||||
|
* @start: trigger start or stop
|
||||||
|
*/
|
||||||
|
void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start)
|
||||||
|
{
|
||||||
|
if (start)
|
||||||
|
snd_hdac_stream_start(azx_dev, true);
|
||||||
|
else
|
||||||
|
snd_hdac_stream_stop(azx_dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_dsp_trigger);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal
|
||||||
|
* @azx_dev: HD-audio core stream used for DSP loading
|
||||||
|
* @dmab: buffer used by DSP loading
|
||||||
|
*/
|
||||||
|
void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
|
||||||
|
struct snd_dma_buffer *dmab)
|
||||||
|
{
|
||||||
|
struct hdac_bus *bus = azx_dev->bus;
|
||||||
|
|
||||||
|
if (!dmab->area || !azx_dev->locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
snd_hdac_dsp_lock(azx_dev);
|
||||||
|
/* reset BDL address */
|
||||||
|
snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
|
||||||
|
snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
|
||||||
|
snd_hdac_stream_writel(azx_dev, SD_CTL, 0);
|
||||||
|
azx_dev->bufsize = 0;
|
||||||
|
azx_dev->period_bytes = 0;
|
||||||
|
azx_dev->format_val = 0;
|
||||||
|
|
||||||
|
bus->io_ops->dma_free_pages(bus, dmab);
|
||||||
|
dmab->area = NULL;
|
||||||
|
|
||||||
|
spin_lock_irq(&bus->reg_lock);
|
||||||
|
azx_dev->locked = false;
|
||||||
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
|
snd_hdac_dsp_unlock(azx_dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_dsp_cleanup);
|
||||||
|
#endif /* CONFIG_SND_HDA_DSP_LOADER */
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ config SND_HDA_TEGRA
|
|||||||
|
|
||||||
if SND_HDA
|
if SND_HDA
|
||||||
|
|
||||||
config SND_HDA_DSP_LOADER
|
|
||||||
bool
|
|
||||||
|
|
||||||
config SND_HDA_PREALLOC_SIZE
|
config SND_HDA_PREALLOC_SIZE
|
||||||
int "Pre-allocated buffer size for HD-audio driver"
|
int "Pre-allocated buffer size for HD-audio driver"
|
||||||
range 0 32768
|
range 0 32768
|
||||||
|
|||||||
Reference in New Issue
Block a user