ALSA: hda - Move the dsp loader to hda_controller
Moving the DSP loading functionality to hda_controller.c means that the dsp lock doesn't need to be shared in hda_intel and hda_controller. The forthcoming platform driver doesn't need the DSP loading code, but sharing it doesn't hurt. Tested on Chromebook Pixel's ca0132 that uses the DSP loader. Signed-off-by: Dylan Reid <dgreid@chromium.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6790899443
commit
2b5fd6c2e9
3 changed files with 144 additions and 152 deletions
|
@ -33,12 +33,25 @@
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "hda_intel_trace.h"
|
#include "hda_intel_trace.h"
|
||||||
|
|
||||||
|
/* DSP lock helpers */
|
||||||
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
|
#define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex)
|
||||||
|
#define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex)
|
||||||
|
#define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex)
|
||||||
|
#define dsp_is_locked(dev) ((dev)->locked)
|
||||||
|
#else
|
||||||
|
#define dsp_lock_init(dev) do {} while (0)
|
||||||
|
#define dsp_lock(dev) do {} while (0)
|
||||||
|
#define dsp_unlock(dev) do {} while (0)
|
||||||
|
#define dsp_is_locked(dev) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AZX stream operations.
|
* AZX stream operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* start a stream */
|
/* start a stream */
|
||||||
void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
|
static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Before stream start, initialize parameter
|
* Before stream start, initialize parameter
|
||||||
|
@ -53,7 +66,6 @@ void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
azx_sd_readb(chip, azx_dev, SD_CTL) |
|
azx_sd_readb(chip, azx_dev, SD_CTL) |
|
||||||
SD_CTL_DMA_START | SD_INT_MASK);
|
SD_CTL_DMA_START | SD_INT_MASK);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(azx_stream_start);
|
|
||||||
|
|
||||||
/* stop DMA */
|
/* stop DMA */
|
||||||
static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
|
static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
|
@ -75,7 +87,7 @@ void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
EXPORT_SYMBOL_GPL(azx_stream_stop);
|
EXPORT_SYMBOL_GPL(azx_stream_stop);
|
||||||
|
|
||||||
/* reset stream */
|
/* reset stream */
|
||||||
void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
|
static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
{
|
{
|
||||||
unsigned char val;
|
unsigned char val;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@ -103,12 +115,11 @@ void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
/* reset first position - may not be synced with hw at this time */
|
/* reset first position - may not be synced with hw at this time */
|
||||||
*azx_dev->posbuf = 0;
|
*azx_dev->posbuf = 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(azx_stream_reset);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set up the SD for streaming
|
* set up the SD for streaming
|
||||||
*/
|
*/
|
||||||
int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
{
|
{
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
/* make sure the run bit is zero for SD */
|
/* make sure the run bit is zero for SD */
|
||||||
|
@ -152,7 +163,6 @@ int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(azx_setup_controller);
|
|
||||||
|
|
||||||
/* assign a stream for the PCM */
|
/* assign a stream for the PCM */
|
||||||
static inline struct azx_dev *
|
static inline struct azx_dev *
|
||||||
|
@ -267,10 +277,10 @@ static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
|
||||||
/*
|
/*
|
||||||
* set up a BDL entry
|
* set up a BDL entry
|
||||||
*/
|
*/
|
||||||
int setup_bdle(struct azx *chip,
|
static int setup_bdle(struct azx *chip,
|
||||||
struct snd_dma_buffer *dmab,
|
struct snd_dma_buffer *dmab,
|
||||||
struct azx_dev *azx_dev, u32 **bdlp,
|
struct azx_dev *azx_dev, u32 **bdlp,
|
||||||
int ofs, int size, int with_ioc)
|
int ofs, int size, int with_ioc)
|
||||||
{
|
{
|
||||||
u32 *bdl = *bdlp;
|
u32 *bdl = *bdlp;
|
||||||
|
|
||||||
|
@ -306,7 +316,6 @@ int setup_bdle(struct azx *chip,
|
||||||
*bdlp = bdl;
|
*bdlp = bdl;
|
||||||
return ofs;
|
return ofs;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(setup_bdle);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set up BDL entries
|
* set up BDL entries
|
||||||
|
@ -1014,6 +1023,124 @@ int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(azx_attach_pcm_stream);
|
EXPORT_SYMBOL_GPL(azx_attach_pcm_stream);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
|
/*
|
||||||
|
* DSP loading code (e.g. for CA0132)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* use the first stream for loading DSP */
|
||||||
|
static struct azx_dev *
|
||||||
|
azx_get_dsp_loader_dev(struct azx *chip)
|
||||||
|
{
|
||||||
|
return &chip->azx_dev[chip->playback_index_offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
||||||
|
unsigned int byte_size,
|
||||||
|
struct snd_dma_buffer *bufp)
|
||||||
|
{
|
||||||
|
u32 *bdl;
|
||||||
|
struct azx *chip = bus->private_data;
|
||||||
|
struct azx_dev *azx_dev;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
azx_dev = azx_get_dsp_loader_dev(chip);
|
||||||
|
|
||||||
|
dsp_lock(azx_dev);
|
||||||
|
spin_lock_irq(&chip->reg_lock);
|
||||||
|
if (azx_dev->running || azx_dev->locked) {
|
||||||
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
err = -EBUSY;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
azx_dev->prepared = 0;
|
||||||
|
chip->saved_azx_dev = *azx_dev;
|
||||||
|
azx_dev->locked = 1;
|
||||||
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
|
||||||
|
err = chip->ops->dma_alloc_pages(chip, 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;
|
||||||
|
|
||||||
|
azx_stream_reset(chip, azx_dev);
|
||||||
|
|
||||||
|
/* reset BDL address */
|
||||||
|
azx_sd_writel(chip, azx_dev, SD_BDLPL, 0);
|
||||||
|
azx_sd_writel(chip, azx_dev, SD_BDLPU, 0);
|
||||||
|
|
||||||
|
azx_dev->frags = 0;
|
||||||
|
bdl = (u32 *)azx_dev->bdl.area;
|
||||||
|
err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
azx_setup_controller(chip, azx_dev);
|
||||||
|
dsp_unlock(azx_dev);
|
||||||
|
return azx_dev->stream_tag;
|
||||||
|
|
||||||
|
error:
|
||||||
|
chip->ops->dma_free_pages(chip, bufp);
|
||||||
|
err_alloc:
|
||||||
|
spin_lock_irq(&chip->reg_lock);
|
||||||
|
if (azx_dev->opened)
|
||||||
|
*azx_dev = chip->saved_azx_dev;
|
||||||
|
azx_dev->locked = 0;
|
||||||
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
unlock:
|
||||||
|
dsp_unlock(azx_dev);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(azx_load_dsp_prepare);
|
||||||
|
|
||||||
|
void azx_load_dsp_trigger(struct hda_bus *bus, bool start)
|
||||||
|
{
|
||||||
|
struct azx *chip = bus->private_data;
|
||||||
|
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
||||||
|
|
||||||
|
if (start)
|
||||||
|
azx_stream_start(chip, azx_dev);
|
||||||
|
else
|
||||||
|
azx_stream_stop(chip, azx_dev);
|
||||||
|
azx_dev->running = start;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(azx_load_dsp_trigger);
|
||||||
|
|
||||||
|
void azx_load_dsp_cleanup(struct hda_bus *bus,
|
||||||
|
struct snd_dma_buffer *dmab)
|
||||||
|
{
|
||||||
|
struct azx *chip = bus->private_data;
|
||||||
|
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
||||||
|
|
||||||
|
if (!dmab->area || !azx_dev->locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dsp_lock(azx_dev);
|
||||||
|
/* reset BDL address */
|
||||||
|
azx_sd_writel(chip, azx_dev, SD_BDLPL, 0);
|
||||||
|
azx_sd_writel(chip, azx_dev, SD_BDLPU, 0);
|
||||||
|
azx_sd_writel(chip, azx_dev, SD_CTL, 0);
|
||||||
|
azx_dev->bufsize = 0;
|
||||||
|
azx_dev->period_bytes = 0;
|
||||||
|
azx_dev->format_val = 0;
|
||||||
|
|
||||||
|
chip->ops->dma_free_pages(chip, dmab);
|
||||||
|
dmab->area = NULL;
|
||||||
|
|
||||||
|
spin_lock_irq(&chip->reg_lock);
|
||||||
|
if (azx_dev->opened)
|
||||||
|
*azx_dev = chip->saved_azx_dev;
|
||||||
|
azx_dev->locked = 0;
|
||||||
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
dsp_unlock(azx_dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(azx_load_dsp_cleanup);
|
||||||
|
#endif /* CONFIG_SND_HDA_DSP_LOADER */
|
||||||
|
|
||||||
int azx_alloc_stream_pages(struct azx *chip)
|
int azx_alloc_stream_pages(struct azx *chip)
|
||||||
{
|
{
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
|
@ -32,26 +32,15 @@ unsigned int azx_get_position(struct azx *chip,
|
||||||
bool with_check);
|
bool with_check);
|
||||||
|
|
||||||
/* Stream control. */
|
/* Stream control. */
|
||||||
void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev);
|
|
||||||
void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
|
void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
|
||||||
void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev);
|
|
||||||
int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev);
|
|
||||||
int setup_bdle(struct azx *chip,
|
|
||||||
struct snd_dma_buffer *dmab,
|
|
||||||
struct azx_dev *azx_dev, u32 **bdlp,
|
|
||||||
int ofs, int size, int with_ioc);
|
|
||||||
|
|
||||||
/* DSP lock helpers */
|
|
||||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||||
#define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex)
|
int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
||||||
#define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex)
|
unsigned int byte_size,
|
||||||
#define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex)
|
struct snd_dma_buffer *bufp);
|
||||||
#define dsp_is_locked(dev) ((dev)->locked)
|
void azx_load_dsp_trigger(struct hda_bus *bus, bool start);
|
||||||
#else
|
void azx_load_dsp_cleanup(struct hda_bus *bus,
|
||||||
#define dsp_lock_init(dev) do {} while (0)
|
struct snd_dma_buffer *dmab);
|
||||||
#define dsp_lock(dev) do {} while (0)
|
|
||||||
#define dsp_unlock(dev) do {} while (0)
|
|
||||||
#define dsp_is_locked(dev) 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocation functions. */
|
/* Allocation functions. */
|
||||||
|
|
|
@ -723,15 +723,6 @@ static unsigned int azx_get_response(struct hda_bus *bus,
|
||||||
static void azx_power_notify(struct hda_bus *bus, bool power_up);
|
static void azx_power_notify(struct hda_bus *bus, bool power_up);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
|
||||||
static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
|
||||||
unsigned int byte_size,
|
|
||||||
struct snd_dma_buffer *bufp);
|
|
||||||
static void azx_load_dsp_trigger(struct hda_bus *bus, bool start);
|
|
||||||
static void azx_load_dsp_cleanup(struct hda_bus *bus,
|
|
||||||
struct snd_dma_buffer *dmab);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* enter link reset */
|
/* enter link reset */
|
||||||
static void azx_enter_link_reset(struct azx *chip)
|
static void azx_enter_link_reset(struct azx *chip)
|
||||||
{
|
{
|
||||||
|
@ -1354,121 +1345,6 @@ static void azx_stop_chip(struct azx *chip)
|
||||||
chip->initialized = 0;
|
chip->initialized = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
|
||||||
/*
|
|
||||||
* DSP loading code (e.g. for CA0132)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* use the first stream for loading DSP */
|
|
||||||
static struct azx_dev *
|
|
||||||
azx_get_dsp_loader_dev(struct azx *chip)
|
|
||||||
{
|
|
||||||
return &chip->azx_dev[chip->playback_index_offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
|
||||||
unsigned int byte_size,
|
|
||||||
struct snd_dma_buffer *bufp)
|
|
||||||
{
|
|
||||||
u32 *bdl;
|
|
||||||
struct azx *chip = bus->private_data;
|
|
||||||
struct azx_dev *azx_dev;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
azx_dev = azx_get_dsp_loader_dev(chip);
|
|
||||||
|
|
||||||
dsp_lock(azx_dev);
|
|
||||||
spin_lock_irq(&chip->reg_lock);
|
|
||||||
if (azx_dev->running || azx_dev->locked) {
|
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
|
||||||
err = -EBUSY;
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
azx_dev->prepared = 0;
|
|
||||||
chip->saved_azx_dev = *azx_dev;
|
|
||||||
azx_dev->locked = 1;
|
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
|
||||||
|
|
||||||
err = chip->ops->dma_alloc_pages(chip, 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;
|
|
||||||
|
|
||||||
azx_stream_reset(chip, azx_dev);
|
|
||||||
|
|
||||||
/* reset BDL address */
|
|
||||||
azx_sd_writel(chip, azx_dev, SD_BDLPL, 0);
|
|
||||||
azx_sd_writel(chip, azx_dev, SD_BDLPU, 0);
|
|
||||||
|
|
||||||
azx_dev->frags = 0;
|
|
||||||
bdl = (u32 *)azx_dev->bdl.area;
|
|
||||||
err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0);
|
|
||||||
if (err < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
azx_setup_controller(chip, azx_dev);
|
|
||||||
dsp_unlock(azx_dev);
|
|
||||||
return azx_dev->stream_tag;
|
|
||||||
|
|
||||||
error:
|
|
||||||
chip->ops->dma_free_pages(chip, bufp);
|
|
||||||
err_alloc:
|
|
||||||
spin_lock_irq(&chip->reg_lock);
|
|
||||||
if (azx_dev->opened)
|
|
||||||
*azx_dev = chip->saved_azx_dev;
|
|
||||||
azx_dev->locked = 0;
|
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
|
||||||
unlock:
|
|
||||||
dsp_unlock(azx_dev);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void azx_load_dsp_trigger(struct hda_bus *bus, bool start)
|
|
||||||
{
|
|
||||||
struct azx *chip = bus->private_data;
|
|
||||||
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
|
||||||
|
|
||||||
if (start)
|
|
||||||
azx_stream_start(chip, azx_dev);
|
|
||||||
else
|
|
||||||
azx_stream_stop(chip, azx_dev);
|
|
||||||
azx_dev->running = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void azx_load_dsp_cleanup(struct hda_bus *bus,
|
|
||||||
struct snd_dma_buffer *dmab)
|
|
||||||
{
|
|
||||||
struct azx *chip = bus->private_data;
|
|
||||||
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
|
||||||
|
|
||||||
if (!dmab->area || !azx_dev->locked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dsp_lock(azx_dev);
|
|
||||||
/* reset BDL address */
|
|
||||||
azx_sd_writel(chip, azx_dev, SD_BDLPL, 0);
|
|
||||||
azx_sd_writel(chip, azx_dev, SD_BDLPU, 0);
|
|
||||||
azx_sd_writel(chip, azx_dev, SD_CTL, 0);
|
|
||||||
azx_dev->bufsize = 0;
|
|
||||||
azx_dev->period_bytes = 0;
|
|
||||||
azx_dev->format_val = 0;
|
|
||||||
|
|
||||||
chip->ops->dma_free_pages(chip, dmab);
|
|
||||||
dmab->area = NULL;
|
|
||||||
|
|
||||||
spin_lock_irq(&chip->reg_lock);
|
|
||||||
if (azx_dev->opened)
|
|
||||||
*azx_dev = chip->saved_azx_dev;
|
|
||||||
azx_dev->locked = 0;
|
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
|
||||||
dsp_unlock(azx_dev);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SND_HDA_DSP_LOADER */
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
/* power-up/down the controller */
|
/* power-up/down the controller */
|
||||||
static void azx_power_notify(struct hda_bus *bus, bool power_up)
|
static void azx_power_notify(struct hda_bus *bus, bool power_up)
|
||||||
|
|
Loading…
Add table
Reference in a new issue