96 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			96 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  *  PCM DRM helpers | ||
|  |  * | ||
|  |  *   This program is free software; you can redistribute it and/or modify | ||
|  |  *   it under the terms of the GNU General Public License version 2 as | ||
|  |  *   published by the Free Software Foundation. | ||
|  |  */ | ||
|  | #include <linux/export.h>
 | ||
|  | #include <linux/types.h>
 | ||
|  | #include <sound/asoundef.h>
 | ||
|  | #include <sound/pcm.h>
 | ||
|  | #include <sound/pcm_iec958.h>
 | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status | ||
|  |  * @runtime: pcm runtime structure with ->rate filled in | ||
|  |  * @cs: channel status buffer, at least four bytes | ||
|  |  * @len: length of channel status buffer | ||
|  |  * | ||
|  |  * Create the consumer format channel status data in @cs of maximum size | ||
|  |  * @len corresponding to the parameters of the PCM runtime @runtime. | ||
|  |  * | ||
|  |  * Drivers may wish to tweak the contents of the buffer after creation. | ||
|  |  * | ||
|  |  * Returns: length of buffer, or negative error code if something failed. | ||
|  |  */ | ||
|  | int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, | ||
|  | 	size_t len) | ||
|  | { | ||
|  | 	unsigned int fs, ws; | ||
|  | 
 | ||
|  | 	if (len < 4) | ||
|  | 		return -EINVAL; | ||
|  | 
 | ||
|  | 	switch (runtime->rate) { | ||
|  | 	case 32000: | ||
|  | 		fs = IEC958_AES3_CON_FS_32000; | ||
|  | 		break; | ||
|  | 	case 44100: | ||
|  | 		fs = IEC958_AES3_CON_FS_44100; | ||
|  | 		break; | ||
|  | 	case 48000: | ||
|  | 		fs = IEC958_AES3_CON_FS_48000; | ||
|  | 		break; | ||
|  | 	case 88200: | ||
|  | 		fs = IEC958_AES3_CON_FS_88200; | ||
|  | 		break; | ||
|  | 	case 96000: | ||
|  | 		fs = IEC958_AES3_CON_FS_96000; | ||
|  | 		break; | ||
|  | 	case 176400: | ||
|  | 		fs = IEC958_AES3_CON_FS_176400; | ||
|  | 		break; | ||
|  | 	case 192000: | ||
|  | 		fs = IEC958_AES3_CON_FS_192000; | ||
|  | 		break; | ||
|  | 	default: | ||
|  | 		return -EINVAL; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (len > 4) { | ||
|  | 		switch (snd_pcm_format_width(runtime->format)) { | ||
|  | 		case 16: | ||
|  | 			ws = IEC958_AES4_CON_WORDLEN_20_16; | ||
|  | 			break; | ||
|  | 		case 18: | ||
|  | 			ws = IEC958_AES4_CON_WORDLEN_22_18; | ||
|  | 			break; | ||
|  | 		case 20: | ||
|  | 			ws = IEC958_AES4_CON_WORDLEN_20_16 | | ||
|  | 			     IEC958_AES4_CON_MAX_WORDLEN_24; | ||
|  | 			break; | ||
|  | 		case 24: | ||
|  | 			ws = IEC958_AES4_CON_WORDLEN_24_20 | | ||
|  | 			     IEC958_AES4_CON_MAX_WORDLEN_24; | ||
|  | 			break; | ||
|  | 
 | ||
|  | 		default: | ||
|  | 			return -EINVAL; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	memset(cs, 0, len); | ||
|  | 
 | ||
|  | 	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; | ||
|  | 	cs[1] = IEC958_AES1_CON_GENERAL; | ||
|  | 	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; | ||
|  | 	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs; | ||
|  | 
 | ||
|  | 	if (len > 4) | ||
|  | 		cs[4] = ws; | ||
|  | 
 | ||
|  | 	return len; | ||
|  | } | ||
|  | EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); |