Commit 2b5fd6c2 authored by Dylan Reid's avatar Dylan Reid Committed by Takashi Iwai

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: default avatarDylan Reid <dgreid@chromium.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 67908994
...@@ -33,12 +33,25 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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)
......
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