2015-05-09 13:26:47 +03:00
/*
* 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>
2016-03-31 16:35:58 +03:00
# include <sound/pcm_params.h>
2015-05-09 13:26:47 +03:00
# include <sound/pcm_iec958.h>
2016-03-31 16:35:58 +03:00
static int create_iec958_consumer ( uint rate , uint sample_width ,
u8 * cs , size_t len )
2015-05-09 13:26:47 +03:00
{
unsigned int fs , ws ;
if ( len < 4 )
return - EINVAL ;
2016-03-31 16:35:58 +03:00
switch ( rate ) {
2015-05-09 13:26:47 +03:00
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 ) {
2016-03-31 16:35:58 +03:00
switch ( sample_width ) {
2015-05-09 13:26:47 +03:00
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 :
2016-03-31 16:35:59 +03:00
case 32 : /* Assume 24-bit width for 32-bit samples. */
2015-05-09 13:26:47 +03:00
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 ;
}
2016-03-31 16:35:58 +03:00
/**
* 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 )
{
return create_iec958_consumer ( runtime - > rate ,
snd_pcm_format_width ( runtime - > format ) ,
cs , len ) ;
}
2015-05-09 13:26:47 +03:00
EXPORT_SYMBOL ( snd_pcm_create_iec958_consumer ) ;
2016-03-31 16:35:58 +03:00
/**
* snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status
* @ hw_params : the hw_params instance for extracting rate and sample format
* @ 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_hw_params ( struct snd_pcm_hw_params * params ,
u8 * cs , size_t len )
{
return create_iec958_consumer ( params_rate ( params ) , params_width ( params ) ,
cs , len ) ;
}
EXPORT_SYMBOL ( snd_pcm_create_iec958_consumer_hw_params ) ;