mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 12:26:31 +01:00
Added IEC958 support for Cirrus Logic..
This commit is contained in:
parent
ec275f84ed
commit
6c20f0e73f
3 changed files with 113 additions and 10 deletions
|
@ -57,6 +57,19 @@ playback return L_PLAYBACK;
|
|||
record return L_RECORD;
|
||||
output return L_OUTPUT;
|
||||
input return L_INPUT;
|
||||
iec958ocs return L_IEC958OCS;
|
||||
3d return L_3D;
|
||||
reset return L_RESET;
|
||||
user return L_USER;
|
||||
valid return L_VALID;
|
||||
data return L_DATA;
|
||||
protected return L_PROTECTED;
|
||||
pre2 return L_PRE2;
|
||||
fslock return L_FSLOCK;
|
||||
type return L_TYPE;
|
||||
gstatus return L_GSTATUS;
|
||||
enable return L_ENABLE;
|
||||
disable return L_DISABLE;
|
||||
|
||||
/* boolean */
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ static void select_rawmidi_input_switch( char *name );
|
|||
|
||||
static void set_switch_boolean( int val );
|
||||
static void set_switch_integer( int val );
|
||||
static void set_switch_iec958ocs_begin( void );
|
||||
static void set_switch_iec958ocs( int idx, unsigned short val, unsigned short mask );
|
||||
|
||||
/* local variables */
|
||||
|
||||
|
@ -98,6 +100,8 @@ static void *Xswitch = NULL;
|
|||
/* other keywords */
|
||||
%token L_SOUNDCARD L_MIXER L_CHANNEL L_STEREO L_MONO L_SWITCH L_RAWDATA
|
||||
%token L_CONTROL L_PCM L_RAWMIDI L_PLAYBACK L_RECORD L_OUTPUT L_INPUT
|
||||
%token L_IEC958OCS L_3D L_RESET L_USER L_VALID L_DATA L_PROTECTED L_PRE2
|
||||
%token L_FSLOCK L_TYPE L_GSTATUS L_ENABLE L_DISABLE
|
||||
|
||||
%type <b_value> boolean
|
||||
%type <i_value> integer
|
||||
|
@ -208,9 +212,28 @@ switches : switch
|
|||
switch : L_TRUE { set_switch_boolean( 1 ); }
|
||||
| L_FALSE { set_switch_boolean( 0 ); }
|
||||
| L_INTEGER { set_switch_integer( $1 ); }
|
||||
| L_IEC958OCS '(' { set_switch_iec958ocs_begin(); } iec958ocs ')'
|
||||
| error { yyerror( "unknown keyword in switch() data parameter" ); }
|
||||
;
|
||||
|
||||
iec958ocs : iec958ocs1
|
||||
| iec958ocs iec958ocs1
|
||||
;
|
||||
|
||||
iec958ocs1 : L_ENABLE { set_switch_iec958ocs( 0, 1, 0 ); }
|
||||
| L_DISABLE { set_switch_iec958ocs( 0, 0, 0 ); }
|
||||
| L_3D { set_switch_iec958ocs( 4, 0x2000, ~0x2000 ); }
|
||||
| L_RESET { set_switch_iec958ocs( 4, 0x0040, ~0x0040 ); }
|
||||
| L_USER { set_switch_iec958ocs( 4, 0x0020, ~0x0020 ); }
|
||||
| L_VALID { set_switch_iec958ocs( 4, 0x0010, ~0x0010 ); }
|
||||
| L_DATA { set_switch_iec958ocs( 5, 0x0002, ~0x0002 ); }
|
||||
| L_PRE2 { set_switch_iec958ocs( 5, 0x0008, ~0x0018 ); }
|
||||
| L_FSLOCK { set_switch_iec958ocs( 5, 0x0020, ~0x0020 ); }
|
||||
| L_TYPE '(' integer ')' { set_switch_iec958ocs( 5, ($3 & 0x7f) << 6, ~(0x7f<<6) ); }
|
||||
| L_GSTATUS { set_switch_iec958ocs( 5, 0x2000, ~0x2000 ); }
|
||||
| error { yyerror( "unknown keyword in iec958ocs1() arguments" ); }
|
||||
;
|
||||
|
||||
boolean : L_TRUE { $$ = 1; }
|
||||
| L_FALSE { $$ = 0; }
|
||||
| error { yyerror( "unknown boolean value" ); }
|
||||
|
@ -434,3 +457,31 @@ static void set_switch_integer( int val )
|
|||
if ( memcmp( &sw -> value, &xx, sizeof(xx) ) ) *Xswitchchange = 1;
|
||||
memcpy( &sw -> value, &xx, sizeof(xx) );
|
||||
}
|
||||
|
||||
static void set_switch_iec958ocs_begin( void )
|
||||
{
|
||||
/* ok.. this is a little bit wrong, but at these times are all switches same */
|
||||
snd_ctl_switch_t *sw = (snd_ctl_switch_t *)Xswitch;
|
||||
|
||||
if ( Xswitchtype != SWITCH_MIXER || sw -> type != SND_MIXER_SW_TYPE_BOOLEAN ||
|
||||
!strcmp( sw -> name, SND_MIXER_SW_IEC958OUT ) )
|
||||
yyerror( "Switch '%s' cannot store IEC958 information for Cirrus Logic chips...", sw -> name );
|
||||
if ( sw -> value.data32[1] != (('C'<<8)|'S') )
|
||||
yyerror( "Switch '%s' doesn't have Cirrus Logic signature!!!", sw -> name );
|
||||
sw -> value.enable = 0;
|
||||
sw -> value.data16[4] = 0x0000;
|
||||
sw -> value.data16[5] = 0x0000;
|
||||
}
|
||||
|
||||
static void set_switch_iec958ocs( int idx, unsigned short val, unsigned short mask )
|
||||
{
|
||||
/* ok.. this is a little bit wrong, but at these times are all switches same */
|
||||
snd_ctl_switch_t *sw = (snd_ctl_switch_t *)Xswitch;
|
||||
|
||||
if ( idx == 0 ) {
|
||||
sw -> value.enable = val ? 1 : 0;
|
||||
return;
|
||||
}
|
||||
sw -> value.data16[ idx ] &= ~mask;
|
||||
sw -> value.data16[ idx ] |= val;
|
||||
}
|
||||
|
|
|
@ -528,7 +528,8 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign
|
|||
};
|
||||
char *s, v[16];
|
||||
struct data *pdata = (struct data *)data;
|
||||
int idx;
|
||||
int idx, first, switchok = 0;
|
||||
const char *space = " ";
|
||||
|
||||
v[0] = '\0';
|
||||
switch ( type ) {
|
||||
|
@ -540,10 +541,47 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign
|
|||
default:
|
||||
s = "unknown";
|
||||
}
|
||||
fprintf( out, " ; Type is '%s'.\n", s );
|
||||
fprintf( out, "%s; Type is '%s'.\n", space, s );
|
||||
if ( low != 0 || high != 0 )
|
||||
fprintf( out, " ; Accepted switch range is from %ui to %ui.\n", low, high );
|
||||
fprintf( out, " switch( \"%s\", %s", name, v );
|
||||
fprintf( out, "%s; Accepted switch range is from %ui to %ui.\n", space, low, high );
|
||||
if ( interface == SND_INTERFACE_CONTROL && type == SND_CTL_SW_TYPE_WORD &&
|
||||
!strcmp( name, SND_CTL_SW_JOYSTICK_ADDRESS ) ) {
|
||||
for ( idx = 1, first = 1; idx < 16; idx++ ) {
|
||||
if ( pdata -> data16[idx] ) {
|
||||
if ( first ) {
|
||||
fprintf( out, "%s; Available addresses - 0x%x", space, pdata -> data16[idx] );
|
||||
first = 0;
|
||||
} else {
|
||||
fprintf( out, ", 0x%x", pdata -> data16[idx] );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !first ) fprintf( out, "\n" );
|
||||
}
|
||||
fprintf( out, "%sswitch( \"%s\", ", space, name );
|
||||
if ( interface == SND_INTERFACE_MIXER && type == SND_MIXER_SW_TYPE_BOOLEAN &&
|
||||
!strcmp( name, SND_MIXER_SW_IEC958OUT ) ) {
|
||||
if ( pdata -> data16[0] == (('C'<<8)|'S') ) { /* Cirrus Crystal */
|
||||
switchok = 0;
|
||||
fprintf( out, "iec958ocs( %s", pdata -> enable ? "enable" : "disable" );
|
||||
if ( pdata -> data16[4] & 0x2000 ) fprintf( out, " 3d" );
|
||||
if ( pdata -> data16[4] & 0x0040 ) fprintf( out, " reset" );
|
||||
if ( pdata -> data16[4] & 0x0020 ) fprintf( out, " user" );
|
||||
if ( pdata -> data16[4] & 0x0010 ) fprintf( out, " valid" );
|
||||
if ( pdata -> data16[5] & 0x0002 ) fprintf( out, " data" );
|
||||
if ( !(pdata -> data16[5] & 0x0004) ) fprintf( out, " protected" );
|
||||
switch ( pdata -> data16[5] & 0x0018 ) {
|
||||
case 0x0008: fprintf( out, " pre2" ); break;
|
||||
default: break;
|
||||
}
|
||||
if ( pdata -> data16[5] & 0x0020 ) fprintf( out, " fslock" );
|
||||
fprintf( out, " type( 0x%x )", (pdata -> data16[5] >> 6) & 0x7f );
|
||||
if ( pdata -> data16[5] & 0x2000 ) fprintf( out, " gstatus" );
|
||||
fprintf( out, ")" );
|
||||
}
|
||||
}
|
||||
if ( !switchok ) {
|
||||
fprintf( out, v );
|
||||
if ( type < 0 || type > SND_CTL_SW_TYPE_DWORD ) {
|
||||
/* TODO: some well known types should be verbose */
|
||||
fprintf( out, " rawdata( " );
|
||||
|
@ -552,6 +590,7 @@ static void soundcard_setup_write_switch( FILE *out, int interface, const unsign
|
|||
}
|
||||
fprintf( out, "%02x@ )\n", pdata -> data8[31] );
|
||||
}
|
||||
}
|
||||
fprintf( out, " )\n" );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue