Loading include/sound/hdaudio.h +46 −0 Original line number Diff line number Diff line Loading @@ -187,6 +187,11 @@ struct hdac_io_ops { 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 Loading Loading @@ -374,6 +379,7 @@ struct hdac_stream { bool opened:1; bool running:1; bool no_period_wakeup:1; bool locked:1; /* timestamp */ unsigned long start_wallclk; /* start + minimum wallclk */ Loading @@ -383,6 +389,10 @@ struct hdac_stream { int delay_negative_threshold; 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, Loading Loading @@ -440,6 +450,42 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, (snd_hdac_stream_readb(dev, reg) & \ ~(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 */ Loading sound/hda/Kconfig +3 −0 Original line number Diff line number Diff line config SND_HDA_CORE tristate select REGMAP config SND_HDA_DSP_LOADER bool sound/hda/hdac_stream.c +113 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, azx_dev->index = idx; azx_dev->direction = direction; azx_dev->stream_tag = tag; snd_hdac_dsp_lock_init(azx_dev); list_add_tail(&azx_dev->list, &bus->stream_list); } EXPORT_SYMBOL_GPL(snd_hdac_stream_init); Loading Loading @@ -534,3 +535,115 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, } } 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 */ sound/pci/hda/Kconfig +0 −3 Original line number Diff line number Diff line Loading @@ -38,9 +38,6 @@ config SND_HDA_TEGRA if SND_HDA config SND_HDA_DSP_LOADER bool config SND_HDA_PREALLOC_SIZE int "Pre-allocated buffer size for HD-audio driver" range 0 32768 Loading Loading
include/sound/hdaudio.h +46 −0 Original line number Diff line number Diff line Loading @@ -187,6 +187,11 @@ struct hdac_io_ops { 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 Loading Loading @@ -374,6 +379,7 @@ struct hdac_stream { bool opened:1; bool running:1; bool no_period_wakeup:1; bool locked:1; /* timestamp */ unsigned long start_wallclk; /* start + minimum wallclk */ Loading @@ -383,6 +389,10 @@ struct hdac_stream { int delay_negative_threshold; 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, Loading Loading @@ -440,6 +450,42 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, (snd_hdac_stream_readb(dev, reg) & \ ~(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 */ Loading
sound/hda/Kconfig +3 −0 Original line number Diff line number Diff line config SND_HDA_CORE tristate select REGMAP config SND_HDA_DSP_LOADER bool
sound/hda/hdac_stream.c +113 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, azx_dev->index = idx; azx_dev->direction = direction; azx_dev->stream_tag = tag; snd_hdac_dsp_lock_init(azx_dev); list_add_tail(&azx_dev->list, &bus->stream_list); } EXPORT_SYMBOL_GPL(snd_hdac_stream_init); Loading Loading @@ -534,3 +535,115 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, } } 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 */
sound/pci/hda/Kconfig +0 −3 Original line number Diff line number Diff line Loading @@ -38,9 +38,6 @@ config SND_HDA_TEGRA if SND_HDA config SND_HDA_DSP_LOADER bool config SND_HDA_PREALLOC_SIZE int "Pre-allocated buffer size for HD-audio driver" range 0 32768 Loading