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:
		
							parent
							
								
									1475241272
								
							
						
					
					
						commit
						8f3f600b52
					
				| @ -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 | ||||
| @ -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 */ | ||||
| @ -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, | ||||
| @ -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 | ||||
|  */ | ||||
|  | ||||
| @ -1,3 +1,6 @@ | ||||
| config SND_HDA_CORE | ||||
| 	tristate | ||||
| 	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->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); | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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…
	
		Reference in New Issue
	
	Block a user