mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	pcm: softvol: add support for S24_LE
Tested with the Wolfson WM8524 DAC on a i.MX6UL board and the following
ALSA configuration file using the pcm test utility from alsa-lib:
"""
$ cat /etc/asound.conf
pcm.!default {
    type plug
    slave.pcm "softvol"
}
pcm.softvol {
    type softvol
    slave {
        pcm "hw:0"
    }
    control {
        name "Master"
        card 0
    }
}
ctl.!default {
    type hw
    card 0
}
ctl.softvol {
    type hw
    card 0
}
$ pcm -D softvol -o S24_LE -c 2 -r 48000
"""
The data in the Synchronous Audio Interface (SAI) of the i.MX6UL is
aligned the following way:
"""
31 30 29 28 | 27 26 25 24 | 23 22 21 20 | .. | 3 2 1 0
## ## ## ##   ## ## ## ## [           DATA[23:0]       ]
"""
Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
			
			
This commit is contained in:
		
							parent
							
								
									8d61695145
								
							
						
					
					
						commit
						6a617cc719
					
				
					 1 changed files with 53 additions and 3 deletions
				
			
		|  | @ -252,6 +252,44 @@ static inline short MULTI_DIV_short(short a, unsigned int b, int swap) | |||
| 	}								\ | ||||
| } while (0) | ||||
| 
 | ||||
| #define CONVERT_AREA_S24_LE() do {					\ | ||||
| 	unsigned int ch, fr;						\ | ||||
| 	int *src, *dst;							\ | ||||
| 	int tmp;							\ | ||||
| 	for (ch = 0; ch < channels; ch++) {				\ | ||||
| 		src_area = &src_areas[ch];				\ | ||||
| 		dst_area = &dst_areas[ch];				\ | ||||
| 		src = snd_pcm_channel_area_addr(src_area, src_offset);	\ | ||||
| 		dst = snd_pcm_channel_area_addr(dst_area, dst_offset);	\ | ||||
| 		src_step = snd_pcm_channel_area_step(src_area)		\ | ||||
| 				/ sizeof(int);				\ | ||||
| 		dst_step = snd_pcm_channel_area_step(dst_area)		\ | ||||
| 				/ sizeof(int);				\ | ||||
| 		GET_VOL_SCALE;						\ | ||||
| 		fr = frames;						\ | ||||
| 		if (! vol_scale) {					\ | ||||
| 			while (fr--) {					\ | ||||
| 				*dst = 0;				\ | ||||
| 				dst += dst_step;			\ | ||||
| 			}						\ | ||||
| 		} else if (vol_scale == 0xffff) {			\ | ||||
| 			while (fr--) {					\ | ||||
| 				*dst = *src;				\ | ||||
| 				src += dst_step;			\ | ||||
| 				dst += src_step;			\ | ||||
| 			}						\ | ||||
| 		} else {						\ | ||||
| 			while (fr--) {					\ | ||||
| 				tmp = *src << 8;			\ | ||||
| 				tmp = (signed int) tmp >> 8;		\ | ||||
| 				*dst = MULTI_DIV_24(tmp, vol_scale);	\ | ||||
| 				src += dst_step;			\ | ||||
| 				dst += src_step;			\ | ||||
| 			}						\ | ||||
| 		}							\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
| 		 | ||||
| #define GET_VOL_SCALE \ | ||||
| 	switch (ch) { \ | ||||
| 	case 0: \ | ||||
|  | @ -315,6 +353,10 @@ static void softvol_convert_stereo_vol(snd_pcm_softvol_t *svol, | |||
| 		CONVERT_AREA(int, | ||||
| 			     !snd_pcm_format_cpu_endian(svol->sformat)); | ||||
| 		break; | ||||
| 	case SND_PCM_FORMAT_S24_LE: | ||||
| 		/* 24bit samples */ | ||||
| 		CONVERT_AREA_S24_LE(); | ||||
| 		break; | ||||
| 	case SND_PCM_FORMAT_S24_3LE: | ||||
| 		CONVERT_AREA_S24_3LE(); | ||||
| 		break; | ||||
|  | @ -366,6 +408,10 @@ static void softvol_convert_mono_vol(snd_pcm_softvol_t *svol, | |||
| 		CONVERT_AREA(int, | ||||
| 			     !snd_pcm_format_cpu_endian(svol->sformat)); | ||||
| 		break; | ||||
| 	case SND_PCM_FORMAT_S24_LE: | ||||
| 		/* 24bit samples */ | ||||
| 		CONVERT_AREA_S24_LE(); | ||||
| 		break; | ||||
| 	case SND_PCM_FORMAT_S24_3LE: | ||||
| 		CONVERT_AREA_S24_3LE(); | ||||
| 		break; | ||||
|  | @ -422,6 +468,7 @@ static int snd_pcm_softvol_hw_refine_cprepare(snd_pcm_t *pcm, | |||
| 		{ | ||||
| 			(1ULL << SND_PCM_FORMAT_S16_LE) | | ||||
| 			(1ULL << SND_PCM_FORMAT_S16_BE) | | ||||
| 			(1ULL << SND_PCM_FORMAT_S24_LE) | | ||||
| 			(1ULL << SND_PCM_FORMAT_S32_LE) | | ||||
|  			(1ULL << SND_PCM_FORMAT_S32_BE), | ||||
| 			(1ULL << (SND_PCM_FORMAT_S24_3LE - 32)) | ||||
|  | @ -577,10 +624,11 @@ static int snd_pcm_softvol_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * param | |||
| 	if (slave->format != SND_PCM_FORMAT_S16_LE && | ||||
| 	    slave->format != SND_PCM_FORMAT_S16_BE && | ||||
| 	    slave->format != SND_PCM_FORMAT_S24_3LE &&  | ||||
| 	    slave->format != SND_PCM_FORMAT_S24_LE && | ||||
| 	    slave->format != SND_PCM_FORMAT_S32_LE && | ||||
| 	    slave->format != SND_PCM_FORMAT_S32_BE) { | ||||
| 		SNDERR("softvol supports only S16_LE, S16_BE, S24_3LE, S32_LE " | ||||
| 		       " or S32_BE"); | ||||
| 		SNDERR("softvol supports only S16_LE, S16_BE, S24_LE, S24_3LE, " | ||||
| 		       "S32_LE or S32_BE"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	svol->sformat = slave->format; | ||||
|  | @ -863,6 +911,7 @@ int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, | |||
| 	    sformat != SND_PCM_FORMAT_S16_LE && | ||||
| 	    sformat != SND_PCM_FORMAT_S16_BE && | ||||
| 	    sformat != SND_PCM_FORMAT_S24_3LE &&  | ||||
| 	    sformat != SND_PCM_FORMAT_S24_LE && | ||||
| 	    sformat != SND_PCM_FORMAT_S32_LE && | ||||
| 	    sformat != SND_PCM_FORMAT_S32_BE) | ||||
| 		return -EINVAL; | ||||
|  | @ -1082,9 +1131,10 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, | |||
| 		    sformat != SND_PCM_FORMAT_S16_LE && | ||||
| 		    sformat != SND_PCM_FORMAT_S16_BE && | ||||
| 		    sformat != SND_PCM_FORMAT_S24_3LE &&  | ||||
| 		    sformat != SND_PCM_FORMAT_S24_LE && | ||||
| 		    sformat != SND_PCM_FORMAT_S32_LE && | ||||
| 		    sformat != SND_PCM_FORMAT_S32_BE) { | ||||
| 			SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format is supported"); | ||||
| 			SNDERR("only S16_LE, S16_BE, S24_LE, S24_3LE, S32_LE or S32_BE format is supported"); | ||||
| 			snd_config_delete(sconf); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jörg Krause
						Jörg Krause